Updated gateway to new version.

This commit is contained in:
Erich Barnstedt 2017-04-20 11:56:34 +02:00
Родитель ea9fa8be43
Коммит 5d0eb53f03
48 изменённых файлов: 4585 добавлений и 1281 удалений

5
.gitignore поставляемый
Просмотреть файл

@ -14,3 +14,8 @@
/**/*.vc.db
/.vscode/**
/build/**
*.dll
*.so
*.pdb
/src/GatewayApp.NetCore/Logs
*.der

Просмотреть файл

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Azure.IoT.Gateway.SDK.NetCore</id>
<version>2017.03.27-beta</version>
<title>Azure IoT Gateway SDK for .Net Core</title>
<description>This package contains the Microsoft Azure IoT Gateway SDK targeting the .NET Core Framework</description>
<authors>Microsoft Corporation</authors>
<language>en-US</language>
<projectUrl>https://github.com/azure/azure-iot-gateway-sdk</projectUrl>
<licenseUrl>https://github.com/Azure/azure-iot-gateway-sdk/blob/master/License.txt</licenseUrl>
<tags>Microsoft Azure IoT Gateway SDK dotnetcore</tags>
</metadata>
<files>
<file src="bindings\dotnetcore\dotnet-core-binding\Microsoft.Azure.Devices.Gateway\bin\Debug\netstandard1.3\Microsoft.Azure.Devices.Gateway.dll" target="lib\netstandard1.3" />
<file src="bindings\dotnetcore\dotnet-core-binding\Microsoft.Azure.Devices.Gateway\bin\Debug\netstandard1.3\Microsoft.Azure.Devices.Gateway.pdb" target="lib\netstandard1.3" />
<file src="build\core\Debug\gateway.dll" target="runtimes\win-x86\native\gateway.dll" />
<file src="build\core\Debug\gateway.pdb" target="runtimes\win-x86\native\gateway.pdb" />
<file src="build\bindings\dotnetcore\Debug\dotnetcore.dll" target="runtimes\win-x86\native\dotnetcore.dll" />
<file src="build\bindings\dotnetcore\Debug\dotnetcore.pdb" target="runtimes\win-x86\native\dotnetcore.pdb" />
<file src="build\modules\iothub\Debug\iothub.dll" target="runtimes\win-x86\native\iothub.dll" />
<file src="build\modules\iothub\Debug\iothub.pdb" target="runtimes\win-x86\native\iothub.pdb" />
<file src="install-deps\bin\aziotsharedutil.dll" target="runtimes\win-x86\native\aziotsharedutil.dll" />
<file src="install-deps\bin\iothub_client.dll" target="runtimes\win-x86\native\iothub_client.dll" />
<file src="install-deps\bin\iothub_service_client.dll" target="runtimes\win-x86\native\iothub_service_client.dll" />
<file src="install-deps\bin\nanomsg.dll" target="runtimes\win-x86\native\nanomsg.dll" />
<file src="install-deps\bin\serializer.dll" target="runtimes\win-x86\native\serializer.dll" />
<file src="binariesfrompreviousbuild\gateway.dll" target="runtimes\win-x64\native\gateway.dll" />
<file src="binariesfrompreviousbuild\gateway.pdb" target="runtimes\win-x64\native\gateway.pdb" />
<file src="binariesfrompreviousbuild\dotnetcore.dll" target="runtimes\win-x64\native\dotnetcore.dll" />
<file src="binariesfrompreviousbuild\dotnetcore.pdb" target="runtimes\win-x64\native\dotnetcore.pdb" />
<file src="binariesfrompreviousbuild\iothub.dll" target="runtimes\win-x64\native\iothub.dll" />
<file src="binariesfrompreviousbuild\iothub.pdb" target="runtimes\win-x64\native\iothub.pdb" />
<file src="binariesfrompreviousbuild\aziotsharedutil.dll" target="runtimes\win-x64\native\aziotsharedutil.dll" />
<file src="binariesfrompreviousbuild\iothub_client.dll" target="runtimes\win-x64\native\iothub_client.dll" />
<file src="binariesfrompreviousbuild\iothub_service_client.dll" target="runtimes\win-x64\native\iothub_service_client.dll" />
<file src="binariesfrompreviousbuild\nanomsg.dll" target="runtimes\win-x64\native\nanomsg.dll" />
<file src="binariesfrompreviousbuild\serializer.dll" target="runtimes\win-x64\native\serializer.dll" />
<file src="binariesfromlinuxbuild\libgateway.so" target="runtimes\debian.8-x64\native\libgateway.so" />
<file src="binariesfromlinuxbuild\libdotnetcore.so" target="runtimes\debian.8-x64\native\libdotnetcore.so" />
<file src="binariesfromlinuxbuild\libiothub.so" target="runtimes\debian.8-x64\native\libiothub.so" />
<file src="binariesfromlinuxbuild\libaziotsharedutil.so" target="runtimes\debian.8-x64\native\libaziotsharedutil.so" />
<file src="binariesfromlinuxbuild\libiothub_client.so" target="runtimes\debian.8-x64\native\libiothub_client.so" />
<file src="binariesfromlinuxbuild\libiothub_service_client.so" target="runtimes\debian.8-x64\native\libiothub_service_client.so" />
<file src="binariesfromlinuxbuild\libnanomsg.so.5.0.0" target="runtimes\debian.8-x64\native\libnanomsg.so.5.0.0" />
<file src="binariesfromlinuxbuild\libserializer.so" target="runtimes\debian.8-x64\native\libserializer.so" />
<file src="binariesfromlinuxbuild\dotnet_core_module_sample.exe" target="runtimes\debian.8-x64\native\dotnet_core_module_sample.exe" />
</files>
</package>

Двоичный файл не отображается.

Просмотреть файл

@ -1,29 +1,13 @@
FROM microsoft/dotnet
FROM microsoft/dotnet:1.0-sdk-projectjson
ADD / /build/module
COPY / /build
RUN \
set -ex \
&& \
apt-get update && apt-get install -y \
build-essential \
libcurl4-openssl-dev \
git \
cmake \
libssl-dev \
valgrind \
uuid-dev \
libglib2.0-dev \
&& \
git clone --no-checkout https://github.com/Azure/azure-iot-gateway-sdk /build/gateway \
&& \
git -C /build/gateway checkout 287beed07490d98a24a4e9ddd33ec7127fc3acbf \
&& \
git -C /build/gateway submodule update --recursive --init \
&& \
bash /build/module/bld/build.sh -C Release -i /build/gateway -o /gateway \
&& \
ldconfig /gateway/Release
WORKDIR /build
RUN dotnet restore
WORKDIR /gateway/Release
ENTRYPOINT ["sample_gateway"]
WORKDIR /build/src/GatewayApp.NetCore
RUN dotnet publish
WORKDIR /build/src/GatewayApp.NetCore/bin/Debug/netcoreapp1.0/publish
ENV LD_LIBRARY_PATH=/build/src/GatewayApp.NetCore/bin/Debug/netcoreapp1.0/publish
ENTRYPOINT ["dotnet", "GatewayApp.NetCore.dll"]

Просмотреть файл

@ -1,4 +1,4 @@
Microsoft Azure IoT Gateway SDK OPC UA Client Module
Microsoft Azure IoT Gateway SDK OPC UA Publisher Module
Copyright (c) Microsoft Corporation
MIT license

Просмотреть файл

@ -11,6 +11,6 @@
<add key="nugetv2dotnet" value="https://www.nuget.org/api/v2/curated-feeds/microsoftdotnet/" />
<add key="nugetv3" value="https://api.nuget.org/v3/index.json" />
<!-- To enable LocalFeed for testing uncomment the following line -->
<add key="Local" value=".nuget" />
<!-- <add key="Local" value=".nuget" /> -->
</packageSources>
</configuration>

Просмотреть файл

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26228.4
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Opc.Ua.Client.Module", "src\Opc.Ua.Client.Module\Opc.Ua.Client.Module.csproj", "{43311AFB-D7C4-4E5A-B1DE-855407F90D1B}"
EndProject

Просмотреть файл

@ -0,0 +1,53 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "GatewayApp.NetCore", "src\GatewayApp.NetCore\GatewayApp.NetCore.xproj", "{592A483D-5F91-400E-B4EF-C25092143A4F}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Opc.Ua.Publisher.Module", "src\Opc.Ua.Publisher.Module\Opc.Ua.Publisher.Module.xproj", "{A1CC3B57-A186-4C3E-9E36-30A54A947369}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0E241D3D-7C66-4E4F-99AB-9FF5780180D1}"
ProjectSection(SolutionItems) = preProject
.travis.yml = .travis.yml
appveyor.yml = appveyor.yml
Dockerfile = Dockerfile
global.json = global.json
License.txt = License.txt
NuGet.Config = NuGet.Config
README.md = README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{C1D01774-05A6-4A39-AF58-9AE7760D619E}"
ProjectSection(SolutionItems) = preProject
.nuget\Azure.IoT.Gateway.SDK.NetCore.nuspec = .nuget\Azure.IoT.Gateway.SDK.NetCore.nuspec
EndProjectSection
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "IoTHubCredentialTools", "src\IoTHubCredentialTools\IoTHubCredentialTools.xproj", "{2605E447-DF6E-4FB8-B226-CD1DB643F186}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{592A483D-5F91-400E-B4EF-C25092143A4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{592A483D-5F91-400E-B4EF-C25092143A4F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{592A483D-5F91-400E-B4EF-C25092143A4F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{592A483D-5F91-400E-B4EF-C25092143A4F}.Release|Any CPU.Build.0 = Release|Any CPU
{A1CC3B57-A186-4C3E-9E36-30A54A947369}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A1CC3B57-A186-4C3E-9E36-30A54A947369}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A1CC3B57-A186-4C3E-9E36-30A54A947369}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A1CC3B57-A186-4C3E-9E36-30A54A947369}.Release|Any CPU.Build.0 = Release|Any CPU
{2605E447-DF6E-4FB8-B226-CD1DB643F186}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2605E447-DF6E-4FB8-B226-CD1DB643F186}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2605E447-DF6E-4FB8-B226-CD1DB643F186}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2605E447-DF6E-4FB8-B226-CD1DB643F186}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{C1D01774-05A6-4A39-AF58-9AE7760D619E} = {0E241D3D-7C66-4E4F-99AB-9FF5780180D1}
EndGlobalSection
EndGlobal

106
README.md
Просмотреть файл

@ -1,7 +1,9 @@
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
# OPC UA Publisher Module for the Azure IoT Gateway SDK
This reference implementation demonstrates how the Azure IoT Gateway SDK can be used to connect to existing OPC UA servers and send JSON encoded telemetry data from these servers in OPC UA "Pub/Sub" format (using a JSON payload) to Azure IoT Hub. All transport protocols supported by the Gateway SDK can be used, i.e. HTTPS, AMQP and MQTT. The transport is selected in the transport setting in gateway_config.json.
This reference implementation demonstrates how the Azure IoT Gateway SDK can be used to connect to existing OPC UA servers and publishes JSON encoded telemetry data from these servers in OPC UA "Pub/Sub" format (using a JSON payload) to Azure IoT Hub. All transport protocols supported by the Gateway SDK can be used, i.e. HTTPS, AMQP and MQTT. The transport is selected in the transport setting in the gatewayconfig.json file.
This module, apart from including an OPC UA *client* for connecting to existing OPC UA servers you have on your network, also includes an OPC UA *server* on port 62222 that can be used to configure the module.
This module uses the OPC Foundations's OPC UA reference stack and therefore licensing restrictions apply. Visit http://opcfoundation.github.io/UA-.NETStandardLibrary/ for OPC UA documentation and licensing terms.
@ -9,90 +11,50 @@ This module uses the OPC Foundations's OPC UA reference stack and therefore lice
|------|-------------|
|master|[![Build status](https://ci.appveyor.com/api/projects/status/6t7ru6ow7t9uv74r/branch/master?svg=true)](https://ci.appveyor.com/project/marcschier/iot-gateway-opc-ua-r4ba5/branch/master) [![Build Status](https://travis-ci.org/Azure/iot-gateway-opc-ua.svg?branch=master)](https://travis-ci.org/Azure/iot-gateway-opc-ua)|
# Azure IoT Gateway SDK compatibility
The current version of the Proxy module is targeted at the Azure IoT Gateway SDK at commit '287beed07490d98a24a4e9ddd33ec7127fc3acbf'.
Use the following command line to clone the compatible version Azure IoT Gateway SDK, then follow the build instructions included:
```
git clone --recursive https://github.com/Azure/azure-iot-gateway-sdk.git
git checkout 287beed07490d98a24a4e9ddd33ec7127fc3acbf
```
The gateway needs to be build with the ```--enable-dotnet-core-binding``` flag to enable it to run this module.
# Directory Structure
## /samples
This folder contains a sample configuration that instructs a vanilla gateway host load the module and IoT Hub proxy module and configures the module to create a
subscription on a standard server which publishes the current server time to Azure IoT Hub.
## /src
This folder contains the C# OPC UA module source file (Module.cs).
## /bld
This folder contains build scripts for Windows and Linux.
This folder contains the source code of the module, a managed gateway loader and a library to handle IoT Hub credentials.
# Building the Module
Run ```bld/build``` to build the module both Debug and Release. The published module can be found in ```build/release``` folder. Run the build script with the ```--help``` command line argument to see all build options.
The build system requires the latest .net Core command line tools to be installed (1.1.1 or later). On Windows, install Visual Studio 2017 with the dotnet core work load. On Linux, follow the instructions [here](https://www.microsoft.com/net/core#linuxubuntu).
This module requires the .NET Core SDK V1.0. You can build the module from Visual Studio 2015 by opening the solution file, right clicking the GatewayApp.NetCore project and selecting "publish". Alternatively, the module can be built from the command line with:
```
dotnet restore
dotnet publish .\src\GatewayApp.NetCore
```
# Configuring the Module
OPC UA nodes whose values should be published to Azure IoT Hub can be configured in the module JSON configuration. A sample template configuration file can be found in ```samples/gateway_config.json```. The configuration consists of a OPC-UA Application Configuration and Subscriptions section.
## Application Configuration section
The ```Configuration``` Section must contain at a minimum all items shown in the sample template. The JSON type conforms to the OPC UA reference stack serialization of the ```ApplicationConfiguration``` type.
E.g. to enable automatic certificate accept (discouraged), set ```"AutoAcceptUntrustedCertificates"``` to true (default is false) inside the ```SecurityConfiguration``` section:
``` JSON
"args": {
"Configuration": {
"ApplicationName": "Opc.Ua.Client.SampleModule",
"ApplicationType": "Client",
"ApplicationUri": "urn:localhost:OPCFoundation:SampleModule",
"SecurityConfiguration": {
"ApplicationCertificate": {},
"AutoAcceptUntrustedCertificates": true
},
The OPC UA nodes whose values should be published to Azure IoT Hub can be configured in the "publishednodes.json" file. It has the format:
```
[
{
"EndpointUrl": "opc.tcp://myopcservername:51210/UA/SampleServer",
"NodeId": { "Identifier": "ns=1;i=123" }
}
{
"EndpointUrl": "opc.tcp:// myopcservername:51210/UA/SampleServer",
"NodeId": { "Identifier": "ns=2;i=456" }
}
]
```
## Subscriptions section
The ```Subscriptions``` Section contains an array of OPC-UA sessions that the module should establish at startup, with each specifying a list of items to monitor. The ```MonitoredItems``` array type in the JSON configuration conforms to the OPC UA reference stack serialization specification of the same type.
# Configuring the Gateway
The ```Configuration``` Section must contain at a minimum all items shown in the provide file. The JSON type conforms to the OPC UA reference stack serialization of the ```ApplicationConfiguration``` type.
E.g. the sample template shows how to monitor the **Current Server Time** node (node ID 2258):
``` JSON
},
"Subscriptions": [
{
"Id": "<DeviceID>",
"SharedAccessKey": "<SharedAccessKey>",
"ServerUrl": "opc.tcp://<hostname>:51210/UA/SampleServer",
"MinimumSecurityLevel": 0,
"MinimumSecurityMode": "SignAndEncrypt",
"PublishingInterval": 400,
"MonitoredItems": [
{
"StartNodeId": "i=2258",
"NodeClass": 2,
"DisplayName": "ServerStatusCurrentTime",
"DiscardOldest": false
}
]
}
]
},
```
The JSON snippet above shows the default security settings, which can thus be ommitted. By default the session is created on the endpoint that supports ```SignAndEncrypt``` message mode, regardless of the security level advertised by the server (0). You can adjust these settings to customize the endpoint selection process, e.g. setting the Security mode to ```"Sign"``` will select all ```Sign``` and ```SignAndEncrypt``` endpoints, ```"None"``` will select all endpoints.
You should pass your application name and the IoT Hub owner connection string (which can be read out for your IoT Hub from portal.azure.com) as command line arguments. The IoT Hub owner connection string is only required for device registration with IoT Hub on first run.
# Running the module
To run the module and have it publish to IoT Hub, configure the name of your Hub (JSON field ```"IoTHubName"```) and the IoT Hub device ID and shared access key to use (JSON fields ```"Id"``` and ```"SharedAccessKey"```) in your version of ```gateway_config.json```. Note that if you use a "Mapping" module in your configuration, you can omit the ```"SharedAccessKey"``` field. Finally, ensure that the right native module is configured, based on your platform (i.e. iothub.dll for Windows, libiothub.so for Linux, etc.).
You can run the module on Windows along with the Gateway SDK and IoT Hub module directly via Visual Studio 2015 by hitting F5 (after publishing). Don't forget your command line arguments!
You can build a sample gateway host as part of the Azure IoT Gateway SDK build system. Ensure that you pass the ```--enable-dotnet-core-binding``` to the build script and use one of the resulting sample gateway hosts.
You can also run the module in a Docker container using the Dockerfile provided. From the root of the repo, in a console, type:
To simplify this step, and to build a sample gateway to host the OPC-UA module - along with the module itself - clone the gateway SDK repo to your device and run the build script with the ```-i <root-of-sdk>```. The resulting release folder will contain not just the module and managed dependencies, but also a native IoT Hub proxy module as well as a ```sample_gateway``` executable that you can pass the updated JSON configuration to.
```docker build -t gw .```
On first run, for one-time IoT Hub registration:
```docker run -it --rm gw <applicationName> <IoTHubOwnerConnectionString>```
From then on:
```docker run -it --rm gw <applicationName>```

Просмотреть файл

@ -1,271 +0,0 @@
@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 repo-root=%current-path%\..
rem // resolve to fully qualified path
for %%i in ("%repo-root%") do set repo-root=%%~fi
set build-sdk-root=%repo-root%\..\azure-iot-gateway-sdk
for %%i in ("%build-sdk-root%") do set build-sdk-root=%%~fi
rem ----------------------------------------------------------------------------
rem -- parse script arguments
rem ----------------------------------------------------------------------------
rem // default build options
set build-clean=
set build-configs=
set build-platform=Win32
if "%PROCESSOR_ARCHITECTURE%" == "AMD64" set build-platform=x64
set build-runtime=
set build-root=%repo-root%\build
set build-rel-root=%build-root%\release
:args-loop
if "%1" equ "" goto :args-done
if "%1" equ "--config" goto :arg-build-config
if "%1" equ "-C" goto :arg-build-config
if "%1" equ "--clean" goto :arg-build-clean
if "%1" equ "-c" goto :arg-build-clean
if "%1" equ "--output" goto :arg-build-rel-root
if "%1" equ "-o" goto :arg-build-rel-root
if "%1" equ "--sdk-root" goto :arg-sdk-root-folder
if "%1" equ "-i" goto :arg-sdk-root-folder
if "%1" equ "--platform" goto :arg-build-platform
if "%1" equ "-p" goto :arg-build-platform
if "%1" equ "--runtime" goto :arg-build-runtime
if "%1" equ "-r" goto :arg-build-runtime
call :usage && exit /b 1
:arg-build-clean
set build-clean=1
goto :args-continue
:arg-build-config
shift
if "%1" equ "" call :usage && exit /b 1
set build-configs=%build-configs%%1
goto :args-continue
:arg-sdk-root-folder
shift
if "%1" equ "" call :usage && exit /b 1
set build-sdk-root=%1
goto :args-continue
:arg-build-platform
shift
if "%1" equ "" call :usage && exit /b 1
set build-platform=%1
goto :args-continue
:arg-build-runtime
shift
if "%1" equ "" call :usage && exit /b 1
set build-runtime=-r %1
goto :args-continue
:arg-build-rel-root
shift
if "%1" equ "" call :usage && exit /b 1
set build-rel-root=%1
goto :args-continue
:args-continue
shift
goto :args-loop
:args-done
call dotnet --version
if not !ERRORLEVEL! == 0 echo No dotnet installed, install first... && exit /b 1
if not exist "%build-sdk-root%\tools\build.cmd" echo no sdk installed at %build-sdk-root%, only building module... && set build-sdk-root=
if "%build-configs%" == "" set build-configs=Release Debug
rem // Start script
echo Building %build-configs%...
if not "%build-clean%" == "" (
echo Cleaning previous build output...
call :rmdir-force %build-root%
)
if not exist %build-root% mkdir %build-root%
call :sdk-build
if not !ERRORLEVEL! == 0 echo Failures during sdk build... && exit /b !ERRORLEVEL!
call :module-build
if not !ERRORLEVEL! == 0 echo Failures during dotnet build... && exit /b !ERRORLEVEL!
call :release-all
if not !ERRORLEVEL! == 0 echo Failures building release... && exit /b !ERRORLEVEL!
goto :build-done
rem -----------------------------------------------------------------------------
rem -- build the sdk
rem -----------------------------------------------------------------------------
:sdk-build
if "%build-sdk-root%" == "" goto :eof
rem // Build the sdk for all configurations
for %%c in (%build-configs%) do (
pushd "%build-sdk-root%\tools
call :sdk-build-and-test %%c
popd
if not !ERRORLEVEL! == 0 exit /b !ERRORLEVEL!
)
goto :eof
rem // Build the sdk for 1 configuration
:sdk-build-and-test
if /I not "%~1" == "Release" if /I not "%~1" == "Debug" if /I not "%~1" == "MinSizeRel" if /I not "%~1" == "RelWithDebInfo" goto :eof
rem // If incremental, check if we had a successful build before...
if exist %build-root%\sdk\%build-platform%-%~1.done goto :eof
rem // Force clean cmake output and install-deps to avoid errors.
call :rmdir-force %build-sdk-root%\build
call :rmdir-force %build-sdk-root%\install-deps
rem // Build sdk
echo Building SDK (%~1) ...
call build.cmd --config %~1 --platform %build-platform% --enable-dotnet-core-binding --disable-ble-module
echo Finished building SDK (%~1)
if not !ERRORLEVEL! == 0 exit /b !ERRORLEVEL!
rem // Copy build output over and mark it as successfully built.
if not exist "%build-root%\sdk\%build-platform%\%~1" mkdir "%build-root%\sdk\%build-platform%\%~1"
xcopy /e /i /y /q "%build-sdk-root%\build" "%build-root%\sdk\%build-platform%\%~1"
if not !ERRORLEVEL! == 0 exit /b !ERRORLEVEL!
echo %~1 >> %build-root%\sdk\%build-platform%-%~1.done
goto :eof
rem -----------------------------------------------------------------------------
rem -- build module
rem -----------------------------------------------------------------------------
:module-build
rem // Clean
:dotnet-clean
if "%build-clean%" == "" goto :dotnet-build
call :dotnet-project-clean %repo-root%\src\Opc.Ua.Client.Module
call :dotnet-project-clean %repo-root%\bld\publish
rem // Build
:dotnet-build
if not !ERRORLEVEL! == 0 exit /b !ERRORLEVEL!
rem // Build and publish all specified configurations
for %%c in (%build-configs%) do (
call :dotnet-build-and-publish %%c
if not !ERRORLEVEL! == 0 exit /b !ERRORLEVEL!
)
goto :eof
rem // Build module and publish for 1 configuration
:dotnet-build-and-publish
if /I not "%~1" == "Release" if /I not "%~1" == "Debug" if /I not "%~1" == "Signed" goto :eof
pushd %repo-root%
rem // Restore packages
call dotnet restore
call dotnet build %build-runtime% -c %~1
popd
if not !ERRORLEVEL! == 0 exit /b !ERRORLEVEL!
rem // Publish all assemblies using publish dummy exe
pushd %repo-root%\bld\publish
rem // Restore packages
call dotnet restore
call dotnet publish %build-runtime% -c %~1 -o "%build-root%\module\%~1"
popd
if not !ERRORLEVEL! == 0 exit /b !ERRORLEVEL!
goto :eof
rem // Clean a project
:dotnet-project-clean
pushd "%~1"
call dotnet clean
popd
goto :eof
rem -----------------------------------------------------------------------------
rem -- Copy everything into a final release folder
rem -----------------------------------------------------------------------------
:release-all
for %%c in (%build-configs%) do (
call :release-binaries %%c
if not !ERRORLEVEL! == 0 exit /b !ERRORLEVEL!
)
goto :eof
:release-binaries
rem // Clean release folder
if not exist "%build-rel-root%\%~1" mkdir "%build-rel-root%\%~1"
del /f /q "%build-rel-root%\%~1\*"
rem // Flatten runtimes for windows (TODO: Should be done by loader)
xcopy /y /i /q "%build-root%\module\%~1" "%build-rel-root%\%~1"
pushd "%build-root%\module\%~1\runtimes\win"
for /f %%i in ('dir /b /s *.dll') do copy /y "%%i" "%build-rel-root%\%~1"
popd
pushd "%build-root%\module\%~1\runtimes\win7"
for /f %%i in ('dir /b /s *.dll') do copy /y "%%i" "%build-rel-root%\%~1"
popd
rem // Copy configuration json
copy /y "%repo-root%\samples\*.json" "%build-rel-root%\%~1"
if not !ERRORLEVEL! == 0 exit /b !ERRORLEVEL!
rem // Delete unnecessary publish.dll and .pdb
pushd "%build-rel-root%\%~1"
del /q /f publish.*
popd
if not !ERRORLEVEL! == 0 exit /b !ERRORLEVEL!
if "%build-sdk-root%" == "" goto :eof
if not !ERRORLEVEL! == 0 exit /b !ERRORLEVEL!
rem // Copy a sample gw host.exe, iothub.dll, iothub_client.dll
pushd %build-root%\sdk\%build-platform%\%~1
xcopy /e /y /i /q "samples\azure_functions_sample\%~1" "%build-rel-root%\%~1"
popd
if not !ERRORLEVEL! == 0 exit /b !ERRORLEVEL!
pushd %build-root%\sdk\%build-platform%\%~1
xcopy /e /y /i /q "samples\dotnet_core_module_sample\%~1" "%build-rel-root%\%~1"
popd
if not !ERRORLEVEL! == 0 exit /b !ERRORLEVEL!
pushd %build-root%\sdk\%build-platform%\%~1
xcopy /e /y /i /q "modules\iothub\%~1" "%build-rel-root%\%~1"
popd
if not !ERRORLEVEL! == 0 exit /b !ERRORLEVEL!
rem // rename sample host.exe and delete unneeded files
pushd "%build-rel-root%\%~1"
copy /y dotnet_core_module_sample.* sample_gateway.*
del /q /f dotnet_core_module_sample.*
del /q /f printermodule.*
del /q /f sensormodule.*
popd
if not !ERRORLEVEL! == 0 exit /b !ERRORLEVEL!
goto :eof
rem -----------------------------------------------------------------------------
rem -- subroutines
rem -----------------------------------------------------------------------------
:rmdir-force
set _attempt=0
:try-rmdir
if not exist %1 goto :done-rmdir
set /a _attempt+=1
if !_attempt! == 30 goto :done-rmdir
echo Removing %~1 (%_attempt%)...
rmdir /s /q %1
goto :try-rmdir
:done-rmdir
set _attempt=
goto :eof
:build-done
echo ... Success!
goto :eof
:usage
echo build.cmd [options]
echo options:
echo -c --clean Build clean (Removes previous build output).
echo -C --config ^<value^> [Debug, Release] build configuration
echo -r --runtime ^<value^> [win] The runtime to build module for.
echo -i --sdk-root ^<value^> [../azure-iot-gateway-sdk] Gateway SDK repo root.
echo -p --platform ^<value^> [Win32] build platform (e.g. Win32, x64, ...).
echo -o --output ^<value^> [/build/release] Root in which to place release.
goto :eof

Просмотреть файл

@ -1,204 +0,0 @@
#!/bin/bash
# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
set -e
repo_root=$(cd "$(dirname "$0")/.." && pwd)
skip_unittests=OFF
skip_dotnet=0
use_zlog=OFF
build_root="${repo_root}/build"
build_rel_root="${build_root}/release"
build_sdk_root="$(cd "$(dirname "$0")/../.." && pwd)/azure-iot-gateway-sdk"
build_clean=0
build_pack_only=0
build_configs=()
build_runtime=
usage ()
{
echo "build.sh [options]"
echo "options"
echo " -c --clean Build clean (Removes previous build output)."
echo " -C --config ^<value^> [Debug, Release] build configuration"
echo " -i --sdk-root ^<value^> [../azure-iot-gateway-sdk] Gateway SDK repo root."
echo " -o --output ^<value^> [/build/release] Root in which to place release."
echo " -x --xtrace print a trace of each command"
exit 1
}
# -----------------------------------------------------------------------------
# -- Parse arguments
# -----------------------------------------------------------------------------
process_args ()
{
save_next_arg=0
for arg in $*; do
if [ $save_next_arg == 1 ]; then
build_rel_root="$arg"
save_next_arg=0
elif [ $save_next_arg == 2 ]; then
build_configs+=("$arg")
save_next_arg=0
elif [ $save_next_arg == 3 ]; then
build_sdk_root="$arg"
save_next_arg=0
else
case "$arg" in
-x | --xtrace)
set -x;;
-o | --build-root)
save_next_arg=1;;
-C | --config)
save_next_arg=2;;
-c | --clean)
build_clean=1;;
-i | --sdk-root)
save_next_arg=3;;
*)
usage;;
esac
fi
done
if [ ! -e "${build_sdk_root}/tools/build.sh" ]; then
echo "No gateway sdk installed at ${build_sdk_root}... "
build_sdk_root=
fi
}
# -----------------------------------------------------------------------------
# -- build the sdk
# -----------------------------------------------------------------------------
sdk_build()
{
if [ -z "${build_sdk_root}" ]; then
echo "Skipping sdk build..."
else
echo -e "\033[1mBuilding sdk...\033[0m"
for c in ${build_configs[@]}; do
if [ -e "${build_root}/sdk/${c}.done" ]; then
echo "Skipping building sdk ${c}..."
else
echo -e "\033[1m ${c}...\033[0m"
mkdir -p "${build_root}/sdk/${c}"
rm -r -f "${build_sdk_root}/build" \
|| return 1
rm -r -f "${build_sdk_root}/install-deps" \
|| return 1
pushd ${build_sdk_root}/tools > /dev/null
( ./build.sh --config ${c} --enable-dotnet-core-binding --disable-ble-module ) \
|| return $build_error
popd > /dev/null
cp -r "${build_sdk_root}/build/"* "${build_root}/sdk/${c}" || \
return 1
echo "${c}" >> "${build_root}/sdk/${c}.done"
fi
done
fi
return 0
}
# -----------------------------------------------------------------------------
# -- build module and publish
# -----------------------------------------------------------------------------
module_build()
{
echo -e "\033[1mBuilding module...\033[0m"
for c in ${build_configs[@]}; do
echo -e "\033[1m ${c}...\033[0m"
mkdir -p "${build_root}/module/${c}"
pushd "${repo_root}/src/Opc.Ua.Client.Module" > /dev/null
dotnet restore \
|| return $?
dotnet build -c ${c} --framework netstandard1.6 \
|| return $?
popd > /dev/null
pushd "${repo_root}/bld/publish" > /dev/null
dotnet restore \
|| return $?
dotnet publish -c ${c} -o "${build_root}/module/${c}" --framework netcoreapp1.1 \
|| return $?
popd > /dev/null
done
return 0
}
# -----------------------------------------------------------------------------
# -- Copy everything into a final release folder
# -----------------------------------------------------------------------------
release_all()
{
for c in ${build_configs[@]}; do
rm -rf "${build_rel_root}/${c}"
mkdir -p "${build_rel_root}/${c}"
pushd "${build_root}/module/${c}" > /dev/null
cp * "${build_rel_root}/${c}" > /dev/null
find ./runtimes/unix -type f -print0 | xargs -0 -I%%% cp %%% "${build_rel_root}/${c}" || \
return 1
popd > /dev/null
pushd "${build_rel_root}/${c}" > /dev/null
rm -f publish.*
popd > /dev/null
if [ "${build_sdk_root}" ]; then
pushd "${build_root}/sdk/${c}" > /dev/null
find . -wholename *dotnetcore.so -type f -print0 | xargs -0 \
-I%%% cp %%% "${build_rel_root}/${c}" || \
return 1
find . -wholename *iothub*.so -type f -print0 | xargs -0 \
-I%%% cp %%% "${build_rel_root}/${c}" || \
return 1
find . -wholename *gateway*.so -type f -print0 | xargs -0 \
-I%%% cp %%% "${build_rel_root}/${c}" || \
return 1
find . -wholename *aziotsharedutil*.so -type f -print0 | xargs -0 \
-I%%% cp %%% "${build_rel_root}/${c}" || \
return 1
cp -r "samples/dotnet_core_module_sample/dotnet_core_module_sample" \
"${build_rel_root}/${c}/sample_gateway" || \
return 1
popd > /dev/null
fi
cp -r "${repo_root}/samples/"*.json "${build_rel_root}/${c}" || \
return 1
done
return 0
}
pushd "${repo_root}" > /dev/null
process_args $*
if [ -z "$build_configs" ]; then
build_configs=(Debug Release)
fi
echo "Building ${build_configs[@]}..."
if [ $build_clean == 1 ]; then
echo "Cleaning previous build output..."
rm -r -f "${build_root}"
fi
mkdir -p "${build_root}"
sdk_build || exit 1
module_build || exit 1
release_all || exit 1
popd > /dev/null
[ $? -eq 0 ] || exit $?

Просмотреть файл

@ -1,10 +0,0 @@
namespace Opc.Ua.Client
{
class Program
{
static void Main(string[] args)
{
var module = new SampleModule();
}
}
}

Просмотреть файл

@ -1,15 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<AssemblyName>publish</AssemblyName>
<OutputType>Exe</OutputType>
<PackageId>publish</PackageId>
<RuntimeFrameworkVersion>1.1.1</RuntimeFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Opc.Ua.Client.Module\Opc.Ua.Client.Module.csproj" />
</ItemGroup>
</Project>

3
global.json Normal file
Просмотреть файл

@ -0,0 +1,3 @@
{
"sdk": { "version": "1.0.0-preview2-003131" }
}

Просмотреть файл

@ -1,63 +0,0 @@
{
"modules": [
{
"name": "opc_ua",
"loader": {
"name": "dotnetcore",
"entrypoint": {
"assembly.name": "Opc.Ua.Client.Module",
"entry.type": "Opc.Ua.Client.SampleModule"
}
},
"args": {
"Configuration": {
"ApplicationName": "Opc.Ua.Client.SampleModule",
"ApplicationType": "Client",
"ApplicationUri": "urn:localhost:OPCFoundation:SampleModule",
"SecurityConfiguration": {
"ApplicationCertificate": {}
}
},
"Subscriptions": [
{
"Id": "<DeviceID>",
"SharedAccessKey": "<SharedAccessKey>",
"ServerUrl": "opc.tcp://<hostname>:51210/UA/SampleServer",
"MinimumSecurityLevel": 0,
"MinimumSecurityMode": "SignAndEncrypt",
"PublishingInterval": 400,
"MonitoredItems": [
{
"StartNodeId": "i=2258",
"NodeClass": 2,
"DisplayName": "ServerStatusCurrentTime",
"DiscardOldest": false
}
]
}
]
}
},
{
"name": "IoTHub",
"loader": {
"name": "native",
"entrypoint": {
"module.path": "<Choose: iothub.dll / libiothub.so>"
}
},
"args": {
"IoTHubName": "<IoTHubName>",
"IoTHubSuffix": "azure-devices.net",
"Transport": "AMQP"
}
}
],
"links": [
{
"source": "opc_ua",
"sink": "IoTHub"
}
]
}

Просмотреть файл

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>592a483d-5f91-400e-b4ef-c25092143a4f</ProjectGuid>
<RootNamespace>GatewayApp.NetCore</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<DnxInvisibleContent Include="aziotsharedutil.dll" />
<DnxInvisibleContent Include="dotnetcore.dll" />
<DnxInvisibleContent Include="dotnetcore.pdb" />
<DnxInvisibleContent Include="gateway.dll" />
<DnxInvisibleContent Include="gateway.pdb" />
<DnxInvisibleContent Include="iothub.dll" />
<DnxInvisibleContent Include="iothub.pdb" />
<DnxInvisibleContent Include="iothub_client.dll" />
<DnxInvisibleContent Include="iothub_service_client.dll" />
<DnxInvisibleContent Include="nanomsg.dll" />
<DnxInvisibleContent Include="serializer.dll" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

Просмотреть файл

@ -0,0 +1,179 @@

using System;
using System.IO;
using Microsoft.Azure.Devices.Gateway;
using IoTHubCredentialTools;
using System.Runtime.InteropServices;
using System.Collections.Generic;
namespace GatewayApp.NetCore
{
public class Program
{
public static void Main(string[] args)
{
// check for OSX, which we don't support
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
throw new NotSupportedException("OSX is not supported by the Gateway App on .Net Core");
}
// patch IoT Hub module DLL name
string gatewayConfigFile = "gatewayconfig.json";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Console.WriteLine("Target system is Linux.");
File.WriteAllText(gatewayConfigFile, File.ReadAllText(gatewayConfigFile).Replace("iothub.dll", "libiothub.so"));
}
else
{
Console.WriteLine("Target system is Windows.");
File.WriteAllText(gatewayConfigFile, File.ReadAllText(gatewayConfigFile).Replace("libiothub.so", "iothub.dll"));
}
// print target system info
if (IsX64Process())
{
Console.WriteLine("Target system is 64-bit.");
}
else
{
Console.WriteLine("Target system is 32-bit.");
throw new Exception("32-bit systems are currently not supported due to https://github.com/Azure/azure-iot-gateway-sdk/releases#known-issues");
}
// make sure our gateway runtime DLLs are in the current directory
string runtimesFolder = GetPathToRuntimesFolder(Directory.GetCurrentDirectory());
if (string.IsNullOrEmpty(runtimesFolder))
{
throw new Exception("Runtimes folder not found. Please make sure you have published the gateway app!");
}
// we always copy them across, overwriting existing ones, to make sure we have the right ones
string pathToNativeGatewayModules = runtimesFolder + Path.DirectorySeparatorChar + GetRuntimeID() + Path.DirectorySeparatorChar + "native";
List<string> filePaths = new List<string>(Directory.EnumerateFiles(pathToNativeGatewayModules));
foreach (string sourcefilePath in filePaths)
{
string destinationFilePath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + Path.GetFileName(sourcefilePath);
File.Copy(sourcefilePath, destinationFilePath, true);
}
// check if we got command line arguments to patch our gateway config file and register ourselves with IoT Hub
if ((args.Length > 0) && !string.IsNullOrEmpty(args[0]))
{
string applicationName = args[0];
File.WriteAllText(gatewayConfigFile, File.ReadAllText(gatewayConfigFile).Replace("<ReplaceWithYourApplicationName>", applicationName));
Console.WriteLine("Gateway config file patched with application name: " + applicationName);
// check if we also received an owner connection string to register ourselves with IoT Hub
if ((args.Length > 1) && !string.IsNullOrEmpty(args[1]))
{
string ownerConnectionString = args[1];
Console.WriteLine("Attemping to register ourselves with IoT Hub using owner connection string: " + ownerConnectionString);
string deviceConnectionString = IoTHubRegistration.RegisterDeviceWithIoTHub(applicationName, ownerConnectionString);
if (!string.IsNullOrEmpty(deviceConnectionString))
{
SecureIoTHubToken.Write(applicationName, deviceConnectionString);
}
else
{
Console.WriteLine("Could not register ourselves with IoT Hub using owner connection string: " + ownerConnectionString);
}
}
else
{
Console.WriteLine("IoT Hub owner connection string not passed as argument, registration with IoT Hub abandoned.");
}
// try to read connection string from secure store and patch gateway config file
Console.WriteLine("Attemping to read connection string from secure store with certificate name: " + applicationName);
string connectionString = SecureIoTHubToken.Read(applicationName);
if (!string.IsNullOrEmpty(connectionString))
{
Console.WriteLine("Attemping to configure publisher with connection string: " + connectionString);
string[] parsedConnectionString = IoTHubRegistration.ParseConnectionString(connectionString, true);
if ((parsedConnectionString != null) && (parsedConnectionString.Length == 3))
{
string _IoTHubName = parsedConnectionString[0];
if (_IoTHubName.Contains("."))
{
_IoTHubName = _IoTHubName.Substring(0, _IoTHubName.IndexOf('.'));
}
File.WriteAllText(gatewayConfigFile, File.ReadAllText(gatewayConfigFile).Replace("<ReplaceWithYourIoTHubName>", _IoTHubName));
Console.WriteLine("Gateway config file patched with IoT Hub name: " + _IoTHubName);
}
else
{
throw new Exception("Could not parse persisted device connection string!");
}
}
else
{
Console.WriteLine("Device connection string not found in secure store.");
}
}
else
{
Console.WriteLine("Application name not passed as argument, patching gateway config file abandoned");
}
IntPtr gateway = GatewayInterop.CreateFromJson(gatewayConfigFile);
if (gateway != IntPtr.Zero)
{
Console.WriteLine(".NET Core Gateway is running. Press enter to quit.");
Console.ReadLine();
GatewayInterop.Destroy(gateway);
}
else
{
Console.WriteLine(".NET Core Gateway failed to initialize.");
}
}
private static string GetPathToRuntimesFolder(string currentPath)
{
List<string> directories = new List<string>(Directory.EnumerateDirectories(currentPath));
foreach(string directoryPath in directories)
{
if (directoryPath.EndsWith("runtimes", StringComparison.OrdinalIgnoreCase))
{
return directoryPath;
}
string result = GetPathToRuntimesFolder(directoryPath);
if (result != null)
{
// found it
return result;
}
}
return null;
}
private static bool IsX64Process()
{
return (IntPtr.Size == 8);
}
private static string GetRuntimeID()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return "debian.8-x64";
}
else
{
if (IsX64Process())
{
return "win-x64";
}
else
{
return "win-x86";
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,23 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("GatewayApp.NetCore")]
[assembly: AssemblyTrademark("")]
// 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("592a483d-5f91-400e-b4ef-c25092143a4f")]
#if RELEASE_DELAY_SIGN
[assembly: AssemblyDelaySign(true)]
[assembly: AssemblyKeyFile("35MSSharedLib1024.snk")]
#endif

Просмотреть файл

@ -0,0 +1,19 @@
[cmdletbinding(SupportsShouldProcess=$true)]
param($publishProperties=@{}, $packOutput, $pubProfilePath)
# to learn more about this file visit https://go.microsoft.com/fwlink/?LinkId=524327
try{
if ($publishProperties['ProjectGuid'] -eq $null){
$publishProperties['ProjectGuid'] = '592a483d-5f91-400e-b4ef-c25092143a4f'
}
$publishModulePath = Join-Path (Split-Path $MyInvocation.MyCommand.Path) 'publish-module.psm1'
Import-Module $publishModulePath -DisableNameChecking -Force
# call Publish-AspNet to perform the publish operation
Publish-AspNet -publishProperties $publishProperties -packOutput $packOutput -pubProfilePath $pubProfilePath
}
catch{
"An error occurred during publish.`n{0}" -f $_.Exception.Message | Write-Error
}

Просмотреть файл

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit http://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<LastUsedBuildConfiguration>Debug</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<ExcludeApp_Data>False</ExcludeApp_Data>
<PublishFramework>netcoreapp1.0</PublishFramework>
<PublishRuntime>win-x64</PublishRuntime>
<UsePowerShell>True</UsePowerShell>
<publishUrl>.\bin\Debug\netcoreapp1.0\publish</publishUrl>
<DeleteExistingFiles>False</DeleteExistingFiles>
</PropertyGroup>
</Project>

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,41 @@
{
"modules": [
{
"name": "OpcUa",
"loader": {
"name": "dotnetcore",
"entrypoint": {
"assembly.name": "Opc.Ua.Publisher.Module",
"entry.type": "Opc.Ua.Publisher.Module"
}
},
"args": {
"Configuration": {
"ApplicationName": "<ReplaceWithYourApplicationName>",
"ApplicationType": "ClientAndServer",
"ApplicationUri": "urn:localhost:microsoft:publisher"
}
}
},
{
"name": "IoTHub",
"loader": {
"name": "native",
"entrypoint": {
"module.path": "iothub.dll"
}
},
"args": {
"IoTHubName": "<ReplaceWithYourIoTHubName>",
"IoTHubSuffix": "azure-devices.net",
"Transport": "AMQP"
}
}
],
"links": [
{
"source": "OpcUa",
"sink": "IoTHub"
}
]
}

Просмотреть файл

@ -0,0 +1,31 @@
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true
},
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"Opc.Ua.Publisher.Module": "1.0.0-*",
"Azure.IoT.Gateway.SDK.NetCore": "2017.3.27-beta"
},
"frameworks": {
"netcoreapp1.0": {}
},
"publishOptions": {
"include": [
"gatewayconfig.json"
]
},
"runtimes": {
"win-x64": {},
"win-x86": {},
"debian.8-x64": {}
}
}

Двоичные данные
src/IoTHubCredentialTools/35MSSharedLib1024.snk Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>2605e447-df6e-4fb8-b226-cd1db643f186</ProjectGuid>
<RootNamespace>IoTHubCredentialTools</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

Просмотреть файл

@ -0,0 +1,175 @@

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace IoTHubCredentialTools
{
public class IoTHubRegistration
{
public const string _IoTHubAPIVersion = "?api-version=2016-11-14";
/// <summary>
/// Returns an array of the parsed parts of a connection string
/// </summary>
public static string[] ParseConnectionString(string connectionString, bool isDevice)
{
string[] connectionStringParts = connectionString.Split(';');
if (connectionStringParts.Length == 3)
{
if (connectionStringParts[0].StartsWith("HostName="))
{
connectionStringParts[0] = connectionStringParts[0].Substring(connectionStringParts[0].IndexOf('=') + 1);
}
else
{
return null;
}
if (connectionStringParts[1].StartsWith("DeviceId=") && (isDevice == true))
{
connectionStringParts[1] = connectionStringParts[1].Substring(connectionStringParts[1].IndexOf('=') + 1);
}
else if (connectionStringParts[1].StartsWith("SharedAccessKeyName=") && (isDevice == false))
{
connectionStringParts[1] = connectionStringParts[1].Substring(connectionStringParts[1].IndexOf('=') + 1);
}
else
{
return null;
}
if (connectionStringParts[2].StartsWith("SharedAccessKey="))
{
connectionStringParts[2] = connectionStringParts[2].Substring(connectionStringParts[2].IndexOf('=') + 1);
}
else
{
return null;
}
return connectionStringParts;
}
else
{
return null;
}
}
/// <summary>
/// Creates a device in the IoT Hub device registry using the IoT Hub REST API
/// </summary>
public static async Task<string> CreateDeviceInIoTHubDeviceRegistry(HttpClient httpClient, string deviceName)
{
// check if device already registered
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "/devices/" + deviceName + _IoTHubAPIVersion);
HttpResponseMessage response = await httpClient.SendAsync(request).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
// already registered, delete existing device first
request = new HttpRequestMessage(HttpMethod.Delete, "/devices/" + deviceName + _IoTHubAPIVersion);
request.Headers.IfMatch.Add(new EntityTagHeaderValue("\"*\""));
response = await httpClient.SendAsync(request).ConfigureAwait(false);
if (!response.IsSuccessStatusCode)
{
throw new Exception("Delete device failed with " + response.Content.ReadAsStringAsync().Result);
}
}
// now create a new one
string jsonMessage = "{\"deviceId\": \"" + deviceName + "\"}";
request = new HttpRequestMessage(HttpMethod.Put, "/devices/" + deviceName + _IoTHubAPIVersion)
{
Content = new StringContent(jsonMessage, Encoding.ASCII, "application/json")
};
response = await httpClient.SendAsync(request).ConfigureAwait(false);
if (!response.IsSuccessStatusCode)
{
throw new Exception("Create device failed with " + response.Content.ReadAsStringAsync().Result);
}
string result = response.Content.ReadAsStringAsync().Result;
if (result.Contains("primaryKey"))
{
const string keyIdentifier = "\"primaryKey\":\"";
const int keylength = 44;
return result.Substring(result.IndexOf(keyIdentifier) + keyIdentifier.Length, keylength);
}
else
{
throw new Exception("Could not find primary key in response: " + response.Content.ReadAsStringAsync().Result);
}
}
/// <summary>
/// Registers a device with IoT Hub
/// </summary>
public static string RegisterDeviceWithIoTHub(string deviceName, string IoTHubOwnerConnectionString)
{
string[] parsedConnectionString = ParseConnectionString(IoTHubOwnerConnectionString, false);
string deviceConnectionString = string.Empty;
if ((parsedConnectionString != null) && (parsedConnectionString.Length == 3))
{
string IoTHubName = parsedConnectionString[0];
string name = parsedConnectionString[1];
string accessToken = parsedConnectionString[2];
using (HttpClient httpClient = new HttpClient())
{
httpClient.BaseAddress = new UriBuilder { Scheme = "https", Host = IoTHubName }.Uri;
string sharedAccessSignature = GenerateSharedAccessToken(name, Convert.FromBase64String(accessToken), IoTHubName, 60000);
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SharedAccessSignature", sharedAccessSignature);
deviceConnectionString = CreateDeviceInIoTHubDeviceRegistry(httpClient, deviceName.Replace(" ", "")).Result;
// prepend the rest of the connection string
deviceConnectionString = "HostName=" + IoTHubName + ";DeviceId=" + deviceName.Replace(" ", "") + ";SharedAccessKey=" + deviceConnectionString;
return deviceConnectionString;
}
}
else
{
throw new Exception("Could not parse IoT Hub owner connection string: " + IoTHubOwnerConnectionString);
}
}
/// <summary>
/// Sas token generation
/// </summary>
/// <param name="keyName"></param>
/// <param name="key"></param>
/// <param name="tokenScope"></param>
/// <param name="ttl"></param>
/// <returns>shared access token</returns>
public static string GenerateSharedAccessToken(string keyName, byte[] key, string tokenScope, int ttl)
{
// http://msdn.microsoft.com/en-us/library/azure/dn170477.aspx
// signature is computed from joined encoded request Uri string and expiry string
DateTime expiryTime = DateTime.UtcNow + TimeSpan.FromMilliseconds(ttl);
string expiry = ((long)(expiryTime - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds).ToString();
string encodedScope = Uri.EscapeDataString(tokenScope);
string sig;
// the connection string signature is base64 encoded
using (var hmac = new HMACSHA256(key))
{
sig = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(encodedScope + "\n" + expiry)));
}
return string.Format(
"sr={0}&sig={1}&se={2}&skn={3}",
encodedScope,
Uri.EscapeDataString(sig),
Uri.EscapeDataString(expiry),
Uri.EscapeDataString(keyName)
);
}
}
}

Просмотреть файл

@ -0,0 +1,23 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("IoTHubCredentialTools")]
[assembly: AssemblyTrademark("")]
// 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("9B381BFA-6061-402F-8A04-8456EB9AE59E")]
#if RELEASE_DELAY_SIGN
[assembly: AssemblyDelaySign(true)]
[assembly: AssemblyKeyFile("35MSSharedLib1024.snk")]
#endif

Просмотреть файл

@ -0,0 +1,192 @@

using System;
using System.IO;
using System.Collections;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Operators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509;
using System.Text;
namespace IoTHubCredentialTools
{
public class SecureIoTHubToken
{
public static string Read(string name)
{
// load an existing key from a no-expired cert with the subject name passed in from the OS-provided X509Store
using (X509Store store = new X509Store("IoTHub", StoreLocation.CurrentUser))
{
store.Open(OpenFlags.ReadOnly);
foreach (X509Certificate2 cert in store.Certificates)
{
if ((cert.SubjectName.Decode(X500DistinguishedNameFlags.None | X500DistinguishedNameFlags.DoNotUseQuotes).Equals("CN=" + name, StringComparison.OrdinalIgnoreCase)) &&
(DateTime.Now < cert.NotAfter))
{
using (RSA rsa = cert.GetRSAPrivateKey())
{
if (rsa != null)
{
foreach (System.Security.Cryptography.X509Certificates.X509Extension extension in cert.Extensions)
{
// check for instruction code extension
if ((extension.Oid.Value == "2.5.29.23") && (extension.RawData.Length >= 4))
{
byte[] bytes = new byte[extension.RawData.Length - 4];
Array.Copy(extension.RawData, 4, bytes, 0, bytes.Length);
byte[] token = rsa.Decrypt(bytes, RSAEncryptionPadding.OaepSHA1);
return Encoding.ASCII.GetString(token);
}
}
}
}
}
}
}
return null;
}
public static void Write(string name, string connectionString)
{
if (string.IsNullOrEmpty(connectionString))
{
throw new ArgumentException("Token not found in X509Store and no new token provided!");
}
SecureRandom random = new SecureRandom();
KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, 2048);
RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator();
keyPairGenerator.Init(keyGenerationParameters);
AsymmetricCipherKeyPair keys = keyPairGenerator.GenerateKeyPair();
ArrayList nameOids = new ArrayList();
nameOids.Add(X509Name.CN);
ArrayList nameValues = new ArrayList();
nameValues.Add(name);
X509Name subjectDN = new X509Name(nameOids, nameValues);
X509Name issuerDN = subjectDN;
X509V3CertificateGenerator cg = new X509V3CertificateGenerator();
cg.SetSerialNumber(BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random));
cg.SetIssuerDN(issuerDN);
cg.SetSubjectDN(subjectDN);
cg.SetNotBefore(DateTime.Now);
cg.SetNotAfter(DateTime.Now.AddMonths(12));
cg.SetPublicKey(keys.Public);
// encrypt the token with the public key so only the owner of the assoc. private key can decrypt it and
// "hide" it in the instruction code cert extension
RSA rsa = RSA.Create();
RSAParameters rsaParams = new RSAParameters();
RsaKeyParameters keyParams = (RsaKeyParameters)keys.Public;
rsaParams.Modulus = new byte[keyParams.Modulus.ToByteArrayUnsigned().Length];
keyParams.Modulus.ToByteArrayUnsigned().CopyTo(rsaParams.Modulus, 0);
rsaParams.Exponent = new byte[keyParams.Exponent.ToByteArrayUnsigned().Length];
keyParams.Exponent.ToByteArrayUnsigned().CopyTo(rsaParams.Exponent, 0);
rsa.ImportParameters(rsaParams);
if (rsa != null)
{
byte[] bytes = rsa.Encrypt(Encoding.ASCII.GetBytes(connectionString), RSAEncryptionPadding.OaepSHA1);
if (bytes != null)
{
cg.AddExtension(X509Extensions.InstructionCode, false, bytes);
}
else
{
rsa.Dispose();
throw new CryptographicException("Could not encrypt IoTHub security token using generated public key!");
}
}
rsa.Dispose();
// sign the cert with the private key
ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA256WITHRSA", keys.Private, random);
Org.BouncyCastle.X509.X509Certificate x509 = cg.Generate(signatureFactory);
// create a PKCS12 store for the cert and its private key
X509Certificate2 certificate = null;
using (MemoryStream pfxData = new MemoryStream())
{
Pkcs12Store pkcsStore = new Pkcs12StoreBuilder().Build();
X509CertificateEntry[] chain = new X509CertificateEntry[1];
string passcode = "passcode";
chain[0] = new X509CertificateEntry(x509);
pkcsStore.SetKeyEntry(name, new AsymmetricKeyEntry(keys.Private), chain);
pkcsStore.Save(pfxData, passcode.ToCharArray(), random);
// create X509Certificate2 object from PKCS12 file
certificate = CreateCertificateFromPKCS12(pfxData.ToArray(), passcode);
// Add to X509Store
using (X509Store store = new X509Store("IoTHub", StoreLocation.CurrentUser))
{
store.Open(OpenFlags.ReadWrite);
// remove any existing cert with our name from the store
foreach (X509Certificate2 cert in store.Certificates)
{
if (cert.SubjectName.Decode(X500DistinguishedNameFlags.None | X500DistinguishedNameFlags.DoNotUseQuotes).Equals("CN=" + name, StringComparison.OrdinalIgnoreCase))
{
store.Remove(cert);
}
}
// add new one
store.Add(certificate);
}
}
}
private static X509Certificate2 CreateCertificateFromPKCS12(byte[] rawData, string password)
{
Exception ex = null;
int flagsRetryCounter = 0;
X509Certificate2 certificate = null;
X509KeyStorageFlags[] storageFlags = {
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.UserKeySet,
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet
};
// try some combinations of storage flags, support is platform dependent
while (certificate == null &&
flagsRetryCounter < storageFlags.Length)
{
try
{
// merge first cert with private key into X509Certificate2
certificate = new X509Certificate2(
rawData,
(password == null) ? String.Empty : password,
storageFlags[flagsRetryCounter]);
// can we really access the private key?
using (RSA rsa = certificate.GetRSAPrivateKey()) { }
}
catch (Exception e)
{
ex = e;
certificate = null;
}
flagsRetryCounter++;
}
if (certificate == null)
{
throw new NotSupportedException("Creating X509Certificate from PKCS #12 store failed", ex);
}
return certificate;
}
}
}

Просмотреть файл

@ -0,0 +1,13 @@
{
"version": "1.0.0-*",
"dependencies": {
"NETStandard.Library": "1.6.0",
"Portable.BouncyCastle": "1.8.1.2",
"System.Collections.NonGeneric": "4.3.0"
},
"frameworks": {
"netstandard1.3": {}
}
}

Просмотреть файл

@ -1,563 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Opc.Ua.Client
{
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Runtime.Serialization;
using System.Text;
using Newtonsoft.Json;
using Microsoft.Azure.Devices.Gateway;
using Ua;
using System.Security.Cryptography.X509Certificates;
/// <summary>
/// Sample Gateway module - acts as Opc.Ua publisher and publishing server
/// </summary>
public class SampleModule : IGatewayModule, IGatewayModuleStart
{
/// <summary>
/// Create module, throws if configuration is bad
/// </summary>
/// <param name="broker"></param>
/// <param name="configuration"></param>
public void Create(Broker broker, byte[] configuration)
{
_broker = broker;
string configString = Encoding.UTF8.GetString(configuration);
// Deserialize from configuration string
_configuration = JsonConvert.DeserializeObject<SampleConfiguration>(configString);
foreach (var session in _configuration.Subscriptions)
{
session.Module = this;
}
Console.WriteLine("Opc.Ua.Client.SampleModule: created.");
}
/// <summary>
/// Disconnect and dispose all sessions
/// </summary>
public void Destroy()
{
foreach (var session in _configuration.Subscriptions)
{
// Disconnect and dispose
session.Dispose();
}
// Then gc.
_configuration.Subscriptions.Clear();
Console.WriteLine("Opc.Ua.Client.SampleModule: destroyed.");
}
/// <summary>
/// Receive message from broker
/// </summary>
/// <param name="received_message"></param>
public void Receive(Message received_message)
{
// No-op
}
/// <summary>
/// Publish message to bus
/// </summary>
/// <param name="message"></param>
public void Publish(Message message)
{
if (_broker != null)
{
_broker.Publish(message);
}
}
/// <summary>
/// Called when gateway starts, establishes the connections to endpoints
/// </summary>
public void Start()
{
Console.WriteLine("Opc.Ua.Client.SampleModule: starting...");
var connections = new List<Task>();
foreach (var session in _configuration.Subscriptions)
{
connections.Add(session.EndpointConnect());
}
try
{
Task.WaitAll(connections.ToArray());
}
catch (AggregateException ae)
{
foreach (var ex in ae.InnerExceptions)
{
Console.WriteLine($"Opc.Ua.Client.SampleModule: Could not connect {ex.ToString()}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Opc.Ua.Client.SampleModule: Could not connect {ex.ToString()}");
}
// Wait for all sessions to be connected
Console.WriteLine("Opc.Ua.Client.SampleModule: started.");
}
/// <summary>
/// Allow access to the opc ua configuration
/// </summary>
internal ApplicationConfiguration Configuration
{
get
{
return _configuration.Configuration;
}
}
private Broker _broker;
private SampleConfiguration _configuration;
}
/// <summary>
/// Module configuration object to deserialize / serialize
/// </summary>
[JsonObject(MemberSerialization.OptIn)]
public class SampleConfiguration
{
/// <summary>
/// Opc client configuration
/// </summary>
[JsonProperty]
public ApplicationConfiguration Configuration { get; set; }
/// <summary>
/// List of sessions to create on startup
/// </summary>
[JsonProperty]
public List<ServerSession> Subscriptions { get; set; }
/// <summary>
/// Called when the object is deserialized
/// </summary>
/// <param name="context"></param>
[OnDeserialized]
internal void OnDeserializedMethod(StreamingContext context)
{
// Validate configuration and set reasonable defaults
Configuration.ApplicationUri = Configuration.ApplicationUri.Replace("localhost", Utils.GetHostName());
if (Configuration.TransportQuotas == null)
Configuration.TransportQuotas = new TransportQuotas { OperationTimeout = 15000 };
if (Configuration.ClientConfiguration == null)
Configuration.ClientConfiguration = new ClientConfiguration();
if (Configuration.ServerConfiguration == null)
Configuration.ServerConfiguration = new ServerConfiguration();
if (Configuration.SecurityConfiguration.TrustedPeerCertificates == null)
Configuration.SecurityConfiguration.TrustedPeerCertificates = new CertificateTrustList();
if (Configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType == null)
Configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType =
"Directory";
if (Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath == null)
Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath =
"OPC Foundation/CertificateStores/UA Applications";
if (Configuration.SecurityConfiguration.TrustedIssuerCertificates == null)
Configuration.SecurityConfiguration.TrustedIssuerCertificates = new CertificateTrustList();
if (Configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType == null)
Configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType =
"Directory";
if (Configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath == null)
Configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath =
"OPC Foundation/CertificateStores/UA Certificate Authorities";
if (Configuration.SecurityConfiguration.RejectedCertificateStore == null)
Configuration.SecurityConfiguration.RejectedCertificateStore = new CertificateTrustList();
if (Configuration.SecurityConfiguration.RejectedCertificateStore.StoreType == null)
Configuration.SecurityConfiguration.RejectedCertificateStore.StoreType =
"Directory";
if (Configuration.SecurityConfiguration.RejectedCertificateStore.StorePath == null)
Configuration.SecurityConfiguration.RejectedCertificateStore.StorePath =
"OPC Foundation/CertificateStores/RejectedCertificates";
if (Configuration.SecurityConfiguration.ApplicationCertificate == null)
Configuration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier();
if (Configuration.SecurityConfiguration.ApplicationCertificate.StoreType == null)
Configuration.SecurityConfiguration.ApplicationCertificate.StoreType =
"X509Store";
if (Configuration.SecurityConfiguration.ApplicationCertificate.StorePath == null)
Configuration.SecurityConfiguration.ApplicationCertificate.StorePath =
"CurrentUser\\UA_MachineDefault";
if (Configuration.SecurityConfiguration.ApplicationCertificate.SubjectName == null)
Configuration.SecurityConfiguration.ApplicationCertificate.SubjectName =
Configuration.ApplicationName;
Configuration.Validate(Configuration.ApplicationType).Wait();
if (Configuration.SecurityConfiguration.ApplicationCertificate.Certificate == null)
{
X509Certificate2 certificate = CertificateFactory.CreateCertificate(
Configuration.SecurityConfiguration.ApplicationCertificate.StoreType,
Configuration.SecurityConfiguration.ApplicationCertificate.StorePath,
Configuration.ApplicationUri,
Configuration.ApplicationName,
Configuration.SecurityConfiguration.ApplicationCertificate.SubjectName
);
Configuration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate;
}
if (Configuration.SecurityConfiguration.ApplicationCertificate.Certificate != null)
{
Configuration.ApplicationUri = Utils.GetApplicationUriFromCertificate(
Configuration.SecurityConfiguration.ApplicationCertificate.Certificate);
}
else
{
Console.WriteLine("Opc.Ua.Client.SampleModule: WARNING: missing application certificate, using unsecure connection.");
}
if (Configuration.SecurityConfiguration.AutoAcceptUntrustedCertificates)
Configuration.CertificateValidator.CertificateValidation +=
new CertificateValidationEventHandler(CertificateValidator_CertificateValidation);
}
/// <summary>
/// Auto accept certificates
/// </summary>
/// <param name="validator"></param>
/// <param name="e"></param>
private void CertificateValidator_CertificateValidation(CertificateValidator validator, CertificateValidationEventArgs e)
{
if (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted)
{
e.Accept = true;
Console.WriteLine($"Opc.Ua.Client.SampleModule: WARNING: Auto-accepting certificate: {e.Certificate.Subject}");
}
}
}
/// <summary>
/// A server session contains a subscription for a list of monitored items
/// </summary>
[JsonObject(MemberSerialization.OptIn)]
public class ServerSession : IDisposable
{
/// <summary>
/// Url of the Server to connect to
/// </summary>
[JsonProperty]
public Uri ServerUrl { get; set; }
/// <summary>
/// SharedAccessKey for device
///
/// TODO: Security: The shared access key should be stored in secure storage,
/// and the device ID can be used as a lookup
/// </summary>
[JsonProperty]
public string SharedAccessKey { get; set; }
/// <summary>
/// Device id or mappable id for mapper
/// </summary>
[JsonProperty]
public string Id { get; set; }
/// <summary>
/// Polling interval
/// </summary>
[JsonProperty]
public int PublishingInterval { get; set; }
/// <summary>
/// Minimum desired Security Level
/// </summary>
[JsonProperty]
public byte MinimumSecurityLevel { get; set; } = 0;
/// <summary>
/// Minimum desired Security mode
/// </summary>
[JsonProperty]
public MessageSecurityMode MinimumSecurityMode { get; set; } = MessageSecurityMode.SignAndEncrypt;
/// <summary>
/// Monitored item configuration
/// </summary>
[JsonProperty]
public List<MonitoredItem> MonitoredItems { get; set; }
/// <summary>
/// Default constructor
/// </summary>
public ServerSession()
{
MonitoredItems = new List<MonitoredItem>();
PublishingInterval = 1000;
}
/// <summary>
/// The Module the session is attached to.
/// </summary>
internal SampleModule Module { get; set; }
/// <summary>
/// Called when the object is deserialized
/// </summary>
/// <param name="context"></param>
[OnDeserialized]
internal void OnDeserializedMethod(StreamingContext context)
{
if (MonitoredItems.Count == 0)
{
throw new Exception("Configuration did not specify monitored items!");
}
if (ServerUrl == null)
{
throw new Exception("Configuration did not contain an endpoint Uri");
}
if (string.IsNullOrEmpty(Id))
{
throw new Exception("Configuration did not contain a device name!");
}
MonitoredItems.ForEach(i => i.Notification += MonitoredItem_Notification);
}
public async Task EndpointConnect()
{
var endpointCollection = DiscoverEndpoints(Module.Configuration, ServerUrl, 60);
var selectedEndpoints = new List<EndpointDescription>();
// Select endpoints
foreach (EndpointDescription endpoint in endpointCollection)
{
if (endpoint.TransportProfileUri == Profiles.UaTcpTransport &&
endpoint.SecurityLevel >= MinimumSecurityLevel &&
endpoint.SecurityMode >= MinimumSecurityMode)
{
// patch endpoint to set the original host name we want to connect to.
var url = new UriBuilder(endpoint.EndpointUrl);
url.Host = ServerUrl.Host;
endpoint.EndpointUrl = url.ToString();
selectedEndpoints.Add(endpoint);
}
}
//
// Sort, but descending with highest level first i.e. return
// < 0 if x is less than y
// > 0 if x is greater than y
// 0 if x and y are equal
//
selectedEndpoints.Sort((y, x) => x.SecurityLevel - y.SecurityLevel);
// Do not emit all exceptions as they occur, only throw them all when no connection can be made.
var exceptions = new List<Exception>(selectedEndpoints.Count);
foreach (EndpointDescription endpoint in selectedEndpoints)
{
ConfiguredEndpoint configuredEndpoint = new ConfiguredEndpoint(
endpoint.Server, EndpointConfiguration.Create(Module.Configuration));
configuredEndpoint.Update(endpoint);
try
{
Console.WriteLine($"Opc.Ua.Client.SampleModule: Trying to create session with mode: {endpoint.SecurityMode}, level:{endpoint.SecurityLevel} to {configuredEndpoint.EndpointUrl}...");
_session = await Session.Create(
Module.Configuration,
configuredEndpoint,
true,
false,
Module.Configuration.ApplicationName,
60000,
// TODO: Make user identity configurable, plus add dedicated security policy
new UserIdentity(new AnonymousIdentityToken()),
null);
if (_session != null)
{
var subscription = new Subscription(_session.DefaultSubscription);
subscription.PublishingInterval = PublishingInterval;
// TODO: Make other subscription settings configurable...
subscription.AddItems(MonitoredItems);
_session.AddSubscription(subscription);
subscription.Create();
Console.WriteLine($"Opc.Ua.Client.SampleModule: Session with mode: {endpoint.SecurityMode}, level:{endpoint.SecurityLevel} to {configuredEndpoint.EndpointUrl} established!");
_session.KeepAlive += new KeepAliveEventHandler(StandardClient_KeepAlive);
// Done
return;
}
exceptions.Add(new Exception($"ERROR: Create session to endpoint {endpoint.ToString()} returned null."));
}
catch (AggregateException ae)
{
exceptions.AddRange(ae.InnerExceptions);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
// ... try another endpoint until we do not have any more...
Console.WriteLine($"Opc.Ua.Client.SampleModule: WARNING Could not create session to endpoint {endpoint.ToString()}...");
}
throw new AggregateException("Failed to find acceptable endpoint to connect to.", exceptions);
}
private void MonitoredItem_Notification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e)
{
try
{
MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification;
if (notification == null)
{
return;
}
DataValue value = notification.Value as DataValue;
if (value == null)
{
return;
}
using (var encoder = new JsonEncoder(monitoredItem.Subscription.Session.MessageContext, false))
{
string applicationURI = monitoredItem.Subscription.Session.Endpoint.Server.ApplicationUri;
encoder.WriteString("ApplicationUri", applicationURI);
encoder.WriteString("DisplayName", monitoredItem.DisplayName);
encoder.WriteNodeId("MonitoredItem", monitoredItem.ResolvedNodeId);
// suppress output of server timestamp in json by setting it to minvalue
value.ServerTimestamp = DateTime.MinValue;
encoder.WriteDataValue("Value", value);
string json = encoder.CloseAndReturnText();
var properties = new Dictionary<string, string>();
properties.Add("content-type", "application/opcua+uajson");
properties.Add("deviceName", Id);
if (SharedAccessKey != null)
{
properties.Add("source", "mapping");
properties.Add("deviceKey", SharedAccessKey);
}
try
{
Module.Publish(new Message(json, properties));
}
catch (Exception ex)
{
Console.WriteLine("Opc.Ua.Client.SampleModule: Failed to publish message, dropping...");
Console.WriteLine(ex.ToString());
}
}
}
catch (Exception exception)
{
Console.WriteLine("Opc.Ua.Client.SampleModule: Error processing monitored item notification.");
Console.WriteLine(exception.ToString());
}
}
private void StandardClient_KeepAlive(Session sender, KeepAliveEventArgs e)
{
if (e != null && sender != null)
{
if (!ServiceResult.IsGood(e.Status))
{
Console.WriteLine($"Opc.Ua.Client.SampleModule: Server {sender.ConfiguredEndpoint.EndpointUrl} Status NOT good: {e.Status} {sender.OutstandingRequestCount}/{sender.DefunctRequestCount}");
}
}
}
private EndpointDescriptionCollection DiscoverEndpoints(ApplicationConfiguration config, Uri discoveryUrl, int timeout)
{
EndpointConfiguration configuration = EndpointConfiguration.Create(config);
configuration.OperationTimeout = timeout;
using (DiscoveryClient client = DiscoveryClient.Create(discoveryUrl, EndpointConfiguration.Create(config)))
{
try
{
EndpointDescriptionCollection endpoints = client.GetEndpoints(null);
ReplaceLocalHostWithRemoteHost(endpoints, discoveryUrl);
return endpoints;
}
catch (Exception e)
{
Console.WriteLine($"Opc.Ua.Client.SampleModule: Could not fetch endpoints from url: {discoveryUrl}");
Console.WriteLine($"Opc.Ua.Client.SampleModule: Reason = {e.Message}");
throw e;
}
}
}
private void ReplaceLocalHostWithRemoteHost(EndpointDescriptionCollection endpoints, Uri discoveryUrl)
{
foreach (EndpointDescription endpoint in endpoints)
{
endpoint.EndpointUrl = Utils.ReplaceLocalhost(endpoint.EndpointUrl, discoveryUrl.DnsSafeHost);
StringCollection updatedDiscoveryUrls = new StringCollection();
foreach (string url in endpoint.Server.DiscoveryUrls)
{
updatedDiscoveryUrls.Add(Utils.ReplaceLocalhost(url, discoveryUrl.DnsSafeHost));
}
endpoint.Server.DiscoveryUrls = updatedDiscoveryUrls;
}
}
/// <summary>
/// Dispose
/// </summary>
public void Dispose()
{
Dispose(true);
}
/// <summary>
/// Dispose implementation
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
{
lock (this)
{
if (!_disposedValue)
{
if (disposing)
{
if (_session != null)
{
_session.Dispose();
_session = null;
}
}
_disposedValue = true;
}
}
}
}
private Session _session;
private bool _disposedValue = false; // To detect redundant calls
}
}

Просмотреть файл

@ -1,52 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Managed OPC UA Publisher module for the Azure IoT Field Gateway</Description>
<AssemblyTitle>Opc Ua Publisher Module for Azure IoT Field Gateway</AssemblyTitle>
<VersionPrefix>0.2.0</VersionPrefix>
<Authors>microsoft</Authors>
<TargetFrameworks>netstandard1.6</TargetFrameworks>
<NoWarn>$(NoWarn);1591;1734</NoWarn>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AssemblyName>Opc.Ua.Client.Module</AssemblyName>
<PackageId>Opc.Ua.Client.Module</PackageId>
<PackageTags>Azure;IoT;.NET;OPC UA;Gateway</PackageTags>
<PackageReleaseNotes>https://github.com/Azure/iot-gateway-opc-ua/releases</PackageReleaseNotes>
<PackageProjectUrl>https://github.com/Azure/iot-gateway-opc-ua</PackageProjectUrl>
<PackageLicenseUrl>https://raw.githubusercontent.com/Azure/iot-gateway-opc-ua/master/license.txt</PackageLicenseUrl>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<RepositoryUrl>https://github.com/Azure/iot-gateway-opc-ua</RepositoryUrl>
<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Core" Version="0.2.0" />
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.SDK" Version="0.2.0" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.1.2" />
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Signed' ">
<DefineConstants>$(DefineConstants);RELEASE_DELAY_SIGN</DefineConstants>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.6' ">
<PackageReference Include="System.Runtime.Serialization.Json" Version="4.3.0" />
<PackageReference Include="system.xml.xpath.xmldocument" Version="4.3.0" />
<PackageReference Include="System.Xml.XmlDocument" Version="4.3.0" />
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.3.0" />
<PackageReference Include="System.Private.ServiceModel" Version="4.1.0" />
<PackageReference Include="Microsoft.Azure.Devices.Gateway" Version="1.0.0" />
</ItemGroup>
</Project>

Двоичные данные
src/Opc.Ua.Publisher.Module/35MSSharedLib1024.snk Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,18 @@
@echo off
setlocal
REM These lines will build the production line station model if the batch file is run from the Station directory
rem ensure Opc.Ua.ModelCompiler.exe is in the path
for %%X in (Opc.Ua.ModelCompiler.exe) do (set FOUND=%%~$PATH:X)
if not defined FOUND goto error
echo Building Station
Opc.Ua.ModelCompiler.exe -d2 ".\PublisherModel.xml" -cg ".\PublisherModel.csv" -o2 "."
exit /b 0
:error
echo Opc.Ua.ModelCompiler.exe not found
echo cannot compile the station models
exit /b 1

Просмотреть файл

@ -0,0 +1,560 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Text;
using Newtonsoft.Json;
using Microsoft.Azure.Devices.Gateway;
using System.Net.Http;
using System.Net.Http.Headers;
using Publisher;
using Opc.Ua.Client;
using IoTHubCredentialTools;
using System.IO;
using System.Net;
namespace Opc.Ua.Publisher
{
/// <summary>
/// Gateway module that acts as Opc.Ua Publisher and Server
/// </summary>
public class Module : IGatewayModule, IGatewayModuleStart
{
public static ApplicationConfiguration m_configuration = null;
public static List<Session> m_sessions = new List<Session>();
public static PublishedNodesCollection m_nodesLookups = new PublishedNodesCollection();
public static List<Uri> m_endpointUrls = new List<Uri>();
public static string m_deviceName = string.Empty;
public static string m_accessKey = string.Empty;
private static Broker m_broker = null;
private PublisherServer m_server = new PublisherServer();
private const string m_IoTHubAPIVersion = "?api-version=2016-11-14";
/// <summary>
/// Trace message helper
/// </summary>
public static void Trace(string message)
{
Utils.Trace(message);
Console.WriteLine(message);
}
/// <summary>
/// Create module, throws if configuration is bad
/// </summary>
public void Create(Broker broker, byte[] configuration)
{
Trace("Opc.Ua.Publisher.Module: Creating...");
m_broker = broker;
string configString = Encoding.UTF8.GetString(configuration);
// Deserialize from configuration string
ModuleConfiguration moduleConfiguration = null;
try
{
moduleConfiguration = JsonConvert.DeserializeObject<ModuleConfiguration>(configString);
}
catch (Exception ex)
{
Trace("Opc.Ua.Publisher.Module: Module config string " + configString + " could not be deserialized: " + ex.Message);
throw;
}
m_configuration = moduleConfiguration.Configuration;
m_configuration.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation);
// update log configuration, if available
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GW_LOGP")))
{
m_configuration.TraceConfiguration.OutputFilePath = Environment.GetEnvironmentVariable("_GW_LOGP");
m_configuration.TraceConfiguration.ApplySettings();
}
// get a list of persisted endpoint URLs and create a session for each.
try
{
// check if we have an env variable specifying the published nodes path, otherwise use current directory
string publishedNodesFilePath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "publishednodes.json";
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GW_PNFP")))
{
publishedNodesFilePath = Environment.GetEnvironmentVariable("_GW_PNFP");
}
Trace("Opc.Ua.Publisher.Module: Attemping to load nodes file from: " + publishedNodesFilePath);
m_nodesLookups = JsonConvert.DeserializeObject<PublishedNodesCollection>(File.ReadAllText(publishedNodesFilePath));
Trace("Opc.Ua.Publisher.Module: Loaded " + m_nodesLookups.Count.ToString() + " nodes.");
}
catch (Exception ex)
{
Trace("Opc.Ua.Publisher.Module: Nodes file loading failed with: " + ex.Message);
}
foreach (NodeLookup nodeLookup in m_nodesLookups)
{
if (!m_endpointUrls.Contains(nodeLookup.EndPointURL))
{
m_endpointUrls.Add(nodeLookup.EndPointURL);
}
}
// start the server
try
{
Trace("Opc.Ua.Publisher.Module: Starting server on endpoint " + m_configuration.ServerConfiguration.BaseAddresses[0].ToString() + "...");
m_server.Start(m_configuration);
Trace("Opc.Ua.Publisher.Module: Server started.");
}
catch (Exception ex)
{
Trace("Opc.Ua.Publisher.Module: Starting server failed with: " + ex.Message);
}
// check if we have an environment variable to register ourselves with IoT Hub
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_HUB_CS")))
{
string ownerConnectionString = Environment.GetEnvironmentVariable("_HUB_CS");
if ((m_configuration != null) && (!string.IsNullOrEmpty(m_configuration.ApplicationName)))
{
Trace("Attemping to register ourselves with IoT Hub using owner connection string: " + ownerConnectionString);
string deviceConnectionString = IoTHubRegistration.RegisterDeviceWithIoTHub(m_configuration.ApplicationName, ownerConnectionString);
if (!string.IsNullOrEmpty(deviceConnectionString))
{
SecureIoTHubToken.Write(m_configuration.ApplicationName, deviceConnectionString);
}
else
{
Trace("Could not register ourselves with IoT Hub using owner connection string: " + ownerConnectionString);
}
}
}
// try to configure our publisher component
TryConfigurePublisherAsync().Wait();
// connect to servers
Trace("Opc.Ua.Publisher.Module: Attemping to connect to servers...");
try
{
List<Task> connectionAttempts = new List<Task>();
foreach (Uri endpointUrl in m_endpointUrls)
{
Trace("Opc.Ua.Publisher.Module: Connecting to server: " + endpointUrl);
connectionAttempts.Add(EndpointConnect(endpointUrl));
}
// Wait for all sessions to be connected
Task.WaitAll(connectionAttempts.ToArray());
}
catch (Exception ex)
{
Trace("Opc.Ua.Publisher.Module: Exception: " + ex.ToString() + "\r\n" + ex.InnerException != null ? ex.InnerException.ToString() : null);
}
Trace("Opc.Ua.Publisher.Module: Created.");
}
/// <summary>
/// Disconnect all sessions
/// </summary>
public void Destroy()
{
foreach (Session session in m_sessions)
{
session.Close();
}
Trace("Opc.Ua.Publisher.Module: All sessions closed.");
}
/// <summary>
/// Receive message from broker
/// </summary>
public void Receive(Message received_message)
{
// No-op
}
/// <summary>
/// Try to configure our Publisher settings
/// </summary>
public static async Task TryConfigurePublisherAsync()
{
// read connection string from secure store and configure publisher, if possible
if ((m_configuration != null) && (!string.IsNullOrEmpty(m_configuration.ApplicationName)))
{
Trace("Opc.Ua.Publisher.Module: Attemping to read connection string from secure store with certificate name: " + m_configuration.ApplicationName);
string connectionString = SecureIoTHubToken.Read(m_configuration.ApplicationName);
if (!string.IsNullOrEmpty(connectionString))
{
Trace("Opc.Ua.Publisher.Module: Attemping to configure publisher with connection string: " + connectionString);
string[] parsedConnectionString = IoTHubRegistration.ParseConnectionString(connectionString, true);
if ((parsedConnectionString != null) && (parsedConnectionString.Length == 3))
{
// note: IoTHub name can't be changed during runtime in the GW IoTHub module
string _IoTHubName = parsedConnectionString[0];
m_deviceName = parsedConnectionString[1];
m_accessKey = parsedConnectionString[2];
Trace("Opc.Ua.Publisher.Module: Publisher configured for device: " + m_deviceName);
// try to connect to IoT Hub
using (HttpClient httpClient = new HttpClient())
{
httpClient.BaseAddress = new UriBuilder { Scheme = "https", Host = _IoTHubName }.Uri;
string sharedAccessToken = IoTHubRegistration.GenerateSharedAccessToken(string.Empty, Convert.FromBase64String(m_accessKey), _IoTHubName, 60000);
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SharedAccessSignature", sharedAccessToken);
// send an empty d2c message
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "/devices/" + m_deviceName + "/messages/events" + IoTHubRegistration._IoTHubAPIVersion);
HttpResponseMessage response = await httpClient.SendAsync(request).ConfigureAwait(false);
if (response.StatusCode != HttpStatusCode.NoContent)
{
throw new Exception("Opc.Ua.Publisher.Module: Could not connect to IoT Hub. Response: " + response.ToString());
}
}
}
else
{
throw new Exception("Opc.Ua.Publisher.Module: Publisher configuration failed!");
}
}
else
{
Trace("Opc.Ua.Publisher.Module: Connection string not found in secure store.");
}
}
}
/// <summary>
/// Publish message to bus
/// </summary>
public static void Publish(Message message)
{
if (m_broker != null)
{
m_broker.Publish(message);
}
}
/// <summary>
/// Called when gateway starts, establishes the connections to endpoints
/// </summary>
public void Start()
{
Trace("Opc.Ua.Publisher.Module: Starting...");
// subscribe to preconfigured nodes
Trace("Opc.Ua.Publisher.Module: Attemping to subscribe to published nodes...");
if (m_nodesLookups != null)
{
foreach (NodeLookup nodeLookup in m_nodesLookups)
{
try
{
CreateMonitoredItem(nodeLookup);
}
catch (Exception ex)
{
Trace("Opc.Ua.Publisher.Module: Unexpected error publishing node: " + ex.Message + "\r\nIgnoring node: " + nodeLookup.EndPointURL.AbsoluteUri + ", " + nodeLookup.NodeID.ToString());
}
}
}
Trace("Opc.Ua.Publisher.Module: Started.");
}
/// <summary>
/// Registers ourselves with IoTHub so we can send messages to it
/// </summary>
private void SelfRegisterWithIoTHub(string ownerConnectionString)
{
string[] parsedConnectionString = IoTHubRegistration.ParseConnectionString(ownerConnectionString, false);
string deviceConnectionString = string.Empty;
if ((parsedConnectionString != null) && (parsedConnectionString.Length == 3))
{
string IoTHubName = parsedConnectionString[0];
string name = parsedConnectionString[1];
string accessToken = parsedConnectionString[2];
using (HttpClient httpClient = new HttpClient())
{
httpClient.BaseAddress = new UriBuilder { Scheme = "https", Host = IoTHubName }.Uri;
string sharedAccessSignature = IoTHubRegistration.GenerateSharedAccessToken(name, Convert.FromBase64String(accessToken), IoTHubName, 60000);
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SharedAccessSignature", sharedAccessSignature);
deviceConnectionString = IoTHubRegistration.CreateDeviceInIoTHubDeviceRegistry(httpClient, m_configuration.ApplicationName.Replace(" ", "")).Result;
// prepend the rest of the connection string
deviceConnectionString = "HostName=" + IoTHubName + ";DeviceId=" + m_configuration.ApplicationName.Replace(" ", "") + ";SharedAccessKey=" + deviceConnectionString;
SecureIoTHubToken.Write(m_configuration.ApplicationName, deviceConnectionString);
}
}
else
{
Trace("Opc.Ua.Publisher.Module: Could not parse IoT Hub owner connection string: " + ownerConnectionString);
}
}
/// <summary>
/// Connects to a single OPC UA Server's endpoint
/// </summary>
public static async Task EndpointConnect(Uri endpointUrl)
{
EndpointDescription selectedEndpoint = SelectUaTcpEndpoint(DiscoverEndpoints(m_configuration, endpointUrl, 10));
ConfiguredEndpoint configuredEndpoint = new ConfiguredEndpoint(selectedEndpoint.Server, EndpointConfiguration.Create(m_configuration));
configuredEndpoint.Update(selectedEndpoint);
Session newSession = await Session.Create(
m_configuration,
configuredEndpoint,
true,
false,
m_configuration.ApplicationName,
60000,
new UserIdentity(new AnonymousIdentityToken()),
null);
if (newSession != null)
{
Trace("Opc.Ua.Publisher.Module: Created session with updated endpoint " + selectedEndpoint.EndpointUrl + " from server!");
newSession.KeepAlive += new KeepAliveEventHandler((sender, e) => StandardClient_KeepAlive(sender, e, newSession));
m_sessions.Add(newSession);
}
}
/// <summary>
/// Creates a subscription to a monitored item on an OPC UA server
/// </summary>
public static void CreateMonitoredItem(NodeLookup nodeLookup)
{
// find the right session using our lookup
Session matchingSession = null;
foreach (Session session in m_sessions)
{
char[] trimChars = { '/', ' ' };
if (session.Endpoint.EndpointUrl.TrimEnd(trimChars).Equals(nodeLookup.EndPointURL.ToString().TrimEnd(trimChars), StringComparison.OrdinalIgnoreCase))
{
matchingSession = session;
break;
}
}
if (matchingSession != null)
{
Subscription subscription = matchingSession.DefaultSubscription;
if (matchingSession.AddSubscription(subscription))
{
subscription.Create();
}
// get the DisplayName for the node.
Node node = matchingSession.ReadNode(nodeLookup.NodeID);
string nodeDisplayName = node.DisplayName.Text;
if (String.IsNullOrEmpty(nodeDisplayName))
{
nodeDisplayName = nodeLookup.NodeID.Identifier.ToString();
}
// add the new monitored item.
MonitoredItem monitoredItem = new MonitoredItem(subscription.DefaultItem);
monitoredItem.StartNodeId = nodeLookup.NodeID;
monitoredItem.AttributeId = Attributes.Value;
monitoredItem.DisplayName = nodeDisplayName;
monitoredItem.MonitoringMode = MonitoringMode.Reporting;
monitoredItem.SamplingInterval = 0;
monitoredItem.QueueSize = 0;
monitoredItem.DiscardOldest = true;
monitoredItem.Notification += new MonitoredItemNotificationEventHandler(Module.MonitoredItem_Notification);
subscription.AddItem(monitoredItem);
subscription.ApplyChanges();
}
else
{
Trace("Opc.Ua.Publisher.Module: ERROR: Could not find endpoint URL " + nodeLookup.EndPointURL.ToString() + " in active server sessions, NodeID " + nodeLookup.NodeID.Identifier.ToString() + " NOT published!");
Trace("Opc.Ua.Publisher.Module: To fix this, please update your publishednodes.json file with the updated endpoint URL!");
}
}
/// <summary>
/// The notification that the data for a monitored item has changed on an OPC UA server
/// </summary>
public static void MonitoredItem_Notification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e)
{
try
{
if (e.NotificationValue == null || monitoredItem.Subscription.Session == null)
{
return;
}
MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification;
if (notification == null)
{
return;
}
DataValue value = notification.Value as DataValue;
if (value == null)
{
return;
}
JsonEncoder encoder = new JsonEncoder(monitoredItem.Subscription.Session.MessageContext, false);
string applicationURI = monitoredItem.Subscription.Session.Endpoint.Server.ApplicationUri;
encoder.WriteString("ApplicationUri", applicationURI);
encoder.WriteString("DisplayName", monitoredItem.DisplayName);
// write NodeId as ns=x;i=y
NodeId nodeId = monitoredItem.ResolvedNodeId;
encoder.WriteString("NodeId", new NodeId(nodeId.Identifier, nodeId.NamespaceIndex).ToString());
// suppress output of server timestamp in json by setting it to minvalue
value.ServerTimestamp = DateTime.MinValue;
encoder.WriteDataValue("Value", value);
string json = encoder.CloseAndReturnText();
byte[] bytes = new UTF8Encoding(false).GetBytes(json);
// publish
var properties = new Dictionary<string, string>();
properties.Add("content-type", "application/opcua+uajson");
properties.Add("deviceName", m_deviceName);
if (m_accessKey != null)
{
properties.Add("source", "mapping");
properties.Add("deviceKey", m_accessKey);
}
try
{
Publish(new Message(json, properties));
Trace("Opc.Ua.Publisher.Module: Published: " + json + " from " + m_deviceName);
}
catch (Exception ex)
{
Trace("Opc.Ua.Publisher.Module: Failed to publish message, dropping...");
Trace(ex.ToString());
}
}
catch (Exception exception)
{
Trace("Opc.Ua.Publisher.Module: Error processing monitored item notification: " + exception.ToString());
}
}
/// <summary>
/// Handler for the standard "keep alive" event sent by all OPC UA servers
/// </summary>
private static void StandardClient_KeepAlive(Session sender, KeepAliveEventArgs e, Session session)
{
if (e != null && session != null)
{
if (!ServiceResult.IsGood(e.Status))
{
Utils.Trace(String.Format(
"Status: {0}/t/tOutstanding requests: {1}/t/tDefunct requests: {2}",
e.Status,
session.OutstandingRequestCount,
session.DefunctRequestCount));
}
}
}
/// <summary>
/// Discovers all endpoints provided by an OPC UA server using a discovery client
/// </summary>
private static EndpointDescriptionCollection DiscoverEndpoints(ApplicationConfiguration config, Uri discoveryUrl, int timeout)
{
EndpointConfiguration configuration = EndpointConfiguration.Create(config);
configuration.OperationTimeout = timeout;
using (DiscoveryClient client = DiscoveryClient.Create(
discoveryUrl,
EndpointConfiguration.Create(config)))
{
try
{
EndpointDescriptionCollection endpoints = client.GetEndpoints(null);
return ReplaceLocalHostWithRemoteHost(endpoints, discoveryUrl);
}
catch (Exception e)
{
Trace("Opc.Ua.Publisher.Module: Could not fetch endpoints from url: " + discoveryUrl.ToString());
Trace("Opc.Ua.Publisher.Module: Reason = " + e.Message);
throw e;
}
}
}
/// <summary>
/// Replaces all instances of "LocalHost" in a collection of endpoint description with the real host name
/// </summary>
private static EndpointDescriptionCollection ReplaceLocalHostWithRemoteHost(EndpointDescriptionCollection endpoints, Uri discoveryUrl)
{
EndpointDescriptionCollection updatedEndpoints = endpoints;
foreach (EndpointDescription endpoint in updatedEndpoints)
{
endpoint.EndpointUrl = Utils.ReplaceLocalhost(endpoint.EndpointUrl, discoveryUrl.DnsSafeHost);
StringCollection updatedDiscoveryUrls = new StringCollection();
foreach (string url in endpoint.Server.DiscoveryUrls)
{
updatedDiscoveryUrls.Add(Utils.ReplaceLocalhost(url, discoveryUrl.DnsSafeHost));
}
endpoint.Server.DiscoveryUrls = updatedDiscoveryUrls;
}
return updatedEndpoints;
}
/// <summary>
/// Selects the UA TCP endpoint from an endpoint collection with the highest security settings offered
/// </summary>
private static EndpointDescription SelectUaTcpEndpoint(EndpointDescriptionCollection endpointCollection)
{
EndpointDescription bestEndpoint = null;
foreach (EndpointDescription endpoint in endpointCollection)
{
if (endpoint.TransportProfileUri == Profiles.UaTcpTransport)
{
if ((bestEndpoint == null) ||
(endpoint.SecurityLevel > bestEndpoint.SecurityLevel))
{
bestEndpoint = endpoint;
}
}
}
return bestEndpoint;
}
/// <summary>
/// Standard certificate validation callback
/// </summary>
private void CertificateValidator_CertificateValidation(CertificateValidator validator, CertificateValidationEventArgs e)
{
if (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted)
{
Trace("Opc.Ua.Publisher.Module: Certificate \""
+ e.Certificate.Subject
+ "\" not trusted. If you want to trust this certificate, please copy it from the \""
+ m_configuration.SecurityConfiguration.RejectedCertificateStore.StorePath + "/certs"
+ "\" to the \""
+ m_configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath + "/certs"
+ "\" folder. A restart of the gateway is NOT required.");
}
}
}
}

Просмотреть файл

@ -0,0 +1,184 @@

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Security.Cryptography.X509Certificates;
namespace Opc.Ua.Publisher
{
/// <summary>
/// Module configuration object to deserialize / serialize
/// </summary>
[JsonObject(MemberSerialization.OptIn)]
public class ModuleConfiguration
{
/// <summary>
/// Opc client configuration
/// </summary>
[JsonProperty]
public ApplicationConfiguration Configuration { get; set; }
/// <summary>
/// Called when the object is deserialized
/// </summary>
/// <param name="context"></param>
[OnDeserialized]
internal void OnDeserializedMethod(StreamingContext context)
{
// Validate configuration and set reasonable defaults
Configuration.ApplicationUri = Configuration.ApplicationUri.Replace("localhost", Utils.GetHostName());
Configuration.ApplicationType = ApplicationType.ClientAndServer;
Configuration.TransportQuotas = new TransportQuotas { OperationTimeout = 15000 };
Configuration.ClientConfiguration = new ClientConfiguration();
Configuration.ServerConfiguration = new ServerConfiguration();
if (Configuration.SecurityConfiguration == null)
{
Configuration.SecurityConfiguration = new SecurityConfiguration();
}
if (Configuration.SecurityConfiguration.TrustedPeerCertificates == null)
{
Configuration.SecurityConfiguration.TrustedPeerCertificates = new CertificateTrustList();
}
if (Configuration.SecurityConfiguration.TrustedIssuerCertificates == null)
{
Configuration.SecurityConfiguration.TrustedIssuerCertificates = new CertificateTrustList();
}
if (Configuration.SecurityConfiguration.RejectedCertificateStore == null)
{
Configuration.SecurityConfiguration.RejectedCertificateStore = new CertificateTrustList();
}
if (Configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType == null)
{
Configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType = "Directory";
}
if (Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath == null)
{
Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = "CertificateStores/UA Applications";
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_TPC_SP")))
{
Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = Environment.GetEnvironmentVariable("_TPC_SP");
}
}
if (Configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType == null)
{
Configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType = "Directory";
}
if (Configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath == null)
{
Configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath = "CertificateStores/UA Certificate Authorities";
}
if (Configuration.SecurityConfiguration.RejectedCertificateStore.StoreType == null)
{
Configuration.SecurityConfiguration.RejectedCertificateStore.StoreType = "Directory";
}
if (Configuration.SecurityConfiguration.RejectedCertificateStore.StorePath == null)
{
Configuration.SecurityConfiguration.RejectedCertificateStore.StorePath = "CertificateStores/Rejected Certificates";
}
Configuration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier();
Configuration.SecurityConfiguration.ApplicationCertificate.StoreType = "X509Store";
Configuration.SecurityConfiguration.ApplicationCertificate.StorePath = "CurrentUser\\UA_MachineDefault";
Configuration.SecurityConfiguration.ApplicationCertificate.SubjectName = Configuration.ApplicationName;
X509Certificate2 certificate = Configuration.SecurityConfiguration.ApplicationCertificate.Find(true).Result;
if (certificate == null)
{
certificate = CertificateFactory.CreateCertificate(
Configuration.SecurityConfiguration.ApplicationCertificate.StoreType,
Configuration.SecurityConfiguration.ApplicationCertificate.StorePath,
Configuration.ApplicationUri,
Configuration.ApplicationName,
Configuration.ApplicationName,
new List<string>(){ Configuration.ApplicationName }
);
}
if (certificate == null)
{
throw new Exception("Opc.Ua.Publisher.Module: OPC UA application certificate could not be created, cannot continue without it!");
}
Configuration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate;
Configuration.ApplicationUri = Utils.GetApplicationUriFromCertificate(certificate);
// Ensure it is trusted
try
{
ICertificateStore store = Configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore();
if (store == null)
{
Utils.Trace("Could not open trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath);
}
else
{
try
{
Utils.Trace(Utils.TraceMasks.Information, "Adding certificate to trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath);
X509Certificate2 publicKey = new X509Certificate2(certificate.RawData);
store.Add(publicKey).Wait();
}
finally
{
store.Close();
}
}
}
catch (Exception e)
{
Utils.Trace(e, "Could not add certificate to trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath);
}
// patch our base address
if (Configuration.ServerConfiguration.BaseAddresses.Count == 0)
{
Configuration.ServerConfiguration.BaseAddresses.Add("opc.tcp://" + Configuration.ApplicationName.ToLowerInvariant() + ":62222/UA/Publisher");
}
// tighten security policy by removing security policy "none"
foreach (ServerSecurityPolicy policy in Configuration.ServerConfiguration.SecurityPolicies)
{
if (policy.SecurityMode == MessageSecurityMode.None)
{
Configuration.ServerConfiguration.SecurityPolicies.Remove(policy);
break;
}
}
// turn off LDS registration
Configuration.ServerConfiguration.MaxRegistrationInterval = 0;
// add sign & encrypt policy
ServerSecurityPolicy newPolicy = new ServerSecurityPolicy();
newPolicy.SecurityMode = MessageSecurityMode.SignAndEncrypt;
newPolicy.SecurityLevel = 1;
newPolicy.SecurityPolicyUri = SecurityPolicies.Basic128Rsa15;
Configuration.ServerConfiguration.SecurityPolicies.Add(newPolicy);
// enable logging
Configuration.TraceConfiguration = new TraceConfiguration();
Configuration.TraceConfiguration.DeleteOnLoad = true;
Configuration.TraceConfiguration.TraceMasks = 519;
Configuration.TraceConfiguration.OutputFilePath = "./Logs/" + Configuration.ApplicationName + ".log.txt";
Configuration.TraceConfiguration.ApplySettings();
// the OperationTimeout should be twice the minimum value for PublishingInterval * KeepAliveCount, so set to 120s
Configuration.TransportQuotas.OperationTimeout = 120000;
// validate the configuration now
Configuration.Validate(Configuration.ApplicationType).Wait();
}
}
}

Просмотреть файл

@ -0,0 +1,93 @@
using Opc.Ua;
using Opc.Ua.Sample;
using System.Collections.Generic;
using System.Reflection;
namespace Publisher
{
public class PublisherNodeManager : SampleNodeManager
{
private ushort m_namespaceIndex;
private ushort m_typeNamespaceIndex;
private long m_lastUsedId;
public PublisherNodeManager(Opc.Ua.Server.IServerInternal server, ApplicationConfiguration configuration)
: base(server)
{
List<string> namespaceUris = new List<string>();
namespaceUris.Add(Namespaces.Publisher);
namespaceUris.Add(Namespaces.Publisher + "/Instance");
NamespaceUris = namespaceUris;
m_typeNamespaceIndex = Server.NamespaceUris.GetIndexOrAppend(namespaceUris[0]);
m_namespaceIndex = Server.NamespaceUris.GetIndexOrAppend(namespaceUris[1]);
m_lastUsedId = 0;
}
/// <summary>
/// Creates a new node
/// </summary>
public override NodeId New(ISystemContext context, NodeState node)
{
uint id = Utils.IncrementIdentifier(ref m_lastUsedId);
return new NodeId(id, m_namespaceIndex);
}
/// <summary>
/// Loads predefined nodes file
/// </summary>
protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context)
{
NodeStateCollection predefinedNodes = new NodeStateCollection();
predefinedNodes.LoadFromBinaryResource(context, "Opc.Ua.Publisher.Module.Publisher.PredefinedNodes.uanodes", this.GetType().GetTypeInfo().Assembly, true);
return predefinedNodes;
}
/// <summary>
/// Hooks our predefined nodes into the overal node graph of the server and
/// initializes our state class
/// </summary>
protected override NodeState AddBehaviourToPredefinedNode(ISystemContext context, NodeState predefinedNode)
{
BaseObjectState passiveNode = predefinedNode as BaseObjectState;
if (passiveNode == null)
{
return predefinedNode;
}
NodeId typeId = passiveNode.TypeDefinitionId;
if (!IsNodeIdInNamespace(typeId) || typeId.IdType != IdType.Numeric)
{
return predefinedNode;
}
switch ((uint)typeId.Identifier)
{
case ObjectTypes.PublisherType:
{
if (passiveNode is PublisherState)
{
break;
}
PublisherState activeNode = new PublisherState(passiveNode.Parent);
activeNode.Create(context, passiveNode);
// replace the node in the parent.
if (passiveNode.Parent != null)
{
passiveNode.Parent.ReplaceChild(context, activeNode);
}
return activeNode;
}
}
return predefinedNode;
}
}
}

Просмотреть файл

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>a1cc3b57-a186-4c3e-9e36-30a54a947369</ProjectGuid>
<RootNamespace>Opc.Ua.Publisher</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

Просмотреть файл

@ -6,7 +6,7 @@ using System.Runtime.InteropServices;
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("Opc.Ua.Client.SampleModule")]
[assembly: AssemblyProduct("Opc.Ua.Publisher.Module")]
[assembly: AssemblyTrademark("")]
// Setting ComVisible to false makes the types in this assembly not visible

Просмотреть файл

@ -0,0 +1,29 @@

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace Opc.Ua.Publisher
{
[DataContract]
public partial class NodeLookup
{
public NodeLookup()
{
}
[DataMember]
public Uri EndPointURL;
[DataMember]
public NodeId NodeID;
}
[CollectionDataContract]
public partial class PublishedNodesCollection : List<NodeLookup>
{
public PublishedNodesCollection()
{
}
}
}

Просмотреть файл

@ -0,0 +1,712 @@
/* ========================================================================
* 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/
* ======================================================================*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Xml;
using System.Runtime.Serialization;
using Opc.Ua;
namespace Publisher
{
#region PublishNodeMethodState Class
#if (!OPCUA_EXCLUDE_PublishNodeMethodState)
/// <summary>
/// Stores an instance of the PublishNodeMethodType Method.
/// </summary>
/// <exclude />
[System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")]
public partial class PublishNodeMethodState : MethodState
{
#region Constructors
/// <summary>
/// Initializes the type with its default attribute values.
/// </summary>
public PublishNodeMethodState(NodeState parent) : base(parent)
{
}
/// <summary>
/// Constructs an instance of a node.
/// </summary>
/// <param name="parent">The parent.</param>
/// <returns>The new node.</returns>
public new static NodeState Construct(NodeState parent)
{
return new PublishNodeMethodState(parent);
}
#if (!OPCUA_EXCLUDE_InitializationStrings)
/// <summary>
/// Initializes the instance.
/// </summary>
protected override void Initialize(ISystemContext context)
{
Initialize(context, InitializationString);
InitializeOptionalChildren(context);
}
/// <summary>
/// Initializes the any option children defined for the instance.
/// </summary>
protected override void InitializeOptionalChildren(ISystemContext context)
{
base.InitializeOptionalChildren(context);
}
#region Initialization String
private const string InitializationString =
"AQAAACYAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvUHVibGlzaGVyL/////8EYYIKBAAAAAEA" +
"FQAAAFB1Ymxpc2hOb2RlTWV0aG9kVHlwZQEBAQAALwEBAQABAAAAAQH/////AQAAABVgqQoCAAAAAAAO" +
"AAAASW5wdXRBcmd1bWVudHMBAQIAAC4ARAIAAACWAgAAAAEAKgEBMgAAAAYAAABOb2RlSUQADP////8A" +
"AAAAAwAAAAAVAAAAVGhlIE5vZGVJRCB0byBwdWJsaXNoAQAqAQFVAAAAEQAAAFNlcnZlckVuZHBvaW50" +
"VXJsAAz/////AAAAAAMAAAAALQAAAFRoZSBzZXJ2ZXIgZW5kcG9pbnQgVVJMIHRvIGdyYWIgdGhlIG5v" +
"ZGUgZnJvbQEAKAEBAAAAAQH/////AAAAAA==";
#endregion
#endif
#endregion
#region Event Callbacks
/// <summary>
/// Raised when the the method is called.
/// </summary>
public PublishNodeMethodStateMethodCallHandler OnCall;
#endregion
#region Public Properties
#endregion
#region Overridden Methods
/// <summary>
/// Invokes the method, returns the result and output argument.
/// </summary>
/// <param name="context">The current context.</param>
/// <param name="objectId">The id of the object.</param>
/// <param name="inputArguments">The input arguments which have been already validated.</param>
/// <param name="outputArguments">The output arguments which have initialized with thier default values.</param>
/// <returns></returns>
protected override ServiceResult Call(
ISystemContext context,
NodeId objectId,
IList<object> inputArguments,
IList<object> outputArguments)
{
if (OnCall == null)
{
return base.Call(context, objectId, inputArguments, outputArguments);
}
ServiceResult result = null;
string nodeID = (string)inputArguments[0];
string serverEndpointUrl = (string)inputArguments[1];
if (OnCall != null)
{
result = OnCall(
context,
this,
objectId,
nodeID,
serverEndpointUrl);
}
return result;
}
#endregion
#region Private Fields
#endregion
}
/// <summary>
/// Used to receive notifications when the method is called.
/// </summary>
/// <exclude />
public delegate ServiceResult PublishNodeMethodStateMethodCallHandler(
ISystemContext context,
MethodState method,
NodeId objectId,
string nodeID,
string serverEndpointUrl);
#endif
#endregion
#region UnPublishNodeMethodState Class
#if (!OPCUA_EXCLUDE_UnPublishNodeMethodState)
/// <summary>
/// Stores an instance of the UnPublishNodeMethodType Method.
/// </summary>
/// <exclude />
[System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")]
public partial class UnPublishNodeMethodState : MethodState
{
#region Constructors
/// <summary>
/// Initializes the type with its default attribute values.
/// </summary>
public UnPublishNodeMethodState(NodeState parent) : base(parent)
{
}
/// <summary>
/// Constructs an instance of a node.
/// </summary>
/// <param name="parent">The parent.</param>
/// <returns>The new node.</returns>
public new static NodeState Construct(NodeState parent)
{
return new UnPublishNodeMethodState(parent);
}
#if (!OPCUA_EXCLUDE_InitializationStrings)
/// <summary>
/// Initializes the instance.
/// </summary>
protected override void Initialize(ISystemContext context)
{
Initialize(context, InitializationString);
InitializeOptionalChildren(context);
}
/// <summary>
/// Initializes the any option children defined for the instance.
/// </summary>
protected override void InitializeOptionalChildren(ISystemContext context)
{
base.InitializeOptionalChildren(context);
}
#region Initialization String
private const string InitializationString =
"AQAAACYAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvUHVibGlzaGVyL/////8EYYIKBAAAAAEA" +
"FwAAAFVuUHVibGlzaE5vZGVNZXRob2RUeXBlAQEDAAAvAQEDAAMAAAABAf////8BAAAAFWCpCgIAAAAA" +
"AA4AAABJbnB1dEFyZ3VtZW50cwEBBAAALgBEBAAAAJYCAAAAAQAqAQEyAAAABgAAAE5vZGVJRAAM////" +
"/wAAAAADAAAAABUAAABUaGUgTm9kZUlEIHRvIHB1Ymxpc2gBACoBAVUAAAARAAAAU2VydmVyRW5kcG9p" +
"bnRVcmwADP////8AAAAAAwAAAAAtAAAAVGhlIHNlcnZlciBlbmRwb2ludCBVUkwgdG8gZ3JhYiB0aGUg" +
"bm9kZSBmcm9tAQAoAQEAAAABAf////8AAAAA";
#endregion
#endif
#endregion
#region Event Callbacks
/// <summary>
/// Raised when the the method is called.
/// </summary>
public UnPublishNodeMethodStateMethodCallHandler OnCall;
#endregion
#region Public Properties
#endregion
#region Overridden Methods
/// <summary>
/// Invokes the method, returns the result and output argument.
/// </summary>
/// <param name="context">The current context.</param>
/// <param name="objectId">The id of the object.</param>
/// <param name="inputArguments">The input arguments which have been already validated.</param>
/// <param name="outputArguments">The output arguments which have initialized with thier default values.</param>
/// <returns></returns>
protected override ServiceResult Call(
ISystemContext context,
NodeId objectId,
IList<object> inputArguments,
IList<object> outputArguments)
{
if (OnCall == null)
{
return base.Call(context, objectId, inputArguments, outputArguments);
}
ServiceResult result = null;
string nodeID = (string)inputArguments[0];
string serverEndpointUrl = (string)inputArguments[1];
if (OnCall != null)
{
result = OnCall(
context,
this,
objectId,
nodeID,
serverEndpointUrl);
}
return result;
}
#endregion
#region Private Fields
#endregion
}
/// <summary>
/// Used to receive notifications when the method is called.
/// </summary>
/// <exclude />
public delegate ServiceResult UnPublishNodeMethodStateMethodCallHandler(
ISystemContext context,
MethodState method,
NodeId objectId,
string nodeID,
string serverEndpointUrl);
#endif
#endregion
#region GetListOfPublishedNodesMethodState Class
#if (!OPCUA_EXCLUDE_GetListOfPublishedNodesMethodState)
/// <summary>
/// Stores an instance of the GetListOfPublishedNodesMethodType Method.
/// </summary>
/// <exclude />
[System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")]
public partial class GetListOfPublishedNodesMethodState : MethodState
{
#region Constructors
/// <summary>
/// Initializes the type with its default attribute values.
/// </summary>
public GetListOfPublishedNodesMethodState(NodeState parent) : base(parent)
{
}
/// <summary>
/// Constructs an instance of a node.
/// </summary>
/// <param name="parent">The parent.</param>
/// <returns>The new node.</returns>
public new static NodeState Construct(NodeState parent)
{
return new GetListOfPublishedNodesMethodState(parent);
}
#if (!OPCUA_EXCLUDE_InitializationStrings)
/// <summary>
/// Initializes the instance.
/// </summary>
protected override void Initialize(ISystemContext context)
{
Initialize(context, InitializationString);
InitializeOptionalChildren(context);
}
/// <summary>
/// Initializes the any option children defined for the instance.
/// </summary>
protected override void InitializeOptionalChildren(ISystemContext context)
{
base.InitializeOptionalChildren(context);
}
#region Initialization String
private const string InitializationString =
"AQAAACYAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvUHVibGlzaGVyL/////8EYYIKBAAAAAEA" +
"IQAAAEdldExpc3RPZlB1Ymxpc2hlZE5vZGVzTWV0aG9kVHlwZQEBBQAALwEBBQAFAAAAAQH/////AQAA" +
"ABVgqQoCAAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQEGAAAuAEQGAAAAlgEAAAABACoBAVUAAAAIAAAA" +
"Tm9kZUxpc3QADP////8AAAAAAwAAAAA2AAAAVGhlIEpTT04tZm9ybWF0dGVkIG5vZGUgbGlzdCBjdXJy" +
"ZW50bHkgYmVpbmcgcHVibGlzaGVkAQAoAQEAAAABAf////8AAAAA";
#endregion
#endif
#endregion
#region Event Callbacks
/// <summary>
/// Raised when the the method is called.
/// </summary>
public GetListOfPublishedNodesMethodStateMethodCallHandler OnCall;
#endregion
#region Public Properties
#endregion
#region Overridden Methods
/// <summary>
/// Invokes the method, returns the result and output argument.
/// </summary>
/// <param name="context">The current context.</param>
/// <param name="objectId">The id of the object.</param>
/// <param name="inputArguments">The input arguments which have been already validated.</param>
/// <param name="outputArguments">The output arguments which have initialized with thier default values.</param>
/// <returns></returns>
protected override ServiceResult Call(
ISystemContext context,
NodeId objectId,
IList<object> inputArguments,
IList<object> outputArguments)
{
if (OnCall == null)
{
return base.Call(context, objectId, inputArguments, outputArguments);
}
ServiceResult result = null;
string nodeList = (string)outputArguments[0];
if (OnCall != null)
{
result = OnCall(
context,
this,
objectId,
ref nodeList);
}
outputArguments[0] = nodeList;
return result;
}
#endregion
#region Private Fields
#endregion
}
/// <summary>
/// Used to receive notifications when the method is called.
/// </summary>
/// <exclude />
public delegate ServiceResult GetListOfPublishedNodesMethodStateMethodCallHandler(
ISystemContext context,
MethodState method,
NodeId objectId,
ref string nodeList);
#endif
#endregion
#region PublisherState Class
#if (!OPCUA_EXCLUDE_PublisherState)
/// <summary>
/// Stores an instance of the PublisherType ObjectType.
/// </summary>
/// <exclude />
[System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")]
public partial class PublisherState : BaseObjectState
{
#region Constructors
/// <summary>
/// Initializes the type with its default attribute values.
/// </summary>
public PublisherState(NodeState parent) : base(parent)
{
}
/// <summary>
/// Returns the id of the default type definition node for the instance.
/// </summary>
protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris)
{
return Opc.Ua.NodeId.Create(Publisher.ObjectTypes.PublisherType, Publisher.Namespaces.Publisher, namespaceUris);
}
#if (!OPCUA_EXCLUDE_InitializationStrings)
/// <summary>
/// Initializes the instance.
/// </summary>
protected override void Initialize(ISystemContext context)
{
Initialize(context, InitializationString);
InitializeOptionalChildren(context);
}
/// <summary>
/// Initializes the any option children defined for the instance.
/// </summary>
protected override void InitializeOptionalChildren(ISystemContext context)
{
base.InitializeOptionalChildren(context);
}
#region Initialization String
private const string InitializationString =
"AQAAACYAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvUHVibGlzaGVyL/////+EYIAAAQAAAAEA" +
"FQAAAFB1Ymxpc2hlclR5cGVJbnN0YW5jZQEBBwABAQcAAf////8EAAAABGGCCgQAAAABAAsAAABQdWJs" +
"aXNoTm9kZQEBCAAALwEBCAAIAAAAAQH/////AQAAABVgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMB" +
"AQkAAC4ARAkAAACWAgAAAAEAKgEBMgAAAAYAAABOb2RlSUQADP////8AAAAAAwAAAAAVAAAAVGhlIE5v" +
"ZGVJRCB0byBwdWJsaXNoAQAqAQFVAAAAEQAAAFNlcnZlckVuZHBvaW50VXJsAAz/////AAAAAAMAAAAA" +
"LQAAAFRoZSBzZXJ2ZXIgZW5kcG9pbnQgVVJMIHRvIGdyYWIgdGhlIG5vZGUgZnJvbQEAKAEBAAAAAQH/" +
"////AAAAAARhggoEAAAAAQANAAAAVW5QdWJsaXNoTm9kZQEBCgAALwEBCgAKAAAAAQH/////AQAAABVg" +
"qQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAQsAAC4ARAsAAACWAgAAAAEAKgEBMgAAAAYAAABOb2Rl" +
"SUQADP////8AAAAAAwAAAAAVAAAAVGhlIE5vZGVJRCB0byBwdWJsaXNoAQAqAQFVAAAAEQAAAFNlcnZl" +
"ckVuZHBvaW50VXJsAAz/////AAAAAAMAAAAALQAAAFRoZSBzZXJ2ZXIgZW5kcG9pbnQgVVJMIHRvIGdy" +
"YWIgdGhlIG5vZGUgZnJvbQEAKAEBAAAAAQH/////AAAAAARhggoEAAAAAQAXAAAAR2V0TGlzdE9mUHVi" +
"bGlzaGVkTm9kZXMBAQwAAC8BAQwADAAAAAEB/////wEAAAAVYKkKAgAAAAAADwAAAE91dHB1dEFyZ3Vt" +
"ZW50cwEBDQAALgBEDQAAAJYBAAAAAQAqAQFVAAAACAAAAE5vZGVMaXN0AAz/////AAAAAAMAAAAANgAA" +
"AFRoZSBKU09OLWZvcm1hdHRlZCBub2RlIGxpc3QgY3VycmVudGx5IGJlaW5nIHB1Ymxpc2hlZAEAKAEB" +
"AAAAAQH/////AAAAABVgiQoCAAAAAQAQAAAAQ29ubmVjdGlvblN0cmluZwEBDgAALwA/DgAAAAAM////" +
"/wIC/////wAAAAA=";
#endregion
#endif
#endregion
#region Public Properties
/// <summary>
/// A description for the PublishNodeMethodType Method.
/// </summary>
public PublishNodeMethodState PublishNode
{
get
{
return m_publishNodeMethod;
}
set
{
if (!Object.ReferenceEquals(m_publishNodeMethod, value))
{
ChangeMasks |= NodeStateChangeMasks.Children;
}
m_publishNodeMethod = value;
}
}
/// <summary>
/// A description for the UnPublishNodeMethodType Method.
/// </summary>
public UnPublishNodeMethodState UnPublishNode
{
get
{
return m_unPublishNodeMethod;
}
set
{
if (!Object.ReferenceEquals(m_unPublishNodeMethod, value))
{
ChangeMasks |= NodeStateChangeMasks.Children;
}
m_unPublishNodeMethod = value;
}
}
/// <summary>
/// A description for the GetListOfPublishedNodesMethodType Method.
/// </summary>
public GetListOfPublishedNodesMethodState GetListOfPublishedNodes
{
get
{
return m_getListOfPublishedNodesMethod;
}
set
{
if (!Object.ReferenceEquals(m_getListOfPublishedNodesMethod, value))
{
ChangeMasks |= NodeStateChangeMasks.Children;
}
m_getListOfPublishedNodesMethod = value;
}
}
/// <summary>
/// A description for the ConnectionString Variable.
/// </summary>
public BaseDataVariableState<string> ConnectionString
{
get
{
return m_connectionString;
}
set
{
if (!Object.ReferenceEquals(m_connectionString, value))
{
ChangeMasks |= NodeStateChangeMasks.Children;
}
m_connectionString = value;
}
}
#endregion
#region Overridden Methods
/// <summary>
/// Populates a list with the children that belong to the node.
/// </summary>
/// <param name="context">The context for the system being accessed.</param>
/// <param name="children">The list of children to populate.</param>
public override void GetChildren(
ISystemContext context,
IList<BaseInstanceState> children)
{
if (m_publishNodeMethod != null)
{
children.Add(m_publishNodeMethod);
}
if (m_unPublishNodeMethod != null)
{
children.Add(m_unPublishNodeMethod);
}
if (m_getListOfPublishedNodesMethod != null)
{
children.Add(m_getListOfPublishedNodesMethod);
}
if (m_connectionString != null)
{
children.Add(m_connectionString);
}
base.GetChildren(context, children);
}
/// <summary>
/// Finds the child with the specified browse name.
/// </summary>
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 Publisher.BrowseNames.PublishNode:
{
if (createOrReplace)
{
if (PublishNode == null)
{
if (replacement == null)
{
PublishNode = new PublishNodeMethodState(this);
}
else
{
PublishNode = (PublishNodeMethodState)replacement;
}
}
}
instance = PublishNode;
break;
}
case Publisher.BrowseNames.UnPublishNode:
{
if (createOrReplace)
{
if (UnPublishNode == null)
{
if (replacement == null)
{
UnPublishNode = new UnPublishNodeMethodState(this);
}
else
{
UnPublishNode = (UnPublishNodeMethodState)replacement;
}
}
}
instance = UnPublishNode;
break;
}
case Publisher.BrowseNames.GetListOfPublishedNodes:
{
if (createOrReplace)
{
if (GetListOfPublishedNodes == null)
{
if (replacement == null)
{
GetListOfPublishedNodes = new GetListOfPublishedNodesMethodState(this);
}
else
{
GetListOfPublishedNodes = (GetListOfPublishedNodesMethodState)replacement;
}
}
}
instance = GetListOfPublishedNodes;
break;
}
case Publisher.BrowseNames.ConnectionString:
{
if (createOrReplace)
{
if (ConnectionString == null)
{
if (replacement == null)
{
ConnectionString = new BaseDataVariableState<string>(this);
}
else
{
ConnectionString = (BaseDataVariableState<string>)replacement;
}
}
}
instance = ConnectionString;
break;
}
}
if (instance != null)
{
return instance;
}
return base.FindChild(context, browseName, createOrReplace, replacement);
}
#endregion
#region Private Fields
private PublishNodeMethodState m_publishNodeMethod;
private UnPublishNodeMethodState m_unPublishNodeMethod;
private GetListOfPublishedNodesMethodState m_getListOfPublishedNodesMethod;
private BaseDataVariableState<string> m_connectionString;
#endregion
}
#endif
#endregion
}

Просмотреть файл

@ -0,0 +1,342 @@
/* ========================================================================
* 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/
* ======================================================================*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Xml;
using System.Runtime.Serialization;
using Opc.Ua;
namespace Publisher
{
#region Method Identifiers
/// <summary>
/// A class that declares constants for all Methods in the Model Design.
/// </summary>
/// <exclude />
[System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")]
public static partial class Methods
{
/// <summary>
/// The identifier for the PublisherType_PublishNode Method.
/// </summary>
public const uint PublisherType_PublishNode = 8;
/// <summary>
/// The identifier for the PublisherType_UnPublishNode Method.
/// </summary>
public const uint PublisherType_UnPublishNode = 10;
/// <summary>
/// The identifier for the PublisherType_GetListOfPublishedNodes Method.
/// </summary>
public const uint PublisherType_GetListOfPublishedNodes = 12;
/// <summary>
/// The identifier for the PublisherInstance_PublishNode Method.
/// </summary>
public const uint PublisherInstance_PublishNode = 16;
/// <summary>
/// The identifier for the PublisherInstance_UnPublishNode Method.
/// </summary>
public const uint PublisherInstance_UnPublishNode = 18;
/// <summary>
/// The identifier for the PublisherInstance_GetListOfPublishedNodes Method.
/// </summary>
public const uint PublisherInstance_GetListOfPublishedNodes = 20;
}
#endregion
#region Object Identifiers
/// <summary>
/// A class that declares constants for all Objects in the Model Design.
/// </summary>
/// <exclude />
[System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")]
public static partial class Objects
{
/// <summary>
/// The identifier for the PublisherInstance Object.
/// </summary>
public const uint PublisherInstance = 15;
}
#endregion
#region ObjectType Identifiers
/// <summary>
/// A class that declares constants for all ObjectTypes in the Model Design.
/// </summary>
/// <exclude />
[System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")]
public static partial class ObjectTypes
{
/// <summary>
/// The identifier for the PublisherType ObjectType.
/// </summary>
public const uint PublisherType = 7;
}
#endregion
#region Variable Identifiers
/// <summary>
/// A class that declares constants for all Variables in the Model Design.
/// </summary>
/// <exclude />
[System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")]
public static partial class Variables
{
/// <summary>
/// The identifier for the PublisherType_PublishNode_InputArguments Variable.
/// </summary>
public const uint PublisherType_PublishNode_InputArguments = 9;
/// <summary>
/// The identifier for the PublisherType_UnPublishNode_InputArguments Variable.
/// </summary>
public const uint PublisherType_UnPublishNode_InputArguments = 11;
/// <summary>
/// The identifier for the PublisherType_GetListOfPublishedNodes_OutputArguments Variable.
/// </summary>
public const uint PublisherType_GetListOfPublishedNodes_OutputArguments = 13;
/// <summary>
/// The identifier for the PublisherType_ConnectionString Variable.
/// </summary>
public const uint PublisherType_ConnectionString = 14;
/// <summary>
/// The identifier for the PublisherInstance_PublishNode_InputArguments Variable.
/// </summary>
public const uint PublisherInstance_PublishNode_InputArguments = 17;
/// <summary>
/// The identifier for the PublisherInstance_UnPublishNode_InputArguments Variable.
/// </summary>
public const uint PublisherInstance_UnPublishNode_InputArguments = 19;
/// <summary>
/// The identifier for the PublisherInstance_GetListOfPublishedNodes_OutputArguments Variable.
/// </summary>
public const uint PublisherInstance_GetListOfPublishedNodes_OutputArguments = 21;
/// <summary>
/// The identifier for the PublisherInstance_ConnectionString Variable.
/// </summary>
public const uint PublisherInstance_ConnectionString = 22;
}
#endregion
#region Method Node Identifiers
/// <summary>
/// A class that declares constants for all Methods in the Model Design.
/// </summary>
/// <exclude />
[System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")]
public static partial class MethodIds
{
/// <summary>
/// The identifier for the PublisherType_PublishNode Method.
/// </summary>
public static readonly ExpandedNodeId PublisherType_PublishNode = new ExpandedNodeId(Publisher.Methods.PublisherType_PublishNode, Publisher.Namespaces.Publisher);
/// <summary>
/// The identifier for the PublisherType_UnPublishNode Method.
/// </summary>
public static readonly ExpandedNodeId PublisherType_UnPublishNode = new ExpandedNodeId(Publisher.Methods.PublisherType_UnPublishNode, Publisher.Namespaces.Publisher);
/// <summary>
/// The identifier for the PublisherType_GetListOfPublishedNodes Method.
/// </summary>
public static readonly ExpandedNodeId PublisherType_GetListOfPublishedNodes = new ExpandedNodeId(Publisher.Methods.PublisherType_GetListOfPublishedNodes, Publisher.Namespaces.Publisher);
/// <summary>
/// The identifier for the PublisherInstance_PublishNode Method.
/// </summary>
public static readonly ExpandedNodeId PublisherInstance_PublishNode = new ExpandedNodeId(Publisher.Methods.PublisherInstance_PublishNode, Publisher.Namespaces.Publisher);
/// <summary>
/// The identifier for the PublisherInstance_UnPublishNode Method.
/// </summary>
public static readonly ExpandedNodeId PublisherInstance_UnPublishNode = new ExpandedNodeId(Publisher.Methods.PublisherInstance_UnPublishNode, Publisher.Namespaces.Publisher);
/// <summary>
/// The identifier for the PublisherInstance_GetListOfPublishedNodes Method.
/// </summary>
public static readonly ExpandedNodeId PublisherInstance_GetListOfPublishedNodes = new ExpandedNodeId(Publisher.Methods.PublisherInstance_GetListOfPublishedNodes, Publisher.Namespaces.Publisher);
}
#endregion
#region Object Node Identifiers
/// <summary>
/// A class that declares constants for all Objects in the Model Design.
/// </summary>
/// <exclude />
[System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")]
public static partial class ObjectIds
{
/// <summary>
/// The identifier for the PublisherInstance Object.
/// </summary>
public static readonly ExpandedNodeId PublisherInstance = new ExpandedNodeId(Publisher.Objects.PublisherInstance, Publisher.Namespaces.Publisher);
}
#endregion
#region ObjectType Node Identifiers
/// <summary>
/// A class that declares constants for all ObjectTypes in the Model Design.
/// </summary>
/// <exclude />
[System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")]
public static partial class ObjectTypeIds
{
/// <summary>
/// The identifier for the PublisherType ObjectType.
/// </summary>
public static readonly ExpandedNodeId PublisherType = new ExpandedNodeId(Publisher.ObjectTypes.PublisherType, Publisher.Namespaces.Publisher);
}
#endregion
#region Variable Node Identifiers
/// <summary>
/// A class that declares constants for all Variables in the Model Design.
/// </summary>
/// <exclude />
[System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")]
public static partial class VariableIds
{
/// <summary>
/// The identifier for the PublisherType_PublishNode_InputArguments Variable.
/// </summary>
public static readonly ExpandedNodeId PublisherType_PublishNode_InputArguments = new ExpandedNodeId(Publisher.Variables.PublisherType_PublishNode_InputArguments, Publisher.Namespaces.Publisher);
/// <summary>
/// The identifier for the PublisherType_UnPublishNode_InputArguments Variable.
/// </summary>
public static readonly ExpandedNodeId PublisherType_UnPublishNode_InputArguments = new ExpandedNodeId(Publisher.Variables.PublisherType_UnPublishNode_InputArguments, Publisher.Namespaces.Publisher);
/// <summary>
/// The identifier for the PublisherType_GetListOfPublishedNodes_OutputArguments Variable.
/// </summary>
public static readonly ExpandedNodeId PublisherType_GetListOfPublishedNodes_OutputArguments = new ExpandedNodeId(Publisher.Variables.PublisherType_GetListOfPublishedNodes_OutputArguments, Publisher.Namespaces.Publisher);
/// <summary>
/// The identifier for the PublisherType_ConnectionString Variable.
/// </summary>
public static readonly ExpandedNodeId PublisherType_ConnectionString = new ExpandedNodeId(Publisher.Variables.PublisherType_ConnectionString, Publisher.Namespaces.Publisher);
/// <summary>
/// The identifier for the PublisherInstance_PublishNode_InputArguments Variable.
/// </summary>
public static readonly ExpandedNodeId PublisherInstance_PublishNode_InputArguments = new ExpandedNodeId(Publisher.Variables.PublisherInstance_PublishNode_InputArguments, Publisher.Namespaces.Publisher);
/// <summary>
/// The identifier for the PublisherInstance_UnPublishNode_InputArguments Variable.
/// </summary>
public static readonly ExpandedNodeId PublisherInstance_UnPublishNode_InputArguments = new ExpandedNodeId(Publisher.Variables.PublisherInstance_UnPublishNode_InputArguments, Publisher.Namespaces.Publisher);
/// <summary>
/// The identifier for the PublisherInstance_GetListOfPublishedNodes_OutputArguments Variable.
/// </summary>
public static readonly ExpandedNodeId PublisherInstance_GetListOfPublishedNodes_OutputArguments = new ExpandedNodeId(Publisher.Variables.PublisherInstance_GetListOfPublishedNodes_OutputArguments, Publisher.Namespaces.Publisher);
/// <summary>
/// The identifier for the PublisherInstance_ConnectionString Variable.
/// </summary>
public static readonly ExpandedNodeId PublisherInstance_ConnectionString = new ExpandedNodeId(Publisher.Variables.PublisherInstance_ConnectionString, Publisher.Namespaces.Publisher);
}
#endregion
#region BrowseName Declarations
/// <summary>
/// Declares all of the BrowseNames used in the Model Design.
/// </summary>
[System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")]
public static partial class BrowseNames
{
/// <summary>
/// The BrowseName for the ConnectionString component.
/// </summary>
public const string ConnectionString = "ConnectionString";
/// <summary>
/// The BrowseName for the GetListOfPublishedNodes component.
/// </summary>
public const string GetListOfPublishedNodes = "GetListOfPublishedNodes";
/// <summary>
/// The BrowseName for the PublisherInstance component.
/// </summary>
public const string PublisherInstance = "PublisherInstance";
/// <summary>
/// The BrowseName for the PublisherType component.
/// </summary>
public const string PublisherType = "PublisherType";
/// <summary>
/// The BrowseName for the PublishNode component.
/// </summary>
public const string PublishNode = "PublishNode";
/// <summary>
/// The BrowseName for the UnPublishNode component.
/// </summary>
public const string UnPublishNode = "UnPublishNode";
}
#endregion
#region Namespace Declarations
/// <summary>
/// Defines constants for all namespaces referenced by the model design.
/// </summary>
[System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")]
public static partial class Namespaces
{
/// <summary>
/// The URI for the OpcUa namespace (.NET code namespace is 'Opc.Ua').
/// </summary>
public const string OpcUa = "http://opcfoundation.org/UA/";
/// <summary>
/// The URI for the OpcUaXsd namespace (.NET code namespace is 'Opc.Ua').
/// </summary>
public const string OpcUaXsd = "http://opcfoundation.org/UA/2008/02/Types.xsd";
/// <summary>
/// The URI for the Publisher namespace (.NET code namespace is 'Publisher').
/// </summary>
public const string Publisher = "http://opcfoundation.org/UA/Publisher/";
}
#endregion
}

Просмотреть файл

@ -0,0 +1,40 @@
/* ========================================================================
* 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/
* ======================================================================*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Xml;
using System.Runtime.Serialization;
using Opc.Ua;
namespace Publisher
{
}

Двоичные данные
src/Opc.Ua.Publisher.Module/Publisher.PredefinedNodes.uanodes Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<opc:ModelDesign
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:opc="http://opcfoundation.org/UA/ModelDesign.xsd"
xmlns:ua="http://opcfoundation.org/UA/"
xmlns:uax="http://opcfoundation.org/UA/2008/02/Types.xsd"
xmlns="http://opcfoundation.org/UA/Publisher/"
TargetNamespace="http://opcfoundation.org/UA/Publisher/"
>
<!--
This element defines the mappings between the URIs used to identify namespaces and the symbols used in code.
User defined design files can include other user defined design files.
The location of included design files is specified with the FilePath attribute (absolute or relative path without the .xml suffix).
-->
<opc:Namespaces>
<opc:Namespace Name="OpcUa" Prefix="Opc.Ua" InternalPrefix="Opc.Ua.Server" XmlNamespace="http://opcfoundation.org/UA/2008/02/Types.xsd">http://opcfoundation.org/UA/</opc:Namespace>
<opc:Namespace Name="Publisher" Prefix="Publisher">http://opcfoundation.org/UA/Publisher/</opc:Namespace>
</opc:Namespaces>
<opc:Method SymbolicName="PublishNodeMethodType" BaseType="ua:BaseObjectType">
<opc:InputArguments>
<opc:Argument Name="NodeID" DataType="ua:String" ValueRank="Scalar" AccessLevel="ReadWrite">
<opc:Description>The NodeID to publish</opc:Description>
</opc:Argument>
<opc:Argument Name="ServerEndpointUrl" DataType="ua:String" ValueRank="Scalar" AccessLevel="ReadWrite">
<opc:Description>The server endpoint URL to grab the node from</opc:Description>
</opc:Argument>
</opc:InputArguments>
</opc:Method>
<opc:Method SymbolicName="UnPublishNodeMethodType" BaseType="ua:BaseObjectType">
<opc:InputArguments>
<opc:Argument Name="NodeID" DataType="ua:String" ValueRank="Scalar" AccessLevel="ReadWrite">
<opc:Description>The NodeID to publish</opc:Description>
</opc:Argument>
<opc:Argument Name="ServerEndpointUrl" DataType="ua:String" ValueRank="Scalar" AccessLevel="ReadWrite">
<opc:Description>The server endpoint URL to grab the node from</opc:Description>
</opc:Argument>
</opc:InputArguments>
</opc:Method>
<opc:Method SymbolicName="GetListOfPublishedNodesMethodType" BaseType="ua:BaseObjectType">
<opc:OutputArguments>
<opc:Argument Name="NodeList" DataType="ua:String" ValueRank="Scalar" AccessLevel="ReadWrite">
<opc:Description>The JSON-formatted node list currently being published</opc:Description>
</opc:Argument>
</opc:OutputArguments>
</opc:Method>
<opc:ObjectType SymbolicName="PublisherType" BaseType="ua:BaseObjectType" SupportsEvents="true">
<opc:Description>Publisher</opc:Description>
<opc:Children>
<opc:Method SymbolicName="PublishNode" TypeDefinition="PublishNodeMethodType" />
<opc:Method SymbolicName="UnPublishNode" TypeDefinition="UnPublishNodeMethodType" />
<opc:Method SymbolicName="GetListOfPublishedNodes" TypeDefinition="GetListOfPublishedNodesMethodType"/>
<opc:Variable SymbolicName="ConnectionString" DataType="ua:String" ValueRank="Scalar" AccessLevel="Write" />
</opc:Children>
</opc:ObjectType>
<!-- Declare an instance of a Publisher. -->
<opc:Object SymbolicName="PublisherInstance" TypeDefinition="PublisherType" SupportsEvents="true">
<opc:BrowseName>PublisherInstance</opc:BrowseName>
<!--Link the instance back to the ObjectsFolder-->
<opc:References>
<opc:Reference IsInverse="true">
<opc:ReferenceType>ua:Organizes</opc:ReferenceType>
<opc:TargetId>ua:ObjectsFolder</opc:TargetId>
</opc:Reference>
</opc:References>
</opc:Object>
</opc:ModelDesign>

Просмотреть файл

@ -0,0 +1,29 @@
using Opc.Ua;
using Opc.Ua.Server;
using System.Collections.Generic;
namespace Publisher
{
public partial class PublisherServer : StandardServer
{
protected override MasterNodeManager CreateMasterNodeManager(IServerInternal server, ApplicationConfiguration configuration)
{
List<INodeManager> nodeManagers = new List<INodeManager>();
nodeManagers.Add(new PublisherNodeManager(server, configuration));
return new MasterNodeManager(server, configuration, null, nodeManagers.ToArray());
}
protected override ServerProperties LoadServerProperties()
{
ServerProperties properties = new ServerProperties();
properties.ManufacturerName = "Contoso";
properties.ProductName = "OPC UA Factory Publisher";
properties.ProductUri = "";
properties.SoftwareVersion = Utils.GetAssemblySoftwareVersion();
properties.BuildNumber = Utils.GetAssemblyBuildNumber();
properties.BuildDate = Utils.GetAssemblyTimestamp();
return properties;
}
}
}

Просмотреть файл

@ -0,0 +1,305 @@

using IoTHubCredentialTools;
using Newtonsoft.Json;
using Opc.Ua;
using Opc.Ua.Client;
using Opc.Ua.Publisher;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace Publisher
{
public partial class PublisherState
{
/// <summary>
/// Called after the class is created
/// </summary>
protected override void OnAfterCreate(ISystemContext context, NodeState node)
{
base.OnAfterCreate(context, node);
PublishNode.OnCallMethod = PublishNodeMethod;
UnPublishNode.OnCallMethod = UnPublishNodeMethod;
GetListOfPublishedNodes.OnCallMethod = GetListOfPublishedNodesMethod;
ConnectionString.OnWriteValue = ConnectionStringWrite;
}
/// <summary>
/// Method exposed as a node in the server to publish a node to IoT Hub that it is connected to
/// </summary>
private ServiceResult PublishNodeMethod(ISystemContext context, MethodState method, IList<object> inputArguments, IList<object> outputArguments)
{
if (inputArguments[0] == null || inputArguments[1] == null)
{
Module.Trace("PublishNodeMethod: Invalid Arguments!");
return ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments!");
}
string nodeID = inputArguments[0] as string;
string uri = inputArguments[1] as string;
if (string.IsNullOrEmpty(nodeID) || string.IsNullOrEmpty(uri))
{
Module.Trace("PublishNodeMethod: Arguments are not valid strings!");
return ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments as strings!");
}
NodeLookup lookup = new NodeLookup();
lookup.NodeID = new NodeId(nodeID);
try
{
lookup.EndPointURL = new Uri(uri);
}
catch (UriFormatException)
{
Module.Trace("PublishNodeMethod: Invalid endpoint URL!");
return ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide a valid OPC UA endpoint URL as second argument!");
}
// create session, if it doesn't exist already and complete asynchonourly (do to thread dependencies in the UA stack)
if (!Module.m_endpointUrls.Contains(lookup.EndPointURL))
{
try
{
Task.Run(() =>
{
Module.Trace("PublishNodeMethod: Session not found, creating one for " + lookup.EndPointURL);
Module.EndpointConnect(lookup.EndPointURL).Wait();
Module.Trace("PublishNodeMethod: Session created.");
return DoPublish(lookup);
});
return ServiceResult.Create(StatusCodes.GoodCompletesAsynchronously, "Publishing takes a while, please be patient!");
}
catch (Exception ex)
{
Module.Trace("PublishNodeMethod: Exception: " + ex.ToString());
return ServiceResult.Create(ex, StatusCodes.BadUnexpectedError, "Unexpected error publishing node: " + ex.Message);
}
}
else
{
// complete synchonoursly
return DoPublish(lookup);
}
}
/// <summary>
/// Publishes a single Nodelookup
/// </summary>
private ServiceResult DoPublish(NodeLookup lookup)
{
try
{
// find the right session using our lookup
Session matchingSession = null;
foreach (Session session in Module.m_sessions)
{
char[] trimChars = { '/', ' ' };
if (session.Endpoint.EndpointUrl.TrimEnd(trimChars).StartsWith(lookup.EndPointURL.ToString().TrimEnd(trimChars), StringComparison.OrdinalIgnoreCase))
{
lookup.EndPointURL = new Uri(session.Endpoint.EndpointUrl);
matchingSession = session;
break;
}
}
if (matchingSession == null)
{
Module.Trace("PublishNodeMethod: No matching session found for " + lookup.EndPointURL.ToString());
return ServiceResult.Create(StatusCodes.BadSessionIdInvalid, "Session for published node not found!");
}
Module.Trace("PublishNodeMethod: Session found.");
// check if the node has already been published
foreach (MonitoredItem item in matchingSession.DefaultSubscription.MonitoredItems)
{
if (item.StartNodeId == lookup.NodeID)
{
Module.Trace("PublishNodeMethod: Node ID has already been published " + lookup.NodeID.ToString());
return ServiceResult.Create(StatusCodes.BadNodeIdExists, "Node has already been published!");
}
}
// subscribe to the node
Module.CreateMonitoredItem(lookup);
Module.Trace("PublishNodeMethod: Monitored item created.");
// update our data
Module.m_nodesLookups.Add(lookup);
if (!Module.m_endpointUrls.Contains(lookup.EndPointURL))
{
Module.m_endpointUrls.Add(lookup.EndPointURL);
}
//serialize Program.m_nodesLookups to disk
string publishedNodesFilePath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "publishednodes.json";
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GW_PNFP")))
{
publishedNodesFilePath = Environment.GetEnvironmentVariable("_GW_PNFP");
}
File.WriteAllText(publishedNodesFilePath, JsonConvert.SerializeObject(Module.m_nodesLookups));
Module.Trace("PublishNodeMethod: Successful publish: " + lookup.ToString());
return ServiceResult.Good;
}
catch (Exception ex)
{
Module.Trace("PublishNodeMethod: Exception: " + ex.ToString());
return ServiceResult.Create(ex, StatusCodes.BadUnexpectedError, "Unexpected error publishing node: " + ex.Message);
}
}
/// <summary>
/// Method exposed as a node in the server to un-publish a node from IoT Hub that it is connected to
/// </summary>
private ServiceResult UnPublishNodeMethod(ISystemContext context, MethodState method, IList<object> inputArguments, IList<object> outputArguments)
{
if (inputArguments[0] == null || inputArguments[1] == null)
{
Module.Trace("UnPublishNodeMethod: Invalid arguments!");
return ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments!");
}
string nodeID = inputArguments[0] as string;
string uri = inputArguments[1] as string;
if (string.IsNullOrEmpty(nodeID) || string.IsNullOrEmpty(uri))
{
Module.Trace("UnPublishNodeMethod: Arguments are not valid strings!");
return ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments as strings!");
}
NodeLookup lookup = new NodeLookup();
lookup.NodeID = new NodeId(nodeID);
try
{
lookup.EndPointURL = new Uri(uri);
}
catch (UriFormatException)
{
Module.Trace("UnPublishNodeMethod: Invalid endpoint URL!");
return ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide a valid OPC UA endpoint URL as second argument!");
}
// find the right session using our lookup
Session matchingSession = null;
foreach (Session session in Module.m_sessions)
{
char[] trimChars = { '/', ' ' };
if (session.Endpoint.EndpointUrl.TrimEnd(trimChars).Equals(lookup.EndPointURL.ToString().TrimEnd(trimChars), StringComparison.OrdinalIgnoreCase))
{
matchingSession = session;
break;
}
}
if (matchingSession == null)
{
Module.Trace("UnPublishNodeMethod: Session for published node not found: " + lookup.EndPointURL.ToString());
return ServiceResult.Create(StatusCodes.BadSessionIdInvalid, "Session for published node not found!");
}
// find the right monitored item to remove
foreach (MonitoredItem item in matchingSession.DefaultSubscription.MonitoredItems)
{
if (item.StartNodeId == lookup.NodeID)
{
matchingSession.DefaultSubscription.RemoveItem(item);
Module.Trace("UnPublishNodeMethod: Successful unpublish: " + lookup.NodeID.ToString());
// update our data on success only
// we keep the session to the server, as there may be other nodes still published on it
Module.m_nodesLookups.Remove(lookup);
//serialize Program.m_nodesLookups to disk
string publishedNodesFilePath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "publishednodes.json";
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GW_PNFP")))
{
publishedNodesFilePath = Environment.GetEnvironmentVariable("_GW_PNFP");
}
File.WriteAllText(publishedNodesFilePath, JsonConvert.SerializeObject(Module.m_nodesLookups));
return ServiceResult.Good;
}
}
Module.Trace("UnPublishNodeMethod: Monitored item for node ID not found " + lookup.NodeID.ToString());
return ServiceResult.Create(StatusCodes.BadNodeIdInvalid, "Monitored item for node ID not found!");
}
/// <summary>
/// Method exposed as a node in the server to get a list of published nodes
/// </summary>
private ServiceResult GetListOfPublishedNodesMethod(ISystemContext context, MethodState method, IList<object> inputArguments, IList<object> outputArguments)
{
outputArguments[0] = JsonConvert.SerializeObject(Module.m_nodesLookups);
Module.Trace("GetListOfPublishedNodesMethod: Success!");
return ServiceResult.Good;
}
/// <summary>
/// Data node in the server which registers ourselves with IoT Hub when this node is written to
/// </summary>
public ServiceResult ConnectionStringWrite(ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp)
{
var connectionString = value as string;
if (string.IsNullOrEmpty(connectionString))
{
Module.Trace("ConnectionStringWrite: Invalid Argument!");
return ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments as strings!");
}
statusCode = StatusCodes.Bad;
timestamp = DateTime.Now;
// read current connection string and compare to the one passed in
string currentConnectionString = SecureIoTHubToken.Read(Module.m_configuration.ApplicationName);
if (string.Equals(connectionString, currentConnectionString, StringComparison.OrdinalIgnoreCase))
{
Module.Trace("ConnectionStringWrite: Connection string up to date!");
return ServiceResult.Create(StatusCodes.Bad, "Connection string already up-to-date!");
}
// try to parse connection string
string[] parsedConnectionString = IoTHubRegistration.ParseConnectionString(connectionString, true);
if ((parsedConnectionString == null) || (parsedConnectionString.Length != 3))
{
Module.Trace("ConnectionStringWrite: Connection string parsing error: " + connectionString);
return ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Could not parse connection string!");
}
// write connection string
try
{
SecureIoTHubToken.Write(Module.m_configuration.ApplicationName, connectionString);
}
catch (Exception ex)
{
statusCode = StatusCodes.Bad;
Module.Trace("ConnectionStringWrite: Exception: " + ex.ToString());
return ServiceResult.Create(StatusCodes.Bad, "Publisher registration failed: " + ex.Message);
}
try
{
// try to configure our publisher component
Module.TryConfigurePublisherAsync().Wait();
}
catch (Exception ex)
{
statusCode = StatusCodes.Bad;
Module.Trace("ConnectionStringWrite: Exception: " + ex.ToString());
return ServiceResult.Create(StatusCodes.Bad, "Publisher configuration failed: " + ex.Message);
}
statusCode = StatusCodes.Good;
Module.Trace("ConnectionStringWrite: Success!");
return statusCode;
}
}
}

Просмотреть файл

@ -0,0 +1,21 @@
{
"version": "1.0.0-*",
"buildOptions": {
"embed": {
"includeFiles": [
"Publisher.PredefinedNodes.uanodes"
]
},
"debugType": "portable"
},
"dependencies": {
"OPCFoundation.NetStandard.Opc.Ua.SDK": "0.2.3",
"IoTHubCredentialTools": "1.0.0-*",
"Azure.IoT.Gateway.SDK.NetCore": "2017.3.27-beta"
},
"frameworks": {
"netstandard1.3": {}
}
}