heavy refactoring abstracting modules

This commit is contained in:
Spyros Garyfallos 2018-05-10 13:12:14 -07:00
Родитель 943c37a471
Коммит 5ef31acf4a
30 изменённых файлов: 344 добавлений и 230 удалений

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

@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27428.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThermpostatEdgeApplication", "ThermpostatEdgeApplication\ThermpostatEdgeApplication.csproj", "{6E41A1D9-FD4D-43BD-932A-D88459C7F4E5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "hub", "hub", "{34DAEE1A-E6E8-4059-9142-BF0170F3EAA8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.Devices.Edge.Hub.Amqp", "..\..\..\internal\Azure-IoT-Edge-Core\edge-hub\src\Microsoft.Azure.Devices.Edge.Hub.Amqp\Microsoft.Azure.Devices.Edge.Hub.Amqp.csproj", "{123E0E0F-3CAC-4095-B008-848F32A59C38}"
@ -31,6 +29,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.Devices.Edg
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.IoT.TypeEdge", "Microsoft.Azure.IoT.TypeEdge\Microsoft.Azure.IoT.TypeEdge.csproj", "{54587D56-7C22-4084-9321-84D57C2F6ECB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ThermostatApplication", "ThermostatApplication", "{2E4AF4B3-04D0-4950-979B-B04052B8E20A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThermostatApplication.EdgeHost", "ThermostatApplication.EdgeHost\ThermostatApplication.EdgeHost.csproj", "{2C06F377-0612-431F-BA91-A2F5A561E789}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThermostatApplication.Shared", "ThermostatApplication.Shared\ThermostatApplication.Shared.csproj", "{CB2C4940-747F-4C45-9EA8-4C98F7F3AD41}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{40D0EFBC-3D80-42C8-9623-B9CAD4B96EFF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TemperatureModule", "TemperatureModule\TemperatureModule.csproj", "{2B79BE65-8725-42FE-9F63-BC1797080E70}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NormalizeTemperatureModule", "NormalizeTemperatureModule\NormalizeTemperatureModule.csproj", "{A55A00B6-BABA-414D-A38F-C4CAB4B9331B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CodeCoverage|Any CPU = CodeCoverage|Any CPU
@ -38,12 +48,6 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6E41A1D9-FD4D-43BD-932A-D88459C7F4E5}.CodeCoverage|Any CPU.ActiveCfg = Release|Any CPU
{6E41A1D9-FD4D-43BD-932A-D88459C7F4E5}.CodeCoverage|Any CPU.Build.0 = Release|Any CPU
{6E41A1D9-FD4D-43BD-932A-D88459C7F4E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6E41A1D9-FD4D-43BD-932A-D88459C7F4E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6E41A1D9-FD4D-43BD-932A-D88459C7F4E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6E41A1D9-FD4D-43BD-932A-D88459C7F4E5}.Release|Any CPU.Build.0 = Release|Any CPU
{123E0E0F-3CAC-4095-B008-848F32A59C38}.CodeCoverage|Any CPU.ActiveCfg = CodeCoverage|Any CPU
{123E0E0F-3CAC-4095-B008-848F32A59C38}.CodeCoverage|Any CPU.Build.0 = CodeCoverage|Any CPU
{123E0E0F-3CAC-4095-B008-848F32A59C38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@ -116,6 +120,30 @@ Global
{54587D56-7C22-4084-9321-84D57C2F6ECB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{54587D56-7C22-4084-9321-84D57C2F6ECB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{54587D56-7C22-4084-9321-84D57C2F6ECB}.Release|Any CPU.Build.0 = Release|Any CPU
{2C06F377-0612-431F-BA91-A2F5A561E789}.CodeCoverage|Any CPU.ActiveCfg = Debug|Any CPU
{2C06F377-0612-431F-BA91-A2F5A561E789}.CodeCoverage|Any CPU.Build.0 = Debug|Any CPU
{2C06F377-0612-431F-BA91-A2F5A561E789}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2C06F377-0612-431F-BA91-A2F5A561E789}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2C06F377-0612-431F-BA91-A2F5A561E789}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2C06F377-0612-431F-BA91-A2F5A561E789}.Release|Any CPU.Build.0 = Release|Any CPU
{CB2C4940-747F-4C45-9EA8-4C98F7F3AD41}.CodeCoverage|Any CPU.ActiveCfg = Debug|Any CPU
{CB2C4940-747F-4C45-9EA8-4C98F7F3AD41}.CodeCoverage|Any CPU.Build.0 = Debug|Any CPU
{CB2C4940-747F-4C45-9EA8-4C98F7F3AD41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CB2C4940-747F-4C45-9EA8-4C98F7F3AD41}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CB2C4940-747F-4C45-9EA8-4C98F7F3AD41}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CB2C4940-747F-4C45-9EA8-4C98F7F3AD41}.Release|Any CPU.Build.0 = Release|Any CPU
{2B79BE65-8725-42FE-9F63-BC1797080E70}.CodeCoverage|Any CPU.ActiveCfg = Debug|Any CPU
{2B79BE65-8725-42FE-9F63-BC1797080E70}.CodeCoverage|Any CPU.Build.0 = Debug|Any CPU
{2B79BE65-8725-42FE-9F63-BC1797080E70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2B79BE65-8725-42FE-9F63-BC1797080E70}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2B79BE65-8725-42FE-9F63-BC1797080E70}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B79BE65-8725-42FE-9F63-BC1797080E70}.Release|Any CPU.Build.0 = Release|Any CPU
{A55A00B6-BABA-414D-A38F-C4CAB4B9331B}.CodeCoverage|Any CPU.ActiveCfg = Debug|Any CPU
{A55A00B6-BABA-414D-A38F-C4CAB4B9331B}.CodeCoverage|Any CPU.Build.0 = Debug|Any CPU
{A55A00B6-BABA-414D-A38F-C4CAB4B9331B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A55A00B6-BABA-414D-A38F-C4CAB4B9331B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A55A00B6-BABA-414D-A38F-C4CAB4B9331B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A55A00B6-BABA-414D-A38F-C4CAB4B9331B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -132,6 +160,11 @@ Global
{FADB4DA5-7927-4505-AE23-09481B221FED} = {34DAEE1A-E6E8-4059-9142-BF0170F3EAA8}
{6AF2C7B5-C749-47B0-BDE7-55F57C70E961} = {34DAEE1A-E6E8-4059-9142-BF0170F3EAA8}
{4765DE78-0E50-4F41-9603-8B598A56D4C4} = {34DAEE1A-E6E8-4059-9142-BF0170F3EAA8}
{2C06F377-0612-431F-BA91-A2F5A561E789} = {2E4AF4B3-04D0-4950-979B-B04052B8E20A}
{CB2C4940-747F-4C45-9EA8-4C98F7F3AD41} = {2E4AF4B3-04D0-4950-979B-B04052B8E20A}
{40D0EFBC-3D80-42C8-9623-B9CAD4B96EFF} = {2E4AF4B3-04D0-4950-979B-B04052B8E20A}
{2B79BE65-8725-42FE-9F63-BC1797080E70} = {40D0EFBC-3D80-42C8-9623-B9CAD4B96EFF}
{A55A00B6-BABA-414D-A38F-C4CAB4B9331B} = {40D0EFBC-3D80-42C8-9623-B9CAD4B96EFF}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {114E5850-267D-4B44-ACD5-91ACA382DDBC}

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

@ -10,16 +10,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Hubs
{
public class EdgeHub : EdgeModule
{
public EdgeHub()
{
Upstream = new Upstream<JsonMessage>(this);
Downstream = new Downstream<JsonMessage>(this);
}
public override string Name => Agent.Constants.EdgeHubModuleIdentityName;
public Upstream<JsonMessage> Upstream { get; set; }
public Downstream<JsonMessage> Downstream { get; set; }
private IConfigurationRoot HubServiceConfiguration { get; set; }
public override CreationResult Configure(IConfigurationRoot configuration)

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

@ -9,6 +9,7 @@
<ItemGroup>
<PackageReference Include="Autofac" Version="4.8.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.2" />
<PackageReference Include="Autofac.Extras.DynamicProxy" Version="4.4.0" />
<PackageReference Include="Microsoft.Azure.Devices" Version="1.16.0-preview-003" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.0.1" />

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

@ -0,0 +1,13 @@
using Castle.DynamicProxy;
using System.Dynamic;
namespace Microsoft.Azure.IoT.TypeEdge
{
internal class ModuleProxy: IInterceptor
{
public void Intercept(IInvocation invocation)
{
}
}
}

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

@ -0,0 +1,8 @@
using System;
namespace Microsoft.Azure.IoT.TypeEdge.Modules
{
public class EdgeMethodAttribute : Attribute
{
}
}

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

@ -29,11 +29,13 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
private ITransportSettings[] TransportSettings { get; set; }
private Dictionary<string, MessageCallback> Subscriptions { get; set; }
public Upstream<JsonMessage> Upstream { get; set; }
public EdgeModule()
{
Subscriptions = new Dictionary<string, MessageCallback>();
Routes = new List<string>();
Upstream = new Upstream<JsonMessage>(this);
var props = GetType().GetProperties();
@ -56,6 +58,9 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
}
public virtual string Name { get { return this.GetType().Name; } }
public virtual void ConfigureSubscriptions()
{
}
public virtual CreationResult Configure(IConfigurationRoot configuration)
{
return CreationResult.OK;
@ -155,7 +160,6 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
public Output<DiagnosticsMessage> DiagnosticsOutput { get; set; }
public void DependsOn(EdgeModule module)
{
}

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

@ -0,0 +1,6 @@
namespace Microsoft.Azure.IoT.TypeEdge.Modules
{
public class EdgeModuleProxy<T>
{
}
}

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

@ -7,7 +7,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
{
public string Name { get; set; }
public abstract string RouteName { get; }
public EdgeModule Module { get; set; }
internal EdgeModule Module { get; set; }
public Endpoint(string name, EdgeModule module)
{

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

@ -0,0 +1,6 @@
namespace Microsoft.Azure.IoT.TypeEdge.Modules
{
public class MethodArgument
{
}
}

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

@ -0,0 +1,8 @@
namespace Microsoft.Azure.IoT.TypeEdge.Modules
{
public enum MethodResult
{
OK,
Error
}
}

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

@ -12,7 +12,6 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
}
public override string RouteName => $"/messages/modules/{this.Module.Name}/outputs/{Name}";
public string ModuleName { get { return Module.Name; } }
public async Task<PublishResult> PublishAsync(T message)
{

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

@ -19,65 +19,91 @@ using Microsoft.Azure.Devices.Common.Exceptions;
using Newtonsoft.Json;
using Microsoft.Azure.Devices.Shared;
using Newtonsoft.Json.Linq;
using System.Linq;
using Autofac.Extras.DynamicProxy;
using Castle.DynamicProxy;
namespace Microsoft.Azure.IoT.TypeEdge
{
public abstract class TypeEdgeApplication
public class TypeEdgeApplication
{
public IConfigurationRoot Configuration { get; }
public IContainer Container { get; private set; }
IConfigurationRoot configuration;
IContainer container;
ContainerBuilder containerBuilder;
ModuleCollection modules;
EdgeHub hub;
public void RegisterModule<_IModule, _TModule>()
where _IModule : class
where _TModule : class
{
//containerBuilder.RegisterType<_TModule>();
//containerBuilder.RegisterInstance(new ProxyGenerator().CreateInterfaceProxyWithoutTarget<_IModule>(new ModuleProxy()) as _IModule);
containerBuilder.RegisterType<_TModule>().AsSelf().As<_IModule>();
}
public EdgeHub Hub { get; set; }
public ModuleCollection Modules { get; private set; }
public TypeEdgeApplication(IConfigurationRoot configuration)
{
Configuration = configuration;
this.configuration = configuration;
this.containerBuilder = new ContainerBuilder();
hub = new EdgeHub();
// add the framework services
var services = new ServiceCollection().AddLogging();
}
public void Build()
{
//read the configuration first
var (iotHubConnectionString, deviceId) = ReadConfiguration();
Modules = new ModuleCollection();
//setup the container
BuildContainer();
Hub = new EdgeHub();
this.modules = CreateModules();
Compose();
var deviceSasKey = ProvisionDeviceAsync(iotHubConnectionString, deviceId, this.modules).Result;
Container = BuildContainer(services);
ConfigureModules(iotHubConnectionString, deviceId);
BuildHub(iotHubConnectionString, deviceId, deviceSasKey);
}
IContainer BuildContainer(IServiceCollection services)
#region Build
private void BuildContainer()
{
var builder = new ContainerBuilder();
builder.Populate(services);
builder.RegisterBuildCallback(c => { });
var services = new ServiceCollection().AddLogging();
containerBuilder.Populate(services);
containerBuilder.RegisterBuildCallback(c => { });
var iotHubConnectionString = Configuration.GetValue<string>(Agent.Constants.IotHubConnectionStringKey);
container = containerBuilder.Build();
}
private (string iotHubConnectionString, string deviceId) ReadConfiguration()
{
var iotHubConnectionString = configuration.GetValue<string>(Agent.Constants.IotHubConnectionStringKey);
if (String.IsNullOrEmpty(iotHubConnectionString))
throw new Exception($"Missing {Agent.Constants.IotHubConnectionStringKey} value in configuration");
var deviceId = Configuration.GetValue<string>("DeviceId");
var deviceId = configuration.GetValue<string>("DeviceId");
if (String.IsNullOrEmpty(deviceId))
throw new Exception($"Missing DeviceId value in configuration");
#region edge hub config
return (iotHubConnectionString, deviceId);
}
//configure the edge hub
private void BuildHub(string iotHubConnectionString, string deviceId, string deviceSasKey)
{
//Calculate the Hub Enviroment Varialbes
var currentLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
Environment.SetEnvironmentVariable(HubService.Constants.SslCertEnvName,
"edge-hub-server.cert.pfx");
Environment.SetEnvironmentVariable(HubService.Constants.SslCertPathEnvName,
Path.Combine(currentLocation, @"Certificates\edge-hub-server\cert\"));
Environment.SetEnvironmentVariable(HubService.Constants.SslCertEnvName, "edge-hub-server.cert.pfx");
Environment.SetEnvironmentVariable(HubService.Constants.SslCertPathEnvName, Path.Combine(
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
@"Certificates\edge-hub-server\cert\"));
Environment.SetEnvironmentVariable("EdgeModuleHubServerCAChainCertificateFile", Path.Combine(
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
@"Certificates\edge-chain-ca\cert\edge-chain-ca.cert.pem"));
var storageFolder = Path.Combine(
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
@"Storage");
Environment.SetEnvironmentVariable("EdgeModuleHubServerCAChainCertificateFile",
Path.Combine(currentLocation, @"Certificates\edge-chain-ca\cert\edge-chain-ca.cert.pem"));
var storageFolder = Path.Combine(currentLocation, @"Storage");
var hubStorageFolder = Path.Combine(storageFolder, HubService.Constants.EdgeHubStorageFolder);
@ -85,23 +111,6 @@ namespace Microsoft.Azure.IoT.TypeEdge
Directory.CreateDirectory(hubStorageFolder);
Environment.SetEnvironmentVariable("storageFolder", storageFolder);
#endregion
var deviceSasKey = ProvisionDeviceAsync(iotHubConnectionString, deviceId, Modules).Result;
foreach (var module in Modules)
{
var moduleConnectionString = GetModuleConnectionStringAsync(iotHubConnectionString, deviceId, module.Name).Result;
Environment.SetEnvironmentVariable(Agent.Constants.EdgeHubConnectionStringKey, moduleConnectionString);
var moduleConfiguration = new ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
module.InternalConfigure(moduleConfiguration);
}
var csBuilder = IotHubConnectionStringBuilder.Create(iotHubConnectionString);
var edgeConnectionString = new Agent.ModuleConnectionString.ModuleConnectionStringBuilder(csBuilder.HostName, deviceId)
@ -116,12 +125,43 @@ namespace Microsoft.Azure.IoT.TypeEdge
.AddEnvironmentVariables()
.Build();
Hub.InternalConfigure(edgeHubConfiguration);
IContainer container = builder.Build();
return container;
hub.InternalConfigure(edgeHubConfiguration);
}
private void ConfigureModules(string iotHubConnectionString, string deviceId)
{
foreach (var module in this.modules)
{
var moduleConnectionString = GetModuleConnectionStringAsync(iotHubConnectionString, deviceId, module.Name).Result;
Environment.SetEnvironmentVariable(Agent.Constants.EdgeHubConnectionStringKey, moduleConnectionString);
var moduleConfiguration = new ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
module.InternalConfigure(moduleConfiguration);
}
}
private ModuleCollection CreateModules()
{
var modules = new ModuleCollection();
using (var scope = container.BeginLifetimeScope())
{
foreach (var moduleType in container.ComponentRegistry.Registrations.Where(r => typeof(EdgeModule).IsAssignableFrom(r.Activator.LimitType)).Select(r => r.Activator.LimitType).Distinct())
{
var module = scope.Resolve(moduleType) as EdgeModule;
module.ConfigureSubscriptions();
modules.Add(module);
}
}
return modules;
}
private async Task<string> ProvisionDeviceAsync(string iotHubConnectionString, string deviceId, ModuleCollection modules)
{
var csBuilder = IotHubConnectionStringBuilder.Create(iotHubConnectionString);
@ -157,19 +197,26 @@ namespace Microsoft.Azure.IoT.TypeEdge
createOptions = $" -e __MODULE_NAME='{module.Name}' "
}
}));
}
try
{
await registryManager.AddModuleAsync(new Devices.Module(deviceId, module.Name));
}
catch (ModuleAlreadyExistsException)
{
}
}
var twinContent = new TwinContent();
config.ModuleContent["$edgeHub"] = twinContent;
var routes = new Dictionary<string, string>();
foreach (var route in Hub.Routes)
foreach (var route in hub.Routes)
{
routes[$"route{routes.Count}"] = route;
}
foreach (var module in Modules)
foreach (var module in this.modules)
{
foreach (var route in module.Routes)
{
@ -219,43 +266,18 @@ namespace Microsoft.Azure.IoT.TypeEdge
.WithSharedAccessKey(sasKey)
.Build();
}
//private async Task<string> ProvisionModuleAsync(string iotHubConnectionString, string deviceId, string moduleName)
//{
// var csBuilder = IotHubConnectionStringBuilder.Create(iotHubConnectionString);
// RegistryManager registryManager = RegistryManager.CreateFromConnectionString(iotHubConnectionString);
// string sasKey = null;
// try
// {
// var module = await registryManager.AddModuleAsync(new Devices.Module(deviceId, moduleName));
// sasKey = module.Authentication.SymmetricKey.PrimaryKey;
// }
// catch (ModuleAlreadyExistsException)
// {
// var module = await registryManager.GetModuleAsync(deviceId, moduleName);
// sasKey = module.Authentication.SymmetricKey.PrimaryKey;
// }
// return new Agent.ModuleConnectionString.ModuleConnectionStringBuilder(csBuilder.IotHubName, deviceId)
// .WithGatewayHostName(Environment.MachineName)
// .WithModuleId(moduleName)
// .WithSharedAccessKey(sasKey)
// .Build();
//}
public abstract CompositionResult Compose();
#endregion
public async Task RunAsync()
{
List<Task> tasks = new List<Task>();
tasks.Add(Hub.RunAsync());
tasks.Add(hub.RunAsync());
//start all modules
foreach (var module in Modules)
{
foreach (var module in modules)
tasks.Add(module.InternalRunAsync());
}
await Task.WhenAll(tasks.ToArray());
}
}
}

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

@ -0,0 +1,35 @@
using Microsoft.Azure.IoT.TypeEdge.Modules;
using ThermostatApplication;
using ThermostatApplication.Messages;
using ThermostatApplication.Modules;
namespace Modules
{
public class NormalizeTemperatureModule : EdgeModule, INormalizeTemperatureModule
{
ITemperatureModule temperatureModuleProxy;
public Input<TemperatureModuleOutput> Temperature { get; set; }
public Output<TemperatureModuleOutput> NormalizedTemperature { get; set; }
public NormalizeTemperatureModule(ITemperatureModule proxy)
{
temperatureModuleProxy = proxy;
}
public override void ConfigureSubscriptions() {
Temperature.Subscribe(temperatureModuleProxy.Temperature, async (temp) =>
{
if (temp.Scale == TemperatureScale.Celsius)
temp.Temperature = temp.Temperature * 9 / 5 + 32;
await NormalizedTemperature.PublishAsync(temp);
return MessageResult.OK;
});
Upstream.Subscribe(NormalizedTemperature);
}
}
}

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

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.Azure.IoT.TypeEdge\Microsoft.Azure.IoT.TypeEdge.csproj" />
<ProjectReference Include="..\ThermostatApplication.Shared\ThermostatApplication.Shared.csproj" />
</ItemGroup>
</Project>

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

@ -1,15 +1,15 @@
using Microsoft.Azure.IoT.TypeEdge;
using Microsoft.Azure.IoT.TypeEdge.Modules;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ThermostatApplication;
using ThermostatApplication.Messages;
using ThermostatApplication.Modules;
namespace ThermpostatEdgeApplication.Modules
namespace Modules
{
public class TemperatureModule : EdgeModule
public class TemperatureModule : EdgeModule, ITemperatureModule
{
public Output<TemperatureModuleOutput> Temperature { get; set; }

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

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.Azure.IoT.TypeEdge\Microsoft.Azure.IoT.TypeEdge.csproj" />
<ProjectReference Include="..\ThermostatApplication.Shared\ThermostatApplication.Shared.csproj" />
</ItemGroup>
</Project>

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

@ -0,0 +1,30 @@
using Microsoft.Azure.IoT.TypeEdge;
using Microsoft.Extensions.Configuration;
using Modules;
using System;
using System.Threading.Tasks;
using ThermostatApplication.Modules;
namespace ThermostatApplication.EdgeHost
{
class Program
{
static async Task Main(string[] args)
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings_thermostat.json")
.Build();
var edgeApp = new TypeEdgeApplication(configuration);
edgeApp.RegisterModule<ITemperatureModule, TemperatureModule>();
edgeApp.RegisterModule<INormalizeTemperatureModule, NormalizeTemperatureModule>();
edgeApp.Build();
await edgeApp.RunAsync();
Console.WriteLine("Press <ENTER> to exit..");
Console.ReadLine();
}
}
}

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

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.0-rc1-final" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.Azure.IoT.TypeEdge\Microsoft.Azure.IoT.TypeEdge.csproj" />
<ProjectReference Include="..\NormalizeTemperatureModule\NormalizeTemperatureModule.csproj" />
<ProjectReference Include="..\TemperatureModule\TemperatureModule.csproj" />
<ProjectReference Include="..\ThermostatApplication.Shared\ThermostatApplication.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings_thermostat.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

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

@ -2,6 +2,6 @@
"appSettings": {
},
"iotHubConnectionString": "HostName=iotedgedev-iothub-7389d7.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=68K3zvI8CKbN7NM5s46N9rlP+zvPHPJKg7shy1rwMRU=",
"deviceId": "iotedgedev-edgedevice-new",
"deviceId": "type-edge-dev-device",
"RuntimeLogLevel": "info"
}

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

@ -5,7 +5,7 @@ using Microsoft.Azure.IoT.TypeEdge.Hubs;
using Microsoft.Azure.IoT.TypeEdge.Modules;
using Newtonsoft.Json;
namespace ThermpostatEdgeApplication
namespace ThermostatApplication.Messages
{
public class TemperatureModuleInput : IEdgeMessage
{

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

@ -5,7 +5,7 @@ using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace ThermpostatEdgeApplication
namespace ThermostatApplication.Messages
{
public class TemperatureModuleOutput : IEdgeMessage
{

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

@ -0,0 +1,10 @@
using Microsoft.Azure.IoT.TypeEdge.Modules;
using ThermostatApplication.Messages;
namespace ThermostatApplication.Modules
{
public interface INormalizeTemperatureModule
{
Output<TemperatureModuleOutput> NormalizedTemperature { get; set; }
}
}

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

@ -0,0 +1,14 @@
using System;
using System.Threading.Tasks;
using Microsoft.Azure.IoT.TypeEdge;
using Microsoft.Azure.IoT.TypeEdge.Hubs;
using Microsoft.Azure.IoT.TypeEdge.Modules;
using ThermostatApplication.Messages;
namespace ThermostatApplication.Modules
{
public interface ITemperatureModule
{
Output<TemperatureModuleOutput> Temperature { get; set; }
}
}

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

@ -1,4 +1,4 @@
namespace ThermpostatEdgeApplication
namespace ThermostatApplication
{
public enum TemperatureScale
{

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

@ -1,9 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
@ -14,10 +12,4 @@
<ProjectReference Include="..\Microsoft.Azure.IoT.TypeEdge\Microsoft.Azure.IoT.TypeEdge.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings_thermostat.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

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

@ -1,19 +0,0 @@
using Autofac;
using Microsoft.Azure.IoT.TypeEdge;
using Microsoft.Azure.IoT.TypeEdge.Modules;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ThermpostatEdgeApplication.Modules
{
public class NormalizeTemperatureModule : EdgeModule
{
public Input<TemperatureModuleOutput> Temperature { get; set; }
public Output<TemperatureModuleOutput> NormalizedTemperature { get; set; }
}
}

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

@ -1,9 +0,0 @@
using Microsoft.Azure.IoT.TypeEdge.Modules;
namespace ThermpostatEdgeApplication
{
public class NormalizeTemperatureOptions : IModuleOptions
{
public string DeviceConnectionString { get; set; }
}
}

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

@ -1,9 +0,0 @@
using Microsoft.Azure.IoT.TypeEdge.Modules;
namespace ThermpostatEdgeApplication
{
public class ReadTemperatureOptions : IModuleOptions
{
public string DeviceConnectionString { get; set; }
}
}

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

@ -1,25 +0,0 @@
using Microsoft.Extensions.Configuration;
using System;
using System.IO;
using System.Threading.Tasks;
namespace ThermpostatEdgeApplication
{
class Program
{
static async Task Main(string[] args)
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings_thermostat.json")
.AddEnvironmentVariables()
.Build();
var edgeApp = new ThermostatApplication(configuration);
await edgeApp.RunAsync();
Console.WriteLine("Press <ENTER> to exit..");
Console.ReadLine();
}
}
}

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

@ -1,46 +0,0 @@
using Microsoft.Azure.IoT.TypeEdge;
using Microsoft.Azure.IoT.TypeEdge.Hubs;
using Microsoft.Azure.IoT.TypeEdge.Modules;
using Microsoft.Extensions.Configuration;
using ThermpostatEdgeApplication.Modules;
namespace ThermpostatEdgeApplication
{
public class ThermostatApplication : TypeEdgeApplication
{
public ThermostatApplication(IConfigurationRoot configuration)
: base(configuration)
{
}
public override CompositionResult Compose()
{
//setup modules
var temperatureModule = new TemperatureModule();
var normalizeTemperatureModule = new NormalizeTemperatureModule();
Modules.Add(temperatureModule);
Modules.Add(normalizeTemperatureModule);
//setup the modules pub/sub
temperatureModule.DefaultInput.Subscribe(Hub.Downstream, async (msg) => { return MessageResult.OK; });
normalizeTemperatureModule.Temperature.Subscribe(temperatureModule.Temperature, async (temp) =>
{
if (temp.Scale == TemperatureScale.Celsius)
temp.Temperature = temp.Temperature * 9 / 5 + 32;
await normalizeTemperatureModule.NormalizedTemperature.PublishAsync(temp);
return MessageResult.OK;
});
Hub.Upstream.Subscribe(normalizeTemperatureModule.NormalizedTemperature);
//setup module startup depedencies
normalizeTemperatureModule.DependsOn(temperatureModule);
return CompositionResult.OK;
}
}
}