This commit is contained in:
Spyros Garyfallos 2018-05-30 20:26:31 -07:00
Родитель 1e26a5147d
Коммит 4cb24cf68c
56 изменённых файлов: 400 добавлений и 171 удалений

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

@ -18,34 +18,10 @@ namespace Modules
{
//memory state
private TemperatureScale _scale;
private readonly ITemperatureModule _temperatureModuleProxy;
public NormalizeTemperatureModule(ITemperatureModule proxy)
{
_temperatureModuleProxy = proxy;
}
public Input<TemperatureModuleOutput> Temperature { get; set; }
public Output<TemperatureModuleOutput> NormalizedTemperature { get; set; }
public ModuleTwin<NormalizerTwin> Twin { get; set; }
public override async Task<ExecutionResult> RunAsync()
{
while (true)
{
Console.WriteLine("Temporary loop");
Thread.Sleep(1000);
}
var twin = await Twin.GetAsync();
_scale = twin.Scale;
return ExecutionResult.Ok;
}
public override void BuildSubscriptions()
{
Temperature.Subscribe(_temperatureModuleProxy.Temperature, async temp =>
Temperature.Subscribe(proxy.Temperature, async temp =>
{
Console.WriteLine("New Message in NormalizeTemperatureModule.");
if (temp.Scale != _scale)
@ -63,5 +39,17 @@ namespace Modules
return TwinResult.Ok;
});
}
public Input<TemperatureModuleOutput> Temperature { get; set; }
public Output<TemperatureModuleOutput> NormalizedTemperature { get; set; }
public ModuleTwin<NormalizerTwin> Twin { get; set; }
public override async Task<ExecutionResult> RunAsync()
{
var twin = await Twin.GetAsync();
_scale = twin.Scale;
return ExecutionResult.Ok;
}
}
}

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

@ -13,7 +13,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.23" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.26" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
</ItemGroup>
<ItemGroup>

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

@ -3,7 +3,7 @@
"NormalizeTemperatureModule": {
"commandName": "Project",
"environmentVariables": {
"ModuleName": "NormalizeTemperature"
"ModuleName": "normalizetemperaturemodule"
}
}
}

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

@ -13,7 +13,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.23" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.26" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
</ItemGroup>
<ItemGroup>

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

@ -3,7 +3,6 @@
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<add key="RocksDB ARM" value="https://www.myget.org/F/rocksdb-native-arm/api/v3/index.json" />
<add key="private-typeedge-feed" value="https://msblox-03.pkgs.visualstudio.com/_packaging/private-nuget-feed/nuget/v3/index.json" />
</packageSources>
<packageRestore>
<add key="enabled" value="True" />
@ -16,10 +15,4 @@
<add key="format" value="0" />
<add key="disabled" value="False" />
</packageManagement>
<packageSourceCredentials>
<private-typeedge-feed>
<add key="Username" value="spyrosg" />
<add key="ClearTextPassword" value="123asd!@#" />
</private-typeedge-feed>
</packageSourceCredentials>
</configuration>

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

@ -12,13 +12,13 @@
</PropertyGroup>
<ItemGroup>
<None Include="..\.env" Link=".env">
<None Include="..\.env" Link=".env" Visible="false">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Host" Version="0.1.23" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Host" Version="0.1.26" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
<PackageReference Include="rocksdb-native-arm" Version="5.4.6" />
<PackageReference Include="RocksDbNative" Version="5.4.6.10" />
</ItemGroup>

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

@ -12,7 +12,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.23" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.26" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
</ItemGroup>

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

@ -6,7 +6,7 @@ using ThermostatApplication.Twins;
namespace ThermostatApplication.Modules
{
[TypeModule(Name = "normalizetemperature")]
[TypeModule]
public interface INormalizeTemperatureModule
{
Output<TemperatureModuleOutput> NormalizedTemperature { get; set; }

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

@ -6,7 +6,7 @@ using ThermostatApplication.Twins;
namespace ThermostatApplication.Modules
{
[TypeModule(Name = "temperature")]
[TypeModule]
public interface ITemperatureModule
{
Output<TemperatureModuleOutput> Temperature { get; set; }

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

@ -10,7 +10,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.23" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.26" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
</ItemGroup>
<ItemGroup>

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

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

@ -2,14 +2,14 @@
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<id>Microsoft.Azure.IoT.TypeEdge.Host</id>
<version>0.1.23</version>
<version>0.1.26</version>
<authors>paloukari</authors>
<owners>paloukari</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Package Description</description>
<dependencies>
<group targetFramework=".NETCoreApp2.1">
<dependency id="Microsoft.Azure.IoT.TypeEdge" version="0.1.0" exclude="Build,Analyzers" />
<dependency id="Microsoft.Azure.IoT.TypeEdge" version="0.1.26" exclude="Build,Analyzers" />
<dependency id="Microsoft.Azure.Devices.Edge.Agent.Core" version="1.0.0" exclude="Build,Analyzers" />
<dependency id="Microsoft.Azure.Devices.Edge.Hub.Service" version="1.0.0" exclude="Build,Analyzers" />
</group>

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

@ -194,7 +194,6 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host
{
if (!(scope.Resolve(moduleType) is EdgeModule module))
continue;
module.BuildSubscriptions();
modules.Add(module);
}
}
@ -207,7 +206,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host
IotHubConnectionStringBuilder.Create(_options.IotHubConnectionString);
var registryManager = RegistryManager.CreateFromConnectionString(_options.IotHubConnectionString);
string sasKey = null;
string sasKey;
try
{
var device = await registryManager.AddDeviceAsync(

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

@ -2,7 +2,7 @@
<PropertyGroup>
<PackageId>Microsoft.Azure.IoT.TypeEdge.Proxy</PackageId>
<Version>0.1.23</Version>
<Version>0.1.26</Version>
<Authors>paloukari</Authors>
<Company>Microsoft</Company>

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

@ -31,11 +31,11 @@ namespace Microsoft.Azure.IoT.TypeEdge.Proxy
{
get
{
var typeModule = typeof(T).GetCustomAttribute(typeof(TypeModuleAttribute), true) as TypeModuleAttribute;
if (typeModule?.Name != null)
return typeModule.Name;
return typeof(T).IsInterface ? typeof(T).Name.TrimStart('I') : typeof(T).Name;
if (!(typeof(T).GetCustomAttribute(typeof(TypeModuleAttribute), true) is TypeModuleAttribute))
throw new ArgumentException($"{typeof(T).Name} has no TypeModule annotation");
if (!typeof(T).IsInterface)
throw new ArgumentException($"{typeof(T).Name} needs to be an interface");
return typeof(T).Name.Substring(1).ToLower();
}
}
@ -59,7 +59,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Proxy
{
//direct methods
var methodInvocation =
new CloudToDeviceMethod(invocation.Method.Name) {ResponseTimeout = TimeSpan.FromSeconds(30)};
new CloudToDeviceMethod(invocation.Method.Name) { ResponseTimeout = TimeSpan.FromSeconds(30) };
var paramData = JsonConvert.SerializeObject(invocation.Arguments);
methodInvocation.SetPayloadJson(paramData);

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

@ -4,6 +4,5 @@ namespace Microsoft.Azure.IoT.TypeEdge.Attributes
{
public class TypeModuleAttribute : Attribute
{
public string Name { get; set; }
}
}

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

@ -2,7 +2,7 @@
<PropertyGroup>
<PackageId>Microsoft.Azure.IoT.TypeEdge</PackageId>
<Version>0.1.23</Version>
<Version>0.1.26</Version>
<Authors>paloukari</Authors>
<Company>Microsoft</Company>
<PackageOutputPath>../../TypeEdgeNuGets</PackageOutputPath>

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

@ -51,9 +51,11 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
get
{
var proxyInterface = GetType().GetProxyInterface();
if (proxyInterface.GetCustomAttribute(typeof(TypeModuleAttribute), true) is TypeModuleAttribute typeModule)
return typeModule.Name;
return GetType().Name;
if (proxyInterface == null)
throw new ArgumentException($"{GetType().Name} has needs to implement an single interface annotated with the TypeModule Attribute");
return proxyInterface.Name.Substring(1).ToLower();
}
}
@ -87,13 +89,8 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
return CreationResult.Ok;
}
public virtual void BuildSubscriptions()
{
}
internal async Task<ExecutionResult> InternalRunAsync()
{
RegisterMethods();
// Open a connection to the Edge runtime

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

@ -21,11 +21,11 @@ namespace Microsoft.Azure.IoT.TypeEdge.Proxy
{
get
{
var typeModule = _type.GetCustomAttribute(typeof(TypeModuleAttribute), true) as TypeModuleAttribute;
if (typeModule?.Name != null)
return typeModule.Name;
return _type.IsInterface ? _type.Name.TrimStart('I') : _type.Name;
if (!(_type.GetCustomAttribute(typeof(TypeModuleAttribute), true) is TypeModuleAttribute))
throw new ArgumentException($"{_type.Name} has no TypeModule annotation");
if (!_type.IsInterface)
throw new ArgumentException($"{_type.Name} needs to be an interface");
return _type.Name.Substring(1).ToLower();
}
}

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

@ -69,9 +69,6 @@ namespace Microsoft.Azure.IoT.TypeEdge
Module = container.Resolve(moduleType) as EdgeModule;
if (Module != null)
{
Module.BuildSubscriptions();
Module.InternalConfigure(configuration);
await Module.InternalRunAsync();
}
@ -108,7 +105,7 @@ namespace Microsoft.Azure.IoT.TypeEdge
var moduleType = assembly.GetTypes().SingleOrDefault(t =>
t.GetInterfaces().SingleOrDefault(i =>
i.GetCustomAttribute(typeof(TypeModuleAttribute), true) != null &&
string.Equals((i.GetCustomAttribute(typeof(TypeModuleAttribute), true) as TypeModuleAttribute)?.Name, moduleName, StringComparison.CurrentCultureIgnoreCase)) != null);
string.Equals(i.Name.Substring(1), moduleName, StringComparison.CurrentCultureIgnoreCase)) != null);
if (moduleType == null)
{

21
NuGet.Config Normal file
Просмотреть файл

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageRestore>
<add key="enabled" value="True" />
<add key="automatic" value="True" />
</packageRestore>
<bindingRedirects>
<add key="skip" value="False" />
</bindingRedirects>
<packageManagement>
<add key="format" value="0" />
<add key="disabled" value="False" />
</packageManagement>
<packageSources>
<add key="RocksDB ARM" value="https://www.myget.org/F/rocksdb-native-arm/api/v3/index.json" />
<add key="https://www.nuget.org/api/v2/" value="https://www.nuget.org/api/v2/" />
</packageSources>
<disabledPackageSources>
<add key="https://www.nuget.org/api/v2/" value="true" />
</disabledPackageSources>
</configuration>

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

@ -11,56 +11,24 @@ Specifically:
## Development Environment Setup
<details>
<summary>
<b>Important:</b> If you just landed to this repo,<b> make sure you setup your environment first before continuing </b></summary>
To setup your development environment for **TypeEdge** you will need to:
1. **Install [Docker](https://docs.docker.com/engine/installation/)**
2. **Install the latest [.NET Core](https://github.com/dotnet/core/blob/master/release-notes/download-archive.md)**
> ***Important note***: **TypeEdge** requires **.NET Core 2.1.0-Preview2** and above, you can check your version by typing:
```cmd
dotnet --version
```
> *As of 05/25/2018, the latest .NET Core release is [this](https://github.com/dotnet/core/blob/master/release-notes/download-archives/2.1.0-rc1-download.md)*
1. **Install your favorite IDE ([VS Code](https://code.visualstudio.com/download) or [VS 2017](https://www.visualstudio.com/downloads/))**
Make sure you have [Docker](https://docs.docker.com/engine/installation/), the latest [.NET Core SDK](https://github.com/dotnet/core/blob/master/release-notes/download-archive.md) and your git credentials to login [here](https://msblox-03.visualstudio.com/csetypescript)
1. **Temporary step - private NuGet packages**:
Temporarily, and until GA, the required NuGet packages will be distributed through [this](https://msblox-03.pkgs.visualstudio.com/_packaging/private-nuget-feed/nuget/v3/index.json) private NuGet feed. After GA, these packages will be available in the www.nuget.org.
> ***Important note:*** Only MS FTE have access to this NuGet feed. To add the feed to your machine wide configuration just once. This is required because of the way dotnet templates at the moment work.
To add the feed to your machine you will need your git credentials or a personal access token. TO get your git credentials, navigate to the [VSTS repo](https://msblox-03.visualstudio.com/csetypescript) and under **"clone to your computer"** section, click **"Generate Git Credentials"**
Then, **add your credentials to the command bellow** and run it.
```
nuget.exe sources Add -Name "private-typeedge-feed" -Source "https://msblox-03.pkgs.visualstudio.com/_packaging/private-nuget-feed/nuget/v3/index.json" -UserName USERNAME -Password PASSWORD
```
You can download the latest nuget.exe from [here](https://dist.nuget.org/win-x86-commandline/latest/nuget.exe)
You'll also need to add the RocksDB ARM repo:
```
nuget.exe sources Add -Name "RocksDB ARM" -Source "https://www.myget.org/F/rocksdb-native-arm/api/v3/index.json"
```
These steps will get you ready to build your first TypeEdge application.
</details>
<br>
**Temporary step - private NuGet credentials**:
Temporarily the required IoT Edge Runtime NuGet packages will be unofficially distributed through [this](https://msblox-03.pkgs.visualstudio.com/_packaging/private-nuget-feed/nuget/v3/index.json) private NuGet feed.
> ***Important note:*** Only MS FTE have access to this NuGet feed. You will need to add the feed to your solution in a next step. Make sure you know your git credentials. To get your git credentials, navigate to the [VSTS repo](https://msblox-03.visualstudio.com/csetypescript) and under **"clone to your computer"** section, click **"Generate Git Credentials"**.
## QuickStart
Here is the quickest way to get started with TypeEdge. This quick start will create an IoT Edge solution with two modules and run it in the IoT Edge emulator:
Here is the quickest way to get started with **TypeEdge**. This quick start will create an IoT Edge solution with two modules, and run it in the IoT Edge emulator:
1. Install the TypeEdge .NET Core solution template. Just type:
```
dotnet new -i TypeEdge.Application::*
dotnet new -i TypeEdge.Application
```
>**Note:** If you already installed the template and you want to **update to a newer template version**, you need to clear the dotnet http and template cache
>**Note:** If you already installed the template and you want to **upgrade to a newer template version**, you need to clear the dotnet http and template cache
```
dotnet nuget locals http-cache --clear
dotnet new --debug:reinit
@ -74,17 +42,23 @@ Here is the quickest way to get started with TypeEdge. This quick start will cre
dotnet new typeedgeapp -n Thermostat -m1 SensorModule -m2 PreprocessorModule -cs "YOUR_IOTHUBOWNER_CONNECTION"
```
1. Open in VS Code/Visual Studio 2017 and hit F5:
1. Temporary step:
Navigate inside the root folder to add the private packages source. Then, **add your git credentials to the command bellow** and run it. This will download nuget.exe and add the private packages source in your solution.
```
cd Thermostat
addPrivateSource.bat USERNAME PASSWORD
```
3. Open in VS Code/Visual Studio 2017 and hit F5:
```
code .
```
> Note: you can build and run with no IDE, simply by executing the following
> Note: you don't necessarily need VS Code, you can build and run by executing the following
```
dotnet build Thermostat
cd Thermostat\Thermostat.Emulator
dotnet build Thermostat.sln
cd Thermostat.Emulator
dotnet run
```
@ -92,9 +66,30 @@ Here is the quickest way to get started with TypeEdge. This quick start will cre
> Note: You should now see the Edge Hub starting up..
![](images/IoTEdge.png) .. and the messages flowing in .. ![](images/messages.png)
**Congratulations!** You just created your first TypeEdge application. Continue reading bellow to learn how to deploy this application to an IoT Device
**Congratulations!** You just created your first **TypeEdge** application. Continue reading bellow to learn how to deploy this application to an IoT Device, or take the time to understand [how it works](#how).
## Device Deployment
In the application root folder, type:
docker-compose build
This will build your docker images for the device deployment. Final step is to push the images to the docker registry.
>Note: the registry is configured in the .env file inside the root folder. **Make sure you run the the emulator if you edit the .env file**, to update the cloud IoT Device deployment configuration.
docker-compose push
>Note: If your registry requires authentication, you need to provide the registry credentials to docker:
docker login YOUR_REGISTRY -u YOUR_USERNAME -p YOUR_PASSWORD
This was the final step. All IoT Edge containers are ready to be deployed to the device. Follow [these instructions](https://docs.microsoft.com/en-us/azure/iot-edge/quickstart#configure-the-iot-edge-runtime) to deploy the application to the device.
## <a name="how">How it works</a>
## How it works
**TypeEdge** for the moment only supports .NET Core C#. A **TypeEdge** application is a collection of **TypeEdge Modules**.
@ -102,7 +97,7 @@ Here is the quickest way to get started with TypeEdge. This quick start will cre
**TypeEdge** leverages **interfaces** to define the structure and behavior of the modules. A typical example of a **TypeEdge module definition** is:
```cs
[TypeModule(Name = "SensorModule")]
[TypeModule]
public interface ISensorModule
{
Output<SensorModuleOutput> Output { get; set; }
@ -156,16 +151,13 @@ public class SensorModule : EdgeModule, ISensorModule
```
</details>
<br>
A **TypeEdge** module can override any of the virtual methods of the base class ``EdgeModule``. As demonstrated in the above example, the ``RunAsync`` method is used for implementing long running loops, typically useful for modules that read sensor values. Another virtual method is ``Configure``, which can be used to read custom module configuration during startup. Finally, the ``BuildSubscriptions`` is used to define handlers to incoming messages.
A <b>TypeEdge</b> module can override any of the virtual methods of the base class ``EdgeModule``. As demonstrated in the above example, the ``RunAsync`` method is used for implementing long running loops, typically useful for modules that read sensor values. Another virtual method is ``Configure``, which can be used to read custom module configuration during startup. Finally, the ``BuildSubscriptions`` is used to define handlers to incoming messages.
The complete ``EdgeModule`` definition is:
```cs
public abstract class EdgeModule
{
public EdgeModule();
public virtual void BuildSubscriptions();
public virtual CreationResult Configure(IConfigurationRoot configuration);
public virtual Task<ExecutionResult> RunAsync();
}
@ -195,7 +187,7 @@ Input.Subscribe(proxy.Output, async (msg) =>
return MessageResult.OK;
});
```
In this example, the ``PreprocessorModule's`` input called ``Input``, subscribes to ``SensorModule's`` output, called ``Output``, and defines a subscription handler, a delegate that will be called every time the ``SensorModule`` sends a messages through its ``Output ``. In this example, the ``PreprocessorModule`` will enrich the incoming message, and publish it to its output called ``Output ``. These subscriptions need to be declared in the ``BuildSubscriptions`` override.
In this example, the ``PreprocessorModule's`` input called ``Input``, subscribes to ``SensorModule's`` output, called ``Output``, and defines a subscription handler, a delegate that will be called every time the ``SensorModule`` sends a messages through its ``Output ``. In this example, the ``PreprocessorModule`` will enrich the incoming message, and publish it to its output called ``Output ``. These subscriptions need to be declared in the default constructor.
The complete code of the template's ``PreprocessorModule`` is:
@ -205,18 +197,11 @@ The complete code of the template's ``PreprocessorModule`` is:
```cs
public class PreprocessorModule : EdgeModule, IPreprocessorModule
{
readonly ISensorModule proxy;
public Output<PreprocessorModuleOutput> Output { get; set; }
public Input<SensorModuleOutput> Input { get; set; }
public ModuleTwin<PreprocessorModuleTwin> Twin { get; set; }
public PreprocessorModule(ISensorModule proxy)
{
this.proxy = proxy;
}
public override void BuildSubscriptions()
{
Input.Subscribe(proxy.Output, async (msg) =>
{
@ -260,6 +245,7 @@ public static async Task Main(string[] args)
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables()
.AddDotenvFile()
.AddCommandLine(args)
.Build();
@ -293,6 +279,3 @@ ProxyFactory.GetModuleProxy<ISensorModule>().ResetModule(4);
### Solution structure
Apparently, to reference module definition interfaces and to avoid coupling the module implementation code together, these interfaces need to be defined in a separate project that will be commonly shared across the solution, containing only the definition interfaces and the referenced types.
![](images/solution.png)
## Device Deployment
[Coming soon]

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

@ -0,0 +1,10 @@
.dockerignore
.git
.gitignore
.vs
.vscode
docker-compose.yml
docker-compose.*.yml
*/bin
*/obj
nuget.exe

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

@ -0,0 +1 @@
DOCKER_REGISTRY=localhost:5000/

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

@ -13,22 +13,51 @@
"sourceName": "TypeEdgeApplication",
"preferNameDirectory": true,
"symbols": {
"appNameLower":{
"type": "generated",
"generator": "casing",
"parameters": {
"source":"name",
"toLower": true
},
"replaces":"TypeEdgeApplicationEmulatorImageName"
},
"module1Name": {
"type": "parameter",
"defaultValue": "Module1",
"replaces": "TypeEdgeModule1",
"fileRename": "TypeEdgeModule1"
"fileRename": "TypeEdgeModule1",
"description": "The name of the first TypeEdge Module"
},
"module1NameLower":{
"type": "generated",
"generator": "casing",
"parameters": {
"source":"module1Name",
"toLower": true
},
"replaces":"TypeEdgeModule1ImageName"
},
"module2Name": {
"type": "parameter",
"defaultValue": "Module2",
"replaces": "TypeEdgeModule2",
"fileRename": "TypeEdgeModule2"
"fileRename": "TypeEdgeModule2",
"description": "The name of the second TypeEdge Module"
},
"module2NameLower":{
"type": "generated",
"generator": "casing",
"parameters": {
"source":"module2Name",
"toLower": true
},
"replaces":"TypeEdgeModule2ImageName"
},
"connectionString": {
"type": "parameter",
"defaultValue": "PUT YOUR IOT HUB OWNER CONNECTION STRING HERE",
"replaces": "CONNECTION_STRING"
"replaces": "CONNECTION_STRING",
"description": "The IoT Hub owner connection string"
}
}
}

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

@ -0,0 +1,20 @@
ARG base_tag=2.1-runtime-stretch-slim
FROM microsoft/dotnet:${base_tag} AS base
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY Modules/TypeEdgeModule1/TypeEdgeModule1.csproj Modules/TypeEdgeModule1/
COPY TypeEdgeApplication.Shared/TypeEdgeApplication.Shared.csproj TypeEdgeApplication.Shared/
COPY NuGet.Config ./
RUN dotnet restore Modules/TypeEdgeModule1/TypeEdgeModule1.csproj
COPY . .
WORKDIR /src/Modules/TypeEdgeModule1
RUN dotnet build TypeEdgeModule1.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish TypeEdgeModule1.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "TypeEdgeModule1.dll"]

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

@ -1,4 +1,5 @@
using System;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.IoT.TypeEdge.Enums;
@ -26,11 +27,9 @@ namespace Modules
{
while (true)
{
await Output.PublishAsync(new TypeEdgeModule1Output {Data = new Random().NextDouble().ToString()});
await Output.PublishAsync(new TypeEdgeModule1Output {Data = new Random().NextDouble().ToString(CultureInfo.InvariantCulture)});
Thread.Sleep(1000);
}
return await base.RunAsync();
}
}
}

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

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.0" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.26" />
</ItemGroup>
<ItemGroup>

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

@ -0,0 +1,20 @@
ARG base_tag=2.1-runtime-stretch-slim
FROM microsoft/dotnet:${base_tag} AS base
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY Modules/TypeEdgeModule2/TypeEdgeModule2.csproj Modules/TypeEdgeModule2/
COPY TypeEdgeApplication.Shared/TypeEdgeApplication.Shared.csproj TypeEdgeApplication.Shared/
COPY NuGet.Config ./
RUN dotnet restore Modules/TypeEdgeModule2/TypeEdgeModule2.csproj
COPY . .
WORKDIR /src/Modules/TypeEdgeModule2
RUN dotnet build TypeEdgeModule2.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish TypeEdgeModule2.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "TypeEdgeModule2.dll"]

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

@ -11,20 +11,9 @@ namespace Modules
{
public class TypeEdgeModule2 : EdgeModule, ITypeEdgeModule2
{
private readonly ITypeEdgeModule1 _proxy;
public TypeEdgeModule2(ITypeEdgeModule1 proxy)
{
_proxy = proxy;
}
public Output<TypeEdgeModule2Output> Output { get; set; }
public Input<TypeEdgeModule1Output> Input { get; set; }
public ModuleTwin<TypeEdgeModule2Twin> Twin { get; set; }
public override void BuildSubscriptions()
{
Input.Subscribe(_proxy.Output, async msg =>
Input.Subscribe(proxy.Output, async msg =>
{
await Output.PublishAsync(new TypeEdgeModule2Output
{
@ -34,5 +23,9 @@ namespace Modules
return MessageResult.Ok;
});
}
public Output<TypeEdgeModule2Output> Output { get; set; }
public Input<TypeEdgeModule1Output> Input { get; set; }
public ModuleTwin<TypeEdgeModule2Twin> Twin { get; set; }
}
}

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

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.0" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.26" />
</ItemGroup>
<ItemGroup>

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

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageRestore>
<add key="enabled" value="True" />
<add key="automatic" value="True" />
</packageRestore>
<bindingRedirects>
<add key="skip" value="False" />
</bindingRedirects>
<packageManagement>
<add key="format" value="0" />
<add key="disabled" value="False" />
</packageManagement>
<packageSources>
<add key="RocksDB ARM" value="https://www.myget.org/F/rocksdb-native-arm/api/v3/index.json" />
</packageSources>
</configuration>

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

@ -0,0 +1,47 @@
ARG base_tag=2.1-runtime-stretch-slim
FROM microsoft/dotnet:${base_tag} AS base
# Add an unprivileged user account for running Edge Hub
RUN useradd -ms /bin/bash edgehubuser
ENV EdgeHubUser=edgehubuser
ARG EXE_DIR=.
ENV SSL_CERTIFICATE_PATH=/app/certs
ENV SSL_CERTIFICATE_NAME=mqtt-server.pfx
# Install snappy and set up symlinks that are absent from the base image
# Required by RocksDb
RUN apt-get update && \
apt-get install -y libsnappy1v5 libcap2-bin && \
ln -s /lib/x86_64-linux-gnu/libdl.so.2 /usr/lib/x86_64-linux-gnu/libdl.so && \
ln -s /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc.so && \
rm -rf /var/lib/apt/lists/*
# add the CAP_NET_BIND_SERVICE capability to the dotnet binary because
# we are starting edge hub as a non-root user
RUN setcap 'cap_net_bind_service=+ep' /usr/share/dotnet/dotnet
# Expose MQTT and HTTPS ports
EXPOSE 8883/tcp
EXPOSE 443/tcp
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY TypeEdgeApplication.Emulator/TypeEdgeApplication.Emulator.csproj TypeEdgeApplication.Emulator/
COPY TypeEdgeApplication.Shared/TypeEdgeApplication.Shared.csproj TypeEdgeApplication.Shared/
COPY Modules/TypeEdgeModule2/TypeEdgeModule2.csproj Modules/TypeEdgeModule2/
COPY Modules/TypeEdgeModule1/TypeEdgeModule1.csproj Modules/TypeEdgeModule1/
COPY NuGet.Config ./
RUN dotnet restore TypeEdgeApplication.Emulator/TypeEdgeApplication.Emulator.csproj
COPY . .
COPY ./.env Thermostat.Emulator/
WORKDIR /src/TypeEdgeApplication.Emulator
RUN dotnet build TypeEdgeApplication.Emulator.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish TypeEdgeApplication.Emulator.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "TypeEdgeApplication.Emulator.dll"]

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

@ -0,0 +1,2 @@
ARG base_tag=2.1-runtime-stretch-slim
FROM microsoft/dotnet:${base_tag} AS base

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

@ -1,6 +1,7 @@
using System;
using System.Threading.Tasks;
using Microsoft.Azure.IoT.TypeEdge.Host;
using Microsoft.Azure.IoT.TypeEdge.Host.DovEnv;
using Microsoft.Extensions.Configuration;
using TypeEdgeApplication.Shared;
@ -14,6 +15,7 @@ namespace TypeEdgeApplication
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables()
.AddDotenvFile()
.AddCommandLine(args)
.Build();

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

@ -6,10 +6,16 @@
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<None Include="..\.env" Link=".env">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="rocksdb-native-arm" Version="5.4.6" />
<PackageReference Include="RocksDbNative" Version="5.4.6.10" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Host" Version="0.1.0" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Host" Version="0.1.26" />
</ItemGroup>
<ItemGroup>
@ -19,6 +25,7 @@
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

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

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.0" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.26" />
</ItemGroup>
<ItemGroup>

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

@ -6,7 +6,7 @@ using TypeEdgeApplication.Shared.Twins;
namespace TypeEdgeApplication.Shared
{
[TypeModule(Name = "TypeEdgeModule1")]
[TypeModule]
public interface ITypeEdgeModule1
{
Output<TypeEdgeModule1Output> Output { get; set; }

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

@ -6,7 +6,7 @@ using TypeEdgeApplication.Shared.Twins;
namespace TypeEdgeApplication.Shared
{
[TypeModule(Name = "TypeEdgeModule2")]
[TypeModule]
public interface ITypeEdgeModule2
{
Output<TypeEdgeModule2Output> Output { get; set; }

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

@ -5,7 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.0" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.26" />
</ItemGroup>
</Project>

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

@ -15,6 +15,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TypeEdgeModule1", "Modules\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TypeEdgeModule2", "Modules\TypeEdgeModule2\TypeEdgeModule2.csproj", "{B50131E0-4249-45FF-9DB4-FFFF49BD7F7E}"
EndProject
Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{6603BB40-94EB-4AFC-83DE-9EF235F45237}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -41,6 +43,10 @@ Global
{B50131E0-4249-45FF-9DB4-FFFF49BD7F7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B50131E0-4249-45FF-9DB4-FFFF49BD7F7E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B50131E0-4249-45FF-9DB4-FFFF49BD7F7E}.Release|Any CPU.Build.0 = Release|Any CPU
{6603BB40-94EB-4AFC-83DE-9EF235F45237}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6603BB40-94EB-4AFC-83DE-9EF235F45237}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6603BB40-94EB-4AFC-83DE-9EF235F45237}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6603BB40-94EB-4AFC-83DE-9EF235F45237}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

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

@ -0,0 +1,49 @@
@echo off
IF "%1"=="" GOTO HAVE_USERNAME
IF "%2"=="" GOTO HAVE_PASSWORD
if exist nuget.exe (
echo nuget.exe found
) else (
echo downloading nuget.exe from https://www.nuget.org/nuget.exe
Powershell.exe wget -outf nuget.exe https://nuget.org/nuget.exe
if not exist .\nuget.exe (
echo Error: nuget does not exist.
exit /b 1
)
)
echo Adding the private nuget packages feed "private-typeedge-feed"
nuget.exe sources Add -Name "private-typeedge-feed" -Source "https://msblox-03.pkgs.visualstudio.com/_packaging/private-nuget-feed/nuget/v3/index.json" -StorePasswordInClearText -ConfigFile NuGet.Config -UserName "%1" -Password "%2"
if errorlevel 1 (
echo Failed, trying to remove an existing record first ..
echo Removing the private "private-typeedge-feed" ..
nuget.exe sources Remove -Name "private-typeedge-feed"
echo Adding the private nuget packages feed "private-typeedge-feed"
nuget.exe sources Add -Name "private-typeedge-feed" -Source "https://msblox-03.pkgs.visualstudio.com/_packaging/private-nuget-feed/nuget/v3/index.json" -StorePasswordInClearText -ConfigFile NuGet.Config -UserName "%1" -Password "%2"
if errorlevel 0 (
echo Success!
)
)
if exist nuget.exe (
del nuget.exe /q
)
exit /b 0
:HAVE_USERNAME
echo Your Git credentials username is required
exit /b 1
:HAVE_PASSWORD
echo Your Git credentials password is required
exit /b 1
:exit
echo exiting..

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

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" Sdk="Microsoft.Docker.Sdk">
<PropertyGroup Label="Globals">
<ProjectVersion>2.1</ProjectVersion>
<DockerTargetOS>Linux</DockerTargetOS>
<ProjectGuid>6603bb40-94eb-4afc-83de-9ef235f45237</ProjectGuid>
</PropertyGroup>
<ItemGroup>
<None Include=".env" />
<None Include="docker-compose.override.yml">
<DependentUpon>docker-compose.yml</DependentUpon>
</None>
<None Include="docker-compose.vs.debug.yml">
<DependentUpon>docker-compose.yml</DependentUpon>
</None>
<None Include="docker-compose.yml" />
<None Include=".dockerignore" />
</ItemGroup>
</Project>

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

@ -0,0 +1 @@
version: '3.4'

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

@ -0,0 +1,8 @@
version: '3.4'
services:
TypeEdgeApplication.Emulator:
image: ${DOCKER_REGISTRY}TypeEdgeApplicationEmulatorImageName
build:
context: .
dockerfile: TypeEdgeApplication.Emulator/Dockerfile

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

@ -0,0 +1,22 @@
version: '3.4'
services:
TypeEdgeApplication.Emulator:
image: ${DOCKER_REGISTRY}TypeEdgeApplicationEmulatorImageName
build:
context: .
dockerfile: TypeEdgeApplication.Emulator/DockerfileEmpty
TypeEdgeModule1:
image: ${DOCKER_REGISTRY}TypeEdgeModule1ImageName
build:
context: .
dockerfile: Modules/TypeEdgeModule1/Dockerfile
TypeEdgeModule2:
image: ${DOCKER_REGISTRY}TypeEdgeModule2ImageName
build:
context: .
dockerfile: Modules/TypeEdgeModule2/Dockerfile

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

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Host" Version="0.1.0" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Host" Version="0.1.26" />
</ItemGroup>
</Project>

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

@ -6,7 +6,7 @@ using Shared.Twins;
namespace Shared
{
[TypeModule(Name = "TypeEdgeModule")]
[TypeModule]
public interface ITypeEdgeModule
{
Output<TypeEdgeModuleOutput> Output { get; set; }

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

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.0" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.26" />
</ItemGroup>
</Project>

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

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.0" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.26" />
</ItemGroup>
</Project>

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

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Host" Version="0.1.0" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Host" Version="0.1.26" />
</ItemGroup>
</Project>

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

@ -6,7 +6,7 @@ using Shared.Twins;
namespace Shared
{
[TypeModule(Name = "TypeEdgeModule")]
[TypeModule]
public interface ITypeEdgeModule
{
Output<TypeEdgeModuleOutput> Output { get; set; }

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

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.0" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.26" />
</ItemGroup>
</Project>

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

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.0" />
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.26" />
</ItemGroup>
</Project>

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

@ -1,2 +1,3 @@
\obj\
\bin\
\bin\
\.vs\

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

@ -35,7 +35,6 @@ dotnet new --install TypeEdgeApplication
dotnet new --install TypeEdgeProxy
dotnet new --install TypeEdgeEmulator
dotnet clean TypeEdgeModule
dotnet clean TypeEdgeApplication
dotnet clean TypeEdgeProxy
@ -53,7 +52,7 @@ nuget.exe pack build\TypeEdgeApplication -Version %version%
move /Y *.nupkg ..\..\TypeEdgeNuGets
nuget.exe push ..\..\TypeEdgeNuGets\*%version%.nupkg -ApiKey VSTS
rem nuget.exe push ..\..\TypeEdgeNuGets\*%version%.nupkg -ApiKey VSTS
dotnet nuget locals http-cache --clear
dotnet new --debug:reinit