зеркало из https://github.com/Azure/TypeEdge.git
reference data added
This commit is contained in:
Родитель
cf8d0191b9
Коммит
40f0571b17
|
@ -0,0 +1,30 @@
|
|||
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Messages;
|
||||
using ThermostatApplication.Messages;
|
||||
using ThermostatApplication.Modules;
|
||||
|
||||
namespace Modules
|
||||
{
|
||||
public class AnomalyDetection : EdgeModule, IAnomalyDetection
|
||||
{
|
||||
public Input<Temperature> Temperature { get; set; }
|
||||
public Input<Reference<Sample>> Samples { get; set; }
|
||||
public Output<Anomaly> Anomaly { get; set; }
|
||||
|
||||
public AnomalyDetection(IPreprocessor preprocessor, IDataSampling trainer)
|
||||
{
|
||||
Temperature.Subscribe(preprocessor.Detection, async signal =>
|
||||
{
|
||||
return MessageResult.Ok;
|
||||
});
|
||||
Samples.Subscribe(trainer.Samples, async (sampleReference) =>
|
||||
{
|
||||
System.Console.WriteLine("New Sample");
|
||||
System.Console.WriteLine($"Length = {sampleReference.Message.Data.Length}");
|
||||
return MessageResult.Ok;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<ApplicationIcon />
|
||||
<LangVersion>latest</LangVersion>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Configurations>Debug;Release;TemplateDevelopment</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.68" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Microsoft.Azure.IoT.TypeEdge\Microsoft.Azure.IoT.TypeEdge.csproj" Condition="'$(Configuration)|$(Platform)'=='TemplateDevelopment|AnyCPU'" />
|
||||
<ProjectReference Include="..\..\Thermostat.Shared\Thermostat.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,22 @@
|
|||
ARG base_tag=2.1.0-runtime-bionic
|
||||
FROM microsoft/dotnet:${base_tag} AS base
|
||||
WORKDIR /app
|
||||
|
||||
FROM microsoft/dotnet:2.1-sdk AS build
|
||||
WORKDIR /src
|
||||
COPY Modules/AnomalyDetection/AnomalyDetection.csproj Modules/AnomalyDetection/
|
||||
COPY Thermostat.Shared/Thermostat.Shared.csproj Thermostat.Shared/
|
||||
COPY NuGet.Config ./
|
||||
RUN dotnet restore Modules/AnomalyDetection/AnomalyDetection.csproj
|
||||
COPY . .
|
||||
WORKDIR /src/Modules/AnomalyDetection
|
||||
RUN dotnet build AnomalyDetection.csproj -c Release -o /app
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish AnomalyDetection.csproj -c Release -o /app
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app .
|
||||
ENTRYPOINT ["dotnet", "AnomalyDetection.dll"]
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Messages;
|
||||
using System.Collections.Generic;
|
||||
using ThermostatApplication.Messages;
|
||||
using ThermostatApplication.Modules;
|
||||
|
||||
namespace Modules
|
||||
{
|
||||
public class DataSampling : EdgeModule, IDataSampling
|
||||
{
|
||||
List<Temperature> _sample;
|
||||
|
||||
public Input<Temperature> Temperature { get; set; }
|
||||
public Output<Reference<Sample>> Samples { get; set; }
|
||||
|
||||
public DataSampling(IPreprocessor proxy)
|
||||
{
|
||||
_sample = new List<Temperature>();
|
||||
Temperature.Subscribe(proxy.Training, async signal =>
|
||||
{
|
||||
_sample.Add(signal);
|
||||
if (_sample.Count > 999)
|
||||
{
|
||||
await Samples.PublishAsync(new Reference<Sample>()
|
||||
{
|
||||
Message = new Sample() { Data = _sample.ToArray() }
|
||||
});
|
||||
_sample.Clear();
|
||||
}
|
||||
return MessageResult.Ok;
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<ApplicationIcon />
|
||||
<LangVersion>latest</LangVersion>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Configurations>Debug;Release;TemplateDevelopment</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.68" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Microsoft.Azure.IoT.TypeEdge\Microsoft.Azure.IoT.TypeEdge.csproj" Condition="'$(Configuration)|$(Platform)'=='TemplateDevelopment|AnyCPU'" />
|
||||
<ProjectReference Include="..\..\Thermostat.Shared\Thermostat.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,22 @@
|
|||
ARG base_tag=2.1.0-runtime-bionic
|
||||
FROM microsoft/dotnet:${base_tag} AS base
|
||||
WORKDIR /app
|
||||
|
||||
FROM microsoft/dotnet:2.1-sdk AS build
|
||||
WORKDIR /src
|
||||
COPY Modules/DataSampling/DataSampling.csproj Modules/DataSampling/
|
||||
COPY Thermostat.Shared/Thermostat.Shared.csproj Thermostat.Shared/
|
||||
COPY NuGet.Config ./
|
||||
RUN dotnet restore Modules/DataSampling/DataSampling.csproj
|
||||
COPY . .
|
||||
WORKDIR /src/Modules/DataSampling
|
||||
RUN dotnet build DataSampling.csproj -c Release -o /app
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish DataSampling.csproj -c Release -o /app
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app .
|
||||
ENTRYPOINT ["dotnet", "DataSampling.dll"]
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
FROM microsoft/dotnet:2.1-runtime AS base
|
||||
WORKDIR /app
|
||||
|
||||
FROM microsoft/dotnet:2.1-sdk AS build
|
||||
WORKDIR /src
|
||||
COPY Modules/NormalizeTemperatureModule/NormalizeTemperatureModule.csproj Modules/NormalizeTemperatureModule/
|
||||
COPY Thermostat.Shared/Thermostat.Shared.csproj Thermostat.Shared/
|
||||
COPY NuGet.Config ./
|
||||
RUN dotnet restore Modules/NormalizeTemperatureModule/NormalizeTemperatureModule.csproj
|
||||
COPY . .
|
||||
WORKDIR /src/Modules/NormalizeTemperatureModule
|
||||
RUN dotnet build NormalizeTemperatureModule.csproj -c Release -o /app
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish NormalizeTemperatureModule.csproj -c Release -o /app
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app .
|
||||
ENTRYPOINT ["dotnet", "NormalizeTemperatureModule.dll"]
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Enums;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Enums;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Messages;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Twins;
|
||||
using ThermostatApplication;
|
||||
using ThermostatApplication.Messages;
|
||||
using ThermostatApplication.Modules;
|
||||
using ThermostatApplication.Twins;
|
||||
|
||||
namespace Modules
|
||||
{
|
||||
public class NormalizeTemperatureModule : EdgeModule, INormalizeTemperatureModule
|
||||
{
|
||||
//memory state
|
||||
private TemperatureScale _scale;
|
||||
|
||||
public NormalizeTemperatureModule(ITemperatureModule proxy)
|
||||
{
|
||||
Temperature.Subscribe(proxy.Temperature, async temp =>
|
||||
{
|
||||
Console.WriteLine("New Message in NormalizeTemperatureModule.");
|
||||
if (temp.Scale != _scale)
|
||||
if (_scale == TemperatureScale.Celsius)
|
||||
temp.Temperature = temp.Temperature * 9 / 5 + 32;
|
||||
await NormalizedTemperature.PublishAsync(temp);
|
||||
|
||||
return MessageResult.Ok;
|
||||
});
|
||||
|
||||
Twin.Subscribe(async twin =>
|
||||
{
|
||||
_scale = twin.Scale;
|
||||
await Twin.ReportAsync(twin);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
ARG base_tag=2.1.0-runtime-bionic
|
||||
FROM microsoft/dotnet:${base_tag} AS base
|
||||
WORKDIR /app
|
||||
|
||||
FROM microsoft/dotnet:2.1-sdk AS build
|
||||
WORKDIR /src
|
||||
COPY Modules/Preprocessor/Preprocessor.csproj Modules/Preprocessor/
|
||||
COPY Thermostat.Shared/Thermostat.Shared.csproj Thermostat.Shared/
|
||||
COPY NuGet.Config ./
|
||||
RUN dotnet restore Modules/Preprocessor/Preprocessor.csproj
|
||||
COPY . .
|
||||
WORKDIR /src/Modules/Preprocessor
|
||||
RUN dotnet build Preprocessor.csproj -c Release -o /app
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish Preprocessor.csproj -c Release -o /app
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app .
|
||||
ENTRYPOINT ["dotnet", "Preprocessor.dll"]
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Enums;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Enums;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Messages;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Twins;
|
||||
using ThermostatApplication;
|
||||
using ThermostatApplication.Messages;
|
||||
using ThermostatApplication.Modules;
|
||||
using ThermostatApplication.Twins;
|
||||
|
||||
namespace Modules
|
||||
{
|
||||
public class Preprocessor : EdgeModule, IPreprocessor
|
||||
{
|
||||
public Input<Temperature> Temperature { get; set; }
|
||||
public Output<Temperature> Training { get; set; }
|
||||
public Output<Temperature> Detection { get; set; }
|
||||
public ModuleTwin<PreprocessorTwin> Twin { get; set; }
|
||||
|
||||
public Preprocessor(ITemperatureSensor proxy)
|
||||
{
|
||||
Temperature.Subscribe(proxy.Temperature, async signal =>
|
||||
{
|
||||
var twin = Twin.LastKnownTwin;
|
||||
if (twin != null)
|
||||
{
|
||||
if (signal.Scale != twin.Scale)
|
||||
if (twin.Scale == TemperatureScale.Celsius)
|
||||
signal.Value = signal.Value * 9 / 5 + 32;
|
||||
|
||||
await RouteMessageAsync(signal, twin.RoutingMode);
|
||||
}
|
||||
return MessageResult.Ok;
|
||||
});
|
||||
|
||||
Twin.Subscribe(async twin =>
|
||||
{
|
||||
System.Console.WriteLine($"Preprocessor: new routing : { twin.RoutingMode.ToString()}");
|
||||
await Twin.ReportAsync(twin);
|
||||
return TwinResult.Ok;
|
||||
});
|
||||
}
|
||||
|
||||
private async Task RouteMessageAsync(Temperature signal, Routing mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case Routing.None:
|
||||
break;
|
||||
case Routing.Train:
|
||||
await Training.PublishAsync(signal);
|
||||
break;
|
||||
case Routing.Detect:
|
||||
await Detection.PublishAsync(signal);
|
||||
break;
|
||||
case Routing.Both:
|
||||
var results = new Task<PublishResult>[] {
|
||||
Training.PublishAsync(signal),
|
||||
Detection.PublishAsync(signal)
|
||||
};
|
||||
await Task.WhenAll(results);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<ExecutionResult> RunAsync()
|
||||
{
|
||||
await Twin.GetAsync();
|
||||
return ExecutionResult.Ok;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.68" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
|
@ -0,0 +1,13 @@
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.IoT.TypeEdge;
|
||||
|
||||
namespace Modules
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
await Startup.DockerEntryPoint(args);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
FROM microsoft/dotnet:2.1-runtime AS base
|
||||
WORKDIR /app
|
||||
|
||||
FROM microsoft/dotnet:2.1-sdk AS build
|
||||
WORKDIR /src
|
||||
COPY Modules/TemperatureModule/TemperatureModule.csproj Modules/TemperatureModule/
|
||||
COPY Thermostat.Shared/Thermostat.Shared.csproj Thermostat.Shared/
|
||||
COPY NuGet.Config ./
|
||||
RUN dotnet restore Modules/TemperatureModule/TemperatureModule.csproj
|
||||
COPY . .
|
||||
WORKDIR /src/Modules/TemperatureModule
|
||||
RUN dotnet build TemperatureModule.csproj -c Release -o /app
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish TemperatureModule.csproj -c Release -o /app
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app .
|
||||
ENTRYPOINT ["dotnet", "TemperatureModule.dll"]
|
|
@ -0,0 +1,21 @@
|
|||
ARG base_tag=2.1.0-runtime-bionic
|
||||
FROM microsoft/dotnet:${base_tag} AS base
|
||||
WORKDIR /app
|
||||
|
||||
FROM microsoft/dotnet:2.1-sdk AS build
|
||||
WORKDIR /src
|
||||
COPY Modules/TemperatureSensor/TemperatureSensor.csproj Modules/TemperatureSensor/
|
||||
COPY Thermostat.Shared/Thermostat.Shared.csproj Thermostat.Shared/
|
||||
COPY NuGet.Config ./
|
||||
RUN dotnet restore Modules/TemperatureSensor/TemperatureSensor.csproj
|
||||
COPY . .
|
||||
WORKDIR /src/Modules/TemperatureSensor
|
||||
RUN dotnet build TemperatureSensor.csproj -c Release -o /app
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish TemperatureSensor.csproj -c Release -o /app
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app .
|
||||
ENTRYPOINT ["dotnet", "TemperatureSensor.dll"]
|
|
@ -0,0 +1,13 @@
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.IoT.TypeEdge;
|
||||
|
||||
namespace Modules
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
await Startup.DockerEntryPoint(args);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,9 +12,9 @@ using ThermostatApplication.Twins;
|
|||
|
||||
namespace Modules
|
||||
{
|
||||
public class TemperatureModule : EdgeModule, ITemperatureModule
|
||||
public class TemperatureSensor : EdgeModule, ITemperatureSensor
|
||||
{
|
||||
public Output<TemperatureModuleOutput> Temperature { get; set; }
|
||||
public Output<Temperature> Temperature { get; set; }
|
||||
public ModuleTwin<TemperatureTwin> Twin { get; set; }
|
||||
|
||||
public bool ResetSensor(int sensitivity)
|
||||
|
@ -25,16 +25,32 @@ namespace Modules
|
|||
|
||||
public override async Task<ExecutionResult> RunAsync()
|
||||
{
|
||||
double frequency = 0.5;
|
||||
int offset = 70;
|
||||
int amplitute = 10;
|
||||
int samplingRate = 25;
|
||||
|
||||
while (true)
|
||||
{
|
||||
await Temperature.PublishAsync(new TemperatureModuleOutput
|
||||
var sin = Math.Sin(2 * Math.PI * frequency * DateTime.Now.TimeOfDay.TotalSeconds);
|
||||
var value = amplitute
|
||||
* sin
|
||||
+ offset;
|
||||
|
||||
await Temperature.PublishAsync(new Temperature
|
||||
{
|
||||
Scale = TemperatureScale.Celsius,
|
||||
Temperature = new Random().NextDouble() * 100
|
||||
Value = value
|
||||
});
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
|
||||
|
||||
int left = 40;
|
||||
left = (int)(sin * left) + left;
|
||||
var text = new string('-', left);
|
||||
Console.WriteLine($"{value.ToString("F2")} {text}");
|
||||
|
||||
Thread.Sleep(1000 / samplingRate);
|
||||
}
|
||||
return await base.RunAsync();
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.68" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
|
@ -1,4 +1,5 @@
|
|||
FROM microsoft/dotnet:2.1-runtime AS base
|
||||
ARG base_tag=2.1.0-runtime-bionic
|
||||
FROM microsoft/dotnet:${base_tag} AS base
|
||||
|
||||
# Add an unprivileged user account for running Edge Hub
|
||||
RUN useradd -ms /bin/bash edgehubuser
|
||||
|
@ -35,8 +36,10 @@ FROM microsoft/dotnet:2.1-sdk AS build
|
|||
WORKDIR /src
|
||||
COPY Thermostat.Emulator/Thermostat.Emulator.csproj Thermostat.Emulator/
|
||||
COPY Thermostat.Shared/Thermostat.Shared.csproj Thermostat.Shared/
|
||||
COPY Modules/NormalizeTemperatureModule/NormalizeTemperatureModule.csproj Modules/NormalizeTemperatureModule/
|
||||
COPY Modules/TemperatureModule/TemperatureModule.csproj Modules/TemperatureModule/
|
||||
COPY Modules/Preprocessor/Preprocessor.csproj Modules/Preprocessor/
|
||||
COPY Modules/TemperatureSensor/TemperatureSensor.csproj Modules/TemperatureSensor/
|
||||
COPY Modules/DataSampling/DataSampling.csproj Modules/DataSampling/
|
||||
COPY Modules/AnomalyDetection/AnomalyDetection.csproj Modules/AnomalyDetection/
|
||||
COPY ./.env Thermostat.Emulator/
|
||||
COPY NuGet.Config ./
|
||||
RUN dotnet restore Thermostat.Emulator/Thermostat.Emulator.csproj
|
||||
|
|
|
@ -21,10 +21,12 @@ namespace ThermostatApplication
|
|||
|
||||
var host = new TypeEdgeHost(configuration);
|
||||
|
||||
host.RegisterModule<ITemperatureModule, TemperatureModule>();
|
||||
host.RegisterModule<INormalizeTemperatureModule, NormalizeTemperatureModule>();
|
||||
host.RegisterModule<ITemperatureSensor, TemperatureSensor>();
|
||||
host.RegisterModule<IPreprocessor, Preprocessor>();
|
||||
host.RegisterModule<IDataSampling, DataSampling>();
|
||||
host.RegisterModule<IAnomalyDetection, AnomalyDetection>();
|
||||
|
||||
host.Upstream.Subscribe(host.GetProxy<INormalizeTemperatureModule>().NormalizedTemperature);
|
||||
host.Upstream.Subscribe(host.GetProxy<IPreprocessor>().Detection);
|
||||
|
||||
host.Build();
|
||||
|
||||
|
|
|
@ -18,15 +18,17 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Host" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Host" Version="0.1.68" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
|
||||
<PackageReference Include="rocksdb-native-arm" Version="5.4.6" />
|
||||
<PackageReference Include="RocksDbNative" Version="5.4.6.10" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Microsoft.Azure.IoT.TypeEdge.Host\Microsoft.Azure.IoT.TypeEdge.Host.csproj" Condition="'$(Configuration)|$(Platform)'=='TemplateDevelopment|AnyCPU'" />
|
||||
<ProjectReference Include="..\Modules\NormalizeTemperatureModule\NormalizeTemperatureModule.csproj" />
|
||||
<ProjectReference Include="..\Modules\TemperatureModule\TemperatureModule.csproj" />
|
||||
<ProjectReference Include="..\Modules\AnomalyDetection\AnomalyDetection.csproj" />
|
||||
<ProjectReference Include="..\Modules\DataSampling\DataSampling.csproj" />
|
||||
<ProjectReference Include="..\Modules\Preprocessor\Preprocessor.csproj" />
|
||||
<ProjectReference Include="..\Modules\TemperatureSensor\TemperatureSensor.csproj" />
|
||||
<ProjectReference Include="..\Thermostat.Shared\Thermostat.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"TypeEdgeHost": {
|
||||
"IotHubConnectionString": "",
|
||||
"DeviceId": "type-edge-dev8",
|
||||
"IotHubConnectionString": "HostName=bugbashtypeedge.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=Ce7B3aoIyPwqdus+yTXQCkMmcqIfRE02ddRWLG5Zs7M=",
|
||||
"DeviceId": "type-edge-dev",
|
||||
"PrintDeploymentJson": "true"
|
||||
}
|
||||
}
|
|
@ -11,9 +11,29 @@ namespace Thermostat.ServiceApp
|
|||
{
|
||||
private static async Task Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Press <ENTER> to start..");
|
||||
Console.ReadLine();
|
||||
|
||||
ThermostatApplication.Twins.Routing routing = ThermostatApplication.Twins.Routing.None;
|
||||
while (true)
|
||||
{
|
||||
Console.WriteLine("Select Processor routing mode : (N)one, (T)rain, (D)etect, (B)oth");
|
||||
var res = Console.ReadLine();
|
||||
switch (res.ToUpper())
|
||||
{
|
||||
case "T":
|
||||
routing = ThermostatApplication.Twins.Routing.Train;
|
||||
break;
|
||||
case "N":
|
||||
break;
|
||||
case "D":
|
||||
routing = ThermostatApplication.Twins.Routing.Detect;
|
||||
break;
|
||||
case "B":
|
||||
routing = ThermostatApplication.Twins.Routing.Both;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings_thermostat.json")
|
||||
.AddEnvironmentVariables()
|
||||
|
@ -22,13 +42,14 @@ namespace Thermostat.ServiceApp
|
|||
ProxyFactory.Configure(configuration["IotHubConnectionString"],
|
||||
configuration["DeviceId"]);
|
||||
|
||||
var normalizer = ProxyFactory.GetModuleProxy<INormalizeTemperatureModule>();
|
||||
var normalizer = ProxyFactory.GetModuleProxy<IPreprocessor>();
|
||||
|
||||
var twin = await normalizer.Twin.GetAsync();
|
||||
twin.Scale = TemperatureScale.Celsius;
|
||||
twin.RoutingMode = routing;
|
||||
await normalizer.Twin.PublishAsync(twin);
|
||||
|
||||
var result = ProxyFactory.GetModuleProxy<ITemperatureModule>().ResetSensor(10);
|
||||
//var result = ProxyFactory.GetModuleProxy<ITemperatureSensor>().ResetSensor(10);
|
||||
|
||||
Console.WriteLine("Press <ENTER> to exit..");
|
||||
Console.ReadLine();
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.68" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'"/>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
{
|
||||
"DeviceId": "type-edge-dev",
|
||||
"IotHubConnectionString":
|
||||
"HostName=iotedgedev-iothub-7389d7.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=68K3zvI8CKbN7NM5s46N9rlP+zvPHPJKg7shy1rwMRU="
|
||||
"IotHubConnectionString": "HostName=bugbashtypeedge.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=Ce7B3aoIyPwqdus+yTXQCkMmcqIfRE02ddRWLG5Zs7M="
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using Microsoft.Azure.IoT.TypeEdge.Modules.Messages;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ThermostatApplication.Messages
|
||||
{
|
||||
public class Anomaly : EdgeMessage
|
||||
{
|
||||
public double Value { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
using Microsoft.Azure.IoT.TypeEdge.Modules.Messages;
|
||||
|
||||
namespace ThermostatApplication.Messages
|
||||
{
|
||||
public class Sample : EdgeMessage
|
||||
{
|
||||
public Temperature[] Data { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Messages;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ThermostatApplication.Messages
|
||||
{
|
||||
public class Temperature : EdgeMessage
|
||||
{
|
||||
public TemperatureScale Scale { get; set; }
|
||||
public double Value { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Messages;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ThermostatApplication.Messages
|
||||
{
|
||||
public class TemperatureModuleInput : IEdgeMessage
|
||||
{
|
||||
public int MyData { get; set; }
|
||||
public IDictionary<string, string> Properties { get; set; }
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(this));
|
||||
}
|
||||
|
||||
public void SetBytes(byte[] bytes)
|
||||
{
|
||||
var obj = JsonConvert.DeserializeObject<TemperatureModuleInput>(Encoding.UTF8.GetString(bytes));
|
||||
Properties = obj.Properties;
|
||||
MyData = obj.MyData;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Messages;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ThermostatApplication.Messages
|
||||
{
|
||||
public class TemperatureModuleOutput : IEdgeMessage
|
||||
{
|
||||
public TemperatureScale Scale { get; set; }
|
||||
public double Temperature { get; set; }
|
||||
public IDictionary<string, string> Properties { get; set; }
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(this));
|
||||
}
|
||||
|
||||
public void SetBytes(byte[] bytes)
|
||||
{
|
||||
var obj = JsonConvert.DeserializeObject<TemperatureModuleOutput>(Encoding.UTF8.GetString(bytes));
|
||||
Properties = obj.Properties;
|
||||
Scale = obj.Scale;
|
||||
Temperature = obj.Temperature;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
using Microsoft.Azure.IoT.TypeEdge.Attributes;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Messages;
|
||||
using ThermostatApplication.Messages;
|
||||
|
||||
namespace ThermostatApplication.Modules
|
||||
{
|
||||
[TypeModule]
|
||||
public interface IAnomalyDetection
|
||||
{
|
||||
Input<Temperature> Temperature { get; set; }
|
||||
Input<Reference<Sample>> Samples { get; set; }
|
||||
|
||||
Output<Anomaly> Anomaly { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
using Microsoft.Azure.IoT.TypeEdge.Attributes;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Messages;
|
||||
using ThermostatApplication.Messages;
|
||||
|
||||
namespace ThermostatApplication.Modules
|
||||
{
|
||||
[TypeModule]
|
||||
public interface IDataSampling
|
||||
{
|
||||
Input<Temperature> Temperature { get; set; }
|
||||
Output<Reference<Sample>> Samples { get; set; }
|
||||
}
|
||||
}
|
|
@ -7,10 +7,13 @@ using ThermostatApplication.Twins;
|
|||
namespace ThermostatApplication.Modules
|
||||
{
|
||||
[TypeModule]
|
||||
public interface INormalizeTemperatureModule
|
||||
public interface IPreprocessor
|
||||
{
|
||||
Output<TemperatureModuleOutput> NormalizedTemperature { get; set; }
|
||||
Input<Temperature> Temperature { get; set; }
|
||||
|
||||
ModuleTwin<NormalizerTwin> Twin { get; set; }
|
||||
Output<Temperature> Training { get; set; }
|
||||
Output<Temperature> Detection { get; set; }
|
||||
|
||||
ModuleTwin<PreprocessorTwin> Twin { get; set; }
|
||||
}
|
||||
}
|
|
@ -7,9 +7,9 @@ using ThermostatApplication.Twins;
|
|||
namespace ThermostatApplication.Modules
|
||||
{
|
||||
[TypeModule]
|
||||
public interface ITemperatureModule
|
||||
public interface ITemperatureSensor
|
||||
{
|
||||
Output<TemperatureModuleOutput> Temperature { get; set; }
|
||||
Output<Temperature> Temperature { get; set; }
|
||||
ModuleTwin<TemperatureTwin> Twin { get; set; }
|
||||
|
||||
bool ResetSensor(int sensitivity);
|
|
@ -10,7 +10,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.68" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
using Microsoft.Azure.IoT.TypeEdge.Twins;
|
||||
|
||||
namespace ThermostatApplication.Twins
|
||||
{
|
||||
public class NormalizerTwin : TypeModuleTwin
|
||||
{
|
||||
public TemperatureScale Scale { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using Microsoft.Azure.IoT.TypeEdge.Twins;
|
||||
|
||||
namespace ThermostatApplication.Twins
|
||||
{
|
||||
public enum Routing {
|
||||
None,
|
||||
Train,
|
||||
Detect,
|
||||
Both
|
||||
}
|
||||
public class PreprocessorTwin : TypeModuleTwin
|
||||
{
|
||||
public TemperatureScale Scale { get; set; }
|
||||
|
||||
public Routing RoutingMode { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
using Microsoft.Azure.IoT.TypeEdge.Volumes;
|
||||
using ThermostatApplication.Messages;
|
||||
|
||||
namespace ThermostatApplication.Modules
|
||||
{
|
||||
public interface ISharedVolume
|
||||
{
|
||||
Volume<Sample> Samples { get; set; }
|
||||
}
|
||||
}
|
|
@ -7,9 +7,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{8D82
|
|||
EndProject
|
||||
Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{1373DBDC-DC13-429E-8C17-2E4D85CF42BA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NormalizeTemperatureModule", "Modules\NormalizeTemperatureModule\NormalizeTemperatureModule.csproj", "{97D246B7-A79E-49A1-A9BA-2D1B8A6C26BF}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preprocessor", "Modules\NormalizeTemperatureModule\Preprocessor.csproj", "{97D246B7-A79E-49A1-A9BA-2D1B8A6C26BF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TemperatureModule", "Modules\TemperatureModule\TemperatureModule.csproj", "{73158509-5709-40DF-A5A9-89661B3000A7}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TemperatureSensor", "Modules\TemperatureModule\TemperatureSensor.csproj", "{73158509-5709-40DF-A5A9-89661B3000A7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thermostat.Emulator", "Thermostat.Emulator\Thermostat.Emulator.csproj", "{1A622C23-B9BD-4903-A28D-28B446BB358E}"
|
||||
EndProject
|
||||
|
@ -17,6 +17,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thermostat.Shared", "Thermo
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thermostat.ServiceApp", "Thermostat.ServiceApp\Thermostat.ServiceApp.csproj", "{258D1CCE-A112-46A2-88F1-D9BA50450C7B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ModelTraining", "Modules\ModelTraining\ModelTraining.csproj", "{866235F5-B323-465F-A248-F7575F630E05}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AnomalyDetection", "Modules\AnomalyDetection\AnomalyDetection.csproj", "{D29D8C1F-EEFD-42D7-A2AA-5F8DBBF44B06}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -60,6 +64,18 @@ Global
|
|||
{258D1CCE-A112-46A2-88F1-D9BA50450C7B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{258D1CCE-A112-46A2-88F1-D9BA50450C7B}.TemplateDevelopment|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
|
||||
{258D1CCE-A112-46A2-88F1-D9BA50450C7B}.TemplateDevelopment|Any CPU.Build.0 = TemplateDevelopment|Any CPU
|
||||
{866235F5-B323-465F-A248-F7575F630E05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{866235F5-B323-465F-A248-F7575F630E05}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{866235F5-B323-465F-A248-F7575F630E05}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{866235F5-B323-465F-A248-F7575F630E05}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{866235F5-B323-465F-A248-F7575F630E05}.TemplateDevelopment|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{866235F5-B323-465F-A248-F7575F630E05}.TemplateDevelopment|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D29D8C1F-EEFD-42D7-A2AA-5F8DBBF44B06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D29D8C1F-EEFD-42D7-A2AA-5F8DBBF44B06}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D29D8C1F-EEFD-42D7-A2AA-5F8DBBF44B06}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D29D8C1F-EEFD-42D7-A2AA-5F8DBBF44B06}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D29D8C1F-EEFD-42D7-A2AA-5F8DBBF44B06}.TemplateDevelopment|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
|
||||
{D29D8C1F-EEFD-42D7-A2AA-5F8DBBF44B06}.TemplateDevelopment|Any CPU.Build.0 = TemplateDevelopment|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -67,6 +83,8 @@ Global
|
|||
GlobalSection(NestedProjects) = preSolution
|
||||
{97D246B7-A79E-49A1-A9BA-2D1B8A6C26BF} = {8D822B22-E5A9-4165-B27B-458A70D2B44F}
|
||||
{73158509-5709-40DF-A5A9-89661B3000A7} = {8D822B22-E5A9-4165-B27B-458A70D2B44F}
|
||||
{866235F5-B323-465F-A248-F7575F630E05} = {8D822B22-E5A9-4165-B27B-458A70D2B44F}
|
||||
{D29D8C1F-EEFD-42D7-A2AA-5F8DBBF44B06} = {8D822B22-E5A9-4165-B27B-458A70D2B44F}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {E7BE10A1-BBA6-43BB-BC65-A9D38A168E00}
|
||||
|
|
|
@ -11,16 +11,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Example", "Example", "{C865
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{F2FF1756-9AAF-411B-8B54-3829EAC21515}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TemperatureModule", "Example\Modules\TemperatureModule\TemperatureModule.csproj", "{48302C68-971D-414F-A29D-742F79415D74}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{54587D56-7C22-4084-9321-84D57C2F6ECB} = {54587D56-7C22-4084-9321-84D57C2F6ECB}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NormalizeTemperatureModule", "Example\Modules\NormalizeTemperatureModule\NormalizeTemperatureModule.csproj", "{30A335A6-47C9-435A-BA23-50988EAF2C33}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{54587D56-7C22-4084-9321-84D57C2F6ECB} = {54587D56-7C22-4084-9321-84D57C2F6ECB}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thermostat.Shared", "Example\Thermostat.Shared\Thermostat.Shared.csproj", "{45F97F43-7C75-49B8-8525-7F0E9C7B9FB7}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{54587D56-7C22-4084-9321-84D57C2F6ECB} = {54587D56-7C22-4084-9321-84D57C2F6ECB}
|
||||
|
@ -40,6 +30,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thermostat.ServiceApp", "Ex
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.IoT.TypeEdge.Proxy", "Microsoft.Azure.IoT.TypeEdge.Proxy\Microsoft.Azure.IoT.TypeEdge.Proxy.csproj", "{E738845B-4D98-4CB9-BDA4-F83193FE81B5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AnomalyDetection", "Example\Modules\AnomalyDetection\AnomalyDetection.csproj", "{5E31547C-97D8-4B42-A909-A9F7DA23E50D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataSampling", "Example\Modules\DataSampling\DataSampling.csproj", "{FAB78513-F407-4A4F-9908-00E0096C2979}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preprocessor", "Example\Modules\Preprocessor\Preprocessor.csproj", "{18137F45-9592-4E25-B718-630B21DF48DF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TemperatureSensor", "Example\Modules\TemperatureSensor\TemperatureSensor.csproj", "{65C0C786-8C42-4B7D-A0B8-104FF9FA2CE5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
CodeCoverage|Any CPU = CodeCoverage|Any CPU
|
||||
|
@ -64,22 +62,6 @@ Global
|
|||
{6F13F88C-B271-4DA6-9A35-5FD7FEADD3A3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6F13F88C-B271-4DA6-9A35-5FD7FEADD3A3}.TemplateDevelopment|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
|
||||
{6F13F88C-B271-4DA6-9A35-5FD7FEADD3A3}.TemplateDevelopment|Any CPU.Build.0 = TemplateDevelopment|Any CPU
|
||||
{48302C68-971D-414F-A29D-742F79415D74}.CodeCoverage|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{48302C68-971D-414F-A29D-742F79415D74}.CodeCoverage|Any CPU.Build.0 = Debug|Any CPU
|
||||
{48302C68-971D-414F-A29D-742F79415D74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{48302C68-971D-414F-A29D-742F79415D74}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{48302C68-971D-414F-A29D-742F79415D74}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{48302C68-971D-414F-A29D-742F79415D74}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{48302C68-971D-414F-A29D-742F79415D74}.TemplateDevelopment|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
|
||||
{48302C68-971D-414F-A29D-742F79415D74}.TemplateDevelopment|Any CPU.Build.0 = TemplateDevelopment|Any CPU
|
||||
{30A335A6-47C9-435A-BA23-50988EAF2C33}.CodeCoverage|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{30A335A6-47C9-435A-BA23-50988EAF2C33}.CodeCoverage|Any CPU.Build.0 = Debug|Any CPU
|
||||
{30A335A6-47C9-435A-BA23-50988EAF2C33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{30A335A6-47C9-435A-BA23-50988EAF2C33}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{30A335A6-47C9-435A-BA23-50988EAF2C33}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{30A335A6-47C9-435A-BA23-50988EAF2C33}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{30A335A6-47C9-435A-BA23-50988EAF2C33}.TemplateDevelopment|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
|
||||
{30A335A6-47C9-435A-BA23-50988EAF2C33}.TemplateDevelopment|Any CPU.Build.0 = TemplateDevelopment|Any CPU
|
||||
{45F97F43-7C75-49B8-8525-7F0E9C7B9FB7}.CodeCoverage|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{45F97F43-7C75-49B8-8525-7F0E9C7B9FB7}.CodeCoverage|Any CPU.Build.0 = Debug|Any CPU
|
||||
{45F97F43-7C75-49B8-8525-7F0E9C7B9FB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
|
@ -112,17 +94,51 @@ Global
|
|||
{E738845B-4D98-4CB9-BDA4-F83193FE81B5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E738845B-4D98-4CB9-BDA4-F83193FE81B5}.TemplateDevelopment|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
|
||||
{E738845B-4D98-4CB9-BDA4-F83193FE81B5}.TemplateDevelopment|Any CPU.Build.0 = TemplateDevelopment|Any CPU
|
||||
{5E31547C-97D8-4B42-A909-A9F7DA23E50D}.CodeCoverage|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
|
||||
{5E31547C-97D8-4B42-A909-A9F7DA23E50D}.CodeCoverage|Any CPU.Build.0 = TemplateDevelopment|Any CPU
|
||||
{5E31547C-97D8-4B42-A909-A9F7DA23E50D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5E31547C-97D8-4B42-A909-A9F7DA23E50D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5E31547C-97D8-4B42-A909-A9F7DA23E50D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5E31547C-97D8-4B42-A909-A9F7DA23E50D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5E31547C-97D8-4B42-A909-A9F7DA23E50D}.TemplateDevelopment|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
|
||||
{5E31547C-97D8-4B42-A909-A9F7DA23E50D}.TemplateDevelopment|Any CPU.Build.0 = TemplateDevelopment|Any CPU
|
||||
{FAB78513-F407-4A4F-9908-00E0096C2979}.CodeCoverage|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
|
||||
{FAB78513-F407-4A4F-9908-00E0096C2979}.CodeCoverage|Any CPU.Build.0 = TemplateDevelopment|Any CPU
|
||||
{FAB78513-F407-4A4F-9908-00E0096C2979}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FAB78513-F407-4A4F-9908-00E0096C2979}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FAB78513-F407-4A4F-9908-00E0096C2979}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FAB78513-F407-4A4F-9908-00E0096C2979}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FAB78513-F407-4A4F-9908-00E0096C2979}.TemplateDevelopment|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
|
||||
{FAB78513-F407-4A4F-9908-00E0096C2979}.TemplateDevelopment|Any CPU.Build.0 = TemplateDevelopment|Any CPU
|
||||
{18137F45-9592-4E25-B718-630B21DF48DF}.CodeCoverage|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
|
||||
{18137F45-9592-4E25-B718-630B21DF48DF}.CodeCoverage|Any CPU.Build.0 = TemplateDevelopment|Any CPU
|
||||
{18137F45-9592-4E25-B718-630B21DF48DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{18137F45-9592-4E25-B718-630B21DF48DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{18137F45-9592-4E25-B718-630B21DF48DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{18137F45-9592-4E25-B718-630B21DF48DF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{18137F45-9592-4E25-B718-630B21DF48DF}.TemplateDevelopment|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
|
||||
{18137F45-9592-4E25-B718-630B21DF48DF}.TemplateDevelopment|Any CPU.Build.0 = TemplateDevelopment|Any CPU
|
||||
{65C0C786-8C42-4B7D-A0B8-104FF9FA2CE5}.CodeCoverage|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
|
||||
{65C0C786-8C42-4B7D-A0B8-104FF9FA2CE5}.CodeCoverage|Any CPU.Build.0 = TemplateDevelopment|Any CPU
|
||||
{65C0C786-8C42-4B7D-A0B8-104FF9FA2CE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{65C0C786-8C42-4B7D-A0B8-104FF9FA2CE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{65C0C786-8C42-4B7D-A0B8-104FF9FA2CE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{65C0C786-8C42-4B7D-A0B8-104FF9FA2CE5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{65C0C786-8C42-4B7D-A0B8-104FF9FA2CE5}.TemplateDevelopment|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
|
||||
{65C0C786-8C42-4B7D-A0B8-104FF9FA2CE5}.TemplateDevelopment|Any CPU.Build.0 = TemplateDevelopment|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{F2FF1756-9AAF-411B-8B54-3829EAC21515} = {C865B730-A5A7-4738-9F6E-CBC7AA306467}
|
||||
{48302C68-971D-414F-A29D-742F79415D74} = {F2FF1756-9AAF-411B-8B54-3829EAC21515}
|
||||
{30A335A6-47C9-435A-BA23-50988EAF2C33} = {F2FF1756-9AAF-411B-8B54-3829EAC21515}
|
||||
{45F97F43-7C75-49B8-8525-7F0E9C7B9FB7} = {C865B730-A5A7-4738-9F6E-CBC7AA306467}
|
||||
{2076DDEF-8EE3-4BC1-BF79-1C1F62A8719D} = {C865B730-A5A7-4738-9F6E-CBC7AA306467}
|
||||
{286CDAA1-5410-4322-AC1C-F35A83CDA63D} = {C865B730-A5A7-4738-9F6E-CBC7AA306467}
|
||||
{5E31547C-97D8-4B42-A909-A9F7DA23E50D} = {F2FF1756-9AAF-411B-8B54-3829EAC21515}
|
||||
{FAB78513-F407-4A4F-9908-00E0096C2979} = {F2FF1756-9AAF-411B-8B54-3829EAC21515}
|
||||
{18137F45-9592-4E25-B718-630B21DF48DF} = {F2FF1756-9AAF-411B-8B54-3829EAC21515}
|
||||
{65C0C786-8C42-4B7D-A0B8-104FF9FA2CE5} = {F2FF1756-9AAF-411B-8B54-3829EAC21515}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {114E5850-267D-4B44-ACD5-91ACA382DDBC}
|
||||
|
|
|
@ -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.55</version>
|
||||
<version>0.1.68</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.48" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.Azure.IoT.TypeEdge" version="0.1.68" 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>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
ARG base_tag=2.1-runtime-stretch-slim
|
||||
ARG base_tag=2.1.0-runtime-bionic
|
||||
FROM microsoft/dotnet:${base_tag}
|
||||
|
||||
# Add an unprivileged user account for running Edge Hub
|
||||
|
|
|
@ -17,6 +17,7 @@ using Microsoft.Azure.IoT.TypeEdge.Modules;
|
|||
using Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Messages;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Proxy;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Volumes;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
|
@ -159,12 +160,6 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host
|
|||
|
||||
var csBuilder = IotHubConnectionStringBuilder.Create(_options.IotHubConnectionString);
|
||||
|
||||
//new ModuleConnectionString.ModuleConnectionStringBuilder(csBuilder.HostName, _options.DeviceId)
|
||||
// .WithModuleId(Devices.Edge.Agent.Core.Constants.EdgeHubModuleName)
|
||||
// .WithModuleId(Devices.Edge.Agent.Core.Constants.EdgeHubModuleIdentityName)
|
||||
// .WithSharedAccessKey(deviceSasKey)
|
||||
// .Build();
|
||||
|
||||
var edgeConnectionString =
|
||||
new ModuleConnectionStringBuilder(csBuilder.HostName, _options.DeviceId)
|
||||
.Create(Devices.Edge.Agent.Core.Constants.EdgeHubModuleIdentityName)
|
||||
|
@ -241,6 +236,21 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host
|
|||
{
|
||||
if (!(scope.Resolve(moduleType) is EdgeModule module))
|
||||
continue;
|
||||
|
||||
|
||||
//foreach (var item in module.GetType().GetProperties())
|
||||
//{
|
||||
// if (!item.PropertyType.IsGenericType)
|
||||
// continue;
|
||||
// var genericDef = item.PropertyType.GetGenericTypeDefinition();
|
||||
// if (!genericDef.IsAssignableFrom(typeof(Volume<>)))
|
||||
// continue;
|
||||
|
||||
// //the ctor of this prop registers the volume
|
||||
// var instance = Activator.CreateInstance(
|
||||
// genericDef.MakeGenericType(item.PropertyType.GenericTypeArguments),
|
||||
// item.Name, module);
|
||||
//}
|
||||
modules.Add(module);
|
||||
}
|
||||
}
|
||||
|
@ -282,6 +292,12 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host
|
|||
|
||||
foreach (var module in _modules)
|
||||
{
|
||||
var volumes = "";
|
||||
if (module.Volumes.Count > 0)
|
||||
{
|
||||
var v = String.Join(',', module.Volumes.Select(e => $"\"{$"/env/{e.Key.ToLower()}"}\": {{}}"));
|
||||
volumes = $", \"Volumes\": {{ {v} }}";
|
||||
}
|
||||
modulesConfig?.Add(module.Name.ToLower(), JObject.FromObject(new
|
||||
{
|
||||
version = "1.0",
|
||||
|
@ -292,7 +308,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Host
|
|||
{
|
||||
image = dockerRegistry + module.Name.ToLower(),
|
||||
createOptions = "{\n \"Env\":[\n \"" + TypeEdge.Constants.ModuleNameConfigName + "=" +
|
||||
module.Name.ToLower() + "\"\n ]\n}"
|
||||
module.Name.ToLower() + $"\"\n ]\n {volumes} }}"
|
||||
}
|
||||
}));
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<PackageId>Microsoft.Azure.IoT.TypeEdge.Proxy</PackageId>
|
||||
<Version>0.1.55</Version>
|
||||
<Version>0.1.68</Version>
|
||||
<Authors>paloukari</Authors>
|
||||
<Company>Microsoft</Company>
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ using Microsoft.Azure.IoT.TypeEdge.Attributes;
|
|||
using Microsoft.Azure.IoT.TypeEdge.Modules;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Twins;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Volumes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Azure.IoT.TypeEdge.Proxy
|
||||
|
@ -47,7 +48,8 @@ namespace Microsoft.Azure.IoT.TypeEdge.Proxy
|
|||
var genericDef = invocation.Method.ReturnType.GetGenericTypeDefinition();
|
||||
if (genericDef.IsAssignableFrom(typeof(Input<>))
|
||||
|| genericDef.IsAssignableFrom(typeof(Output<>))
|
||||
|| genericDef.IsAssignableFrom(typeof(ModuleTwin<>)))
|
||||
|| genericDef.IsAssignableFrom(typeof(ModuleTwin<>))
|
||||
|| genericDef.IsAssignableFrom(typeof(Volume<>)))
|
||||
{
|
||||
var value = Activator.CreateInstance(
|
||||
genericDef.MakeGenericType(invocation.Method.ReturnType.GenericTypeArguments),
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Microsoft.Azure.IoT.TypeEdge.Attributes
|
||||
{
|
||||
internal class InputAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Microsoft.Azure.IoT.TypeEdge.Attributes
|
||||
{
|
||||
internal class OutputAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
|
@ -73,7 +73,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.DovEnv
|
|||
foreach (var basePath in basePaths)
|
||||
{
|
||||
var testPath = string.Join("/", new string[] { basePath, path });
|
||||
Console.WriteLine($"DotEnv: checking for {testPath}");
|
||||
//Console.WriteLine($"DotEnv: checking for {testPath}");
|
||||
if (!File.Exists(testPath))
|
||||
continue;
|
||||
fileExists = true;
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Azure.IoT.TypeEdge
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static T1 CopyFrom<T1, T2>(this T1 obj, T2 otherObject)
|
||||
where T1 : class
|
||||
where T2 : class
|
||||
{
|
||||
PropertyInfo[] srcFields = otherObject.GetType().GetProperties(
|
||||
BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);
|
||||
|
||||
PropertyInfo[] destFields = obj.GetType().GetProperties(
|
||||
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty);
|
||||
|
||||
foreach (var property in srcFields)
|
||||
{
|
||||
var dest = destFields.FirstOrDefault(x => x.Name == property.Name);
|
||||
if (dest != null && dest.CanWrite)
|
||||
dest.SetValue(obj, property.GetValue(otherObject, null), null);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<PackageId>Microsoft.Azure.IoT.TypeEdge</PackageId>
|
||||
<Version>0.1.55</Version>
|
||||
<Version>0.1.68</Version>
|
||||
<Authors>paloukari</Authors>
|
||||
<Company>Microsoft</Company>
|
||||
<PackageOutputPath>../../TypeEdgeNuGets</PackageOutputPath>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
@ -16,6 +15,7 @@ using Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints;
|
|||
using Microsoft.Azure.IoT.TypeEdge.Modules.Enums;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Messages;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Twins;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Volumes;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
@ -24,11 +24,10 @@ using Newtonsoft.Json;
|
|||
|
||||
namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
||||
{
|
||||
public abstract class EdgeModule
|
||||
public abstract class EdgeModule : IDisposable
|
||||
{
|
||||
private readonly Dictionary<string, MethodCallback> _methodSubscriptions;
|
||||
private readonly Dictionary<string, SubscriptionCallback> _routeSubscriptions;
|
||||
|
||||
private readonly Dictionary<string, SubscriptionCallback> _twinSubscriptions;
|
||||
private string _connectionString;
|
||||
private ModuleClient _ioTHubModuleClient;
|
||||
|
@ -39,6 +38,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
_routeSubscriptions = new Dictionary<string, SubscriptionCallback>();
|
||||
_twinSubscriptions = new Dictionary<string, SubscriptionCallback>();
|
||||
_methodSubscriptions = new Dictionary<string, MethodCallback>();
|
||||
Volumes = new Dictionary<string, string>();
|
||||
|
||||
Routes = new List<string>();
|
||||
|
||||
|
@ -60,6 +60,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
|
||||
internal List<string> Routes { get; set; }
|
||||
|
||||
public Dictionary<string, string> Volumes { get; }
|
||||
|
||||
internal virtual Task<T> PublishTwinAsync<T>(string name, T twin)
|
||||
where T : IModuleTwin, new()
|
||||
|
@ -95,7 +96,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
_ioTHubModuleClient = ModuleClient.CreateFromConnectionString(_connectionString, _transportSettings);
|
||||
|
||||
await _ioTHubModuleClient.OpenAsync();
|
||||
Console.WriteLine($"{Name}:IoT Hub module client initialized.");
|
||||
//Console.WriteLine($"{Name}:IoT Hub module client initialized.");
|
||||
|
||||
// Register callback to be called when a message is received by the module
|
||||
foreach (var subscription in _routeSubscriptions)
|
||||
|
@ -103,7 +104,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
await _ioTHubModuleClient.SetInputMessageHandlerAsync(subscription.Key, MessageHandler,
|
||||
subscription.Value);
|
||||
|
||||
Console.WriteLine($"{Name}:MessageHandler set for {subscription.Key}");
|
||||
//Console.WriteLine($"{Name}:MessageHandler set for {subscription.Key}");
|
||||
}
|
||||
|
||||
// Register callback to be called when a twin update is received by the module
|
||||
|
@ -112,16 +113,16 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
foreach (var subscription in _methodSubscriptions)
|
||||
{
|
||||
await _ioTHubModuleClient.SetMethodHandlerAsync(subscription.Key, MethodCallback, subscription.Value);
|
||||
Console.WriteLine($"{Name}:MethodCallback set for{subscription.Key}");
|
||||
//Console.WriteLine($"{Name}:MethodCallback set for{subscription.Key}");
|
||||
}
|
||||
|
||||
Console.WriteLine($"{Name}:Running RunAsync..");
|
||||
//Console.WriteLine($"{Name}:Running RunAsync..");
|
||||
return await RunAsync();
|
||||
}
|
||||
|
||||
private Task<MethodResponse> MethodCallback(MethodRequest methodRequest, object userContext)
|
||||
{
|
||||
Console.WriteLine($"{Name}:MethodCallback called");
|
||||
//Console.WriteLine($"{Name}:MethodCallback called");
|
||||
if (!(userContext is MethodCallback callback))
|
||||
throw new InvalidOperationException($"{Name}:UserContext doesn't contain a valid SubscriptionCallback");
|
||||
|
||||
|
@ -140,6 +141,8 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"{Name}:ERROR:{ex}");
|
||||
|
||||
// Acknowlege the direct method call with a 400 error message
|
||||
var result = "{\"result\":\"" + ex.Message + "\"}";
|
||||
return Task.FromResult(new MethodResponse(Encoding.UTF8.GetBytes(result), 400));
|
||||
|
@ -148,7 +151,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
|
||||
internal CreationResult InternalConfigure(IConfigurationRoot configuration)
|
||||
{
|
||||
Console.WriteLine($"{Name}:InternalConfigure called");
|
||||
//Console.WriteLine($"{Name}:InternalConfigure called");
|
||||
|
||||
_connectionString = configuration.GetValue<string>($"{Constants.EdgeHubConnectionStringKey}");
|
||||
if (string.IsNullOrEmpty(_connectionString))
|
||||
|
@ -171,9 +174,9 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
internal async Task<PublishResult> PublishMessageAsync<T>(string outputName, T message)
|
||||
where T : IEdgeMessage
|
||||
{
|
||||
Console.WriteLine($"{Name}:PublishMessageAsync called");
|
||||
//Console.WriteLine($"{Name}:PublishMessageAsync called");
|
||||
var edgeMessage = new Message(message.GetBytes());
|
||||
|
||||
|
||||
|
||||
if (message.Properties != null)
|
||||
foreach (var prop in edgeMessage.Properties)
|
||||
|
@ -182,7 +185,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
await _ioTHubModuleClient.SendEventAsync(outputName, edgeMessage);
|
||||
|
||||
var messageString = Encoding.UTF8.GetString(message.GetBytes());
|
||||
Console.WriteLine($">>>>>>{Name}: message: Body: [{messageString}]");
|
||||
//Console.WriteLine($">>>>>>{Name}: message: Body: [{messageString}]");
|
||||
|
||||
return PublishResult.Ok;
|
||||
}
|
||||
|
@ -191,7 +194,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
Func<T, Task<MessageResult>> handler)
|
||||
where T : IEdgeMessage
|
||||
{
|
||||
Console.WriteLine($"{Name}:SubscribeRoute called");
|
||||
//Console.WriteLine($"{Name}:SubscribeRoute called");
|
||||
|
||||
if (outRoute != "$downstream")
|
||||
Routes.Add($"FROM {outRoute} INTO {inRoute}");
|
||||
|
@ -201,7 +204,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
|
||||
internal void SubscribeRoute(string outName, string outRoute, string inName, string inRoute)
|
||||
{
|
||||
Console.WriteLine($"{Name}:SubscribeRoute called");
|
||||
//Console.WriteLine($"{Name}:SubscribeRoute called");
|
||||
|
||||
if (outRoute != "$downstream")
|
||||
Routes.Add($"FROM {outRoute} INTO {inRoute}");
|
||||
|
@ -209,21 +212,21 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
|
||||
internal void SubscribeTwin<T>(string name, Func<T, Task<TwinResult>> handler) where T : IModuleTwin
|
||||
{
|
||||
Console.WriteLine($"{Name}:SubscribeTwin called");
|
||||
//Console.WriteLine($"{Name}:SubscribeTwin called");
|
||||
|
||||
_twinSubscriptions[name] = new SubscriptionCallback(name, handler, typeof(T));
|
||||
}
|
||||
|
||||
private async Task<MessageResponse> MessageHandler(Message message, object userContext)
|
||||
{
|
||||
Console.WriteLine($"{Name}:MessageHandler called");
|
||||
//Console.WriteLine($"{Name}:MessageHandler called");
|
||||
|
||||
if (!(userContext is SubscriptionCallback callback))
|
||||
throw new InvalidOperationException("UserContext doesn't contain a valid SubscriptionCallback");
|
||||
|
||||
var messageBytes = message.GetBytes();
|
||||
var messageString = Encoding.UTF8.GetString(messageBytes);
|
||||
Console.WriteLine($"<<<<<<{Name}:message: Body: [{messageString}]");
|
||||
//Console.WriteLine($"<<<<<<{Name}:message: Body: [{messageString}]");
|
||||
|
||||
if (!(Activator.CreateInstance(callback.Type) is IEdgeMessage input))
|
||||
{
|
||||
|
@ -241,13 +244,13 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
|
||||
private async Task PropertyHandler(TwinCollection desiredProperties, object userContext)
|
||||
{
|
||||
Console.WriteLine($"{Name}:PropertyHandler called");
|
||||
//Console.WriteLine($"{Name}:PropertyHandler called");
|
||||
|
||||
if (!(userContext is Dictionary<string, SubscriptionCallback> callbacks))
|
||||
throw new InvalidOperationException("UserContext doesn't contain a valid SubscriptionCallback");
|
||||
|
||||
Console.WriteLine($"{Name}:Desired property change:");
|
||||
Console.WriteLine(JsonConvert.SerializeObject(desiredProperties));
|
||||
//Console.WriteLine($"{Name}:Desired property change:");
|
||||
//Console.WriteLine(JsonConvert.SerializeObject(desiredProperties));
|
||||
|
||||
foreach (var callback in callbacks)
|
||||
if (desiredProperties.Contains($"___{callback.Key}"))
|
||||
|
@ -281,7 +284,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
var store = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
|
||||
store.Open(OpenFlags.ReadWrite);
|
||||
store.Add(new X509Certificate2(X509Certificate.CreateFromCertFile(certPath)));
|
||||
Console.WriteLine($"{Name}:Added Cert: " + certPath);
|
||||
//Console.WriteLine($"{Name}:Added Cert: " + certPath);
|
||||
store.Close();
|
||||
}
|
||||
|
||||
|
@ -299,7 +302,8 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
var genericDef = type.GetGenericTypeDefinition();
|
||||
if (genericDef == typeof(Input<>)
|
||||
|| genericDef == typeof(Output<>)
|
||||
|| genericDef == typeof(ModuleTwin<>))
|
||||
|| genericDef == typeof(ModuleTwin<>)
|
||||
|| genericDef == typeof(Volume<>))
|
||||
{
|
||||
if (!prop.CanWrite)
|
||||
throw new Exception($"{prop.Name} needs to be set dynamically, please define a setter.");
|
||||
|
@ -314,7 +318,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
|
||||
private void RegisterMethods()
|
||||
{
|
||||
Console.WriteLine($"{Name}:RegisterMethods called");
|
||||
//Console.WriteLine($"{Name}:RegisterMethods called");
|
||||
var interfaceType = GetType().GetProxyInterface();
|
||||
|
||||
if (interfaceType == null)
|
||||
|
@ -328,9 +332,90 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
|||
internal async Task ReportTwinAsync<T>(string name, T twin)
|
||||
where T : IModuleTwin
|
||||
{
|
||||
Console.WriteLine($"{Name}:ReportTwinAsync called");
|
||||
|
||||
//Console.WriteLine($"{Name}:ReportTwinAsync called");
|
||||
await _ioTHubModuleClient.UpdateReportedPropertiesAsync(twin.GetReportedTwin(name).Properties.Reported);
|
||||
}
|
||||
|
||||
internal void RegisterVolume(string volumeName)
|
||||
{
|
||||
var volumePath = volumeName.ToLower();
|
||||
|
||||
if (!Directory.Exists(volumePath))
|
||||
{
|
||||
var di = Directory.CreateDirectory(volumePath);
|
||||
}
|
||||
|
||||
Volumes[volumeName] = volumePath;
|
||||
}
|
||||
|
||||
internal T GetFileData<T>(string name, string index)
|
||||
where T : class, new()
|
||||
{
|
||||
try
|
||||
{
|
||||
var path = Path.Combine(Volumes[name], index);
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var bytes = File.ReadAllBytes(path);
|
||||
var result = JsonConvert.DeserializeObject<T>(Encoding.UTF8.GetString(bytes));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"{Name}:ERROR:{ex}");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
internal bool SetFileData<T>(string name, string index, T value)
|
||||
where T : class, new()
|
||||
{
|
||||
try
|
||||
{
|
||||
var path = Path.Combine(Volumes[name], index);
|
||||
var bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value));
|
||||
|
||||
File.WriteAllBytes(path, bytes);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"{Name}:ERROR:{ex}");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
internal bool DeleteFile(string name, string index)
|
||||
{
|
||||
try
|
||||
{
|
||||
var path = Path.Combine(Volumes[name], index);
|
||||
if (File.Exists(path))
|
||||
File.Delete(path);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"{Name}:ERROR:{ex}");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Volumes != null)
|
||||
foreach (var item in Volumes)
|
||||
{
|
||||
try
|
||||
{
|
||||
//todo:empty or not?
|
||||
//if (Directory.Exists(item.Value))
|
||||
// Directory.Delete(item.Value);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,15 +1,11 @@
|
|||
namespace Microsoft.Azure.IoT.TypeEdge.Modules
|
||||
{
|
||||
public abstract class Endpoint
|
||||
public abstract class Endpoint : TypeProperty
|
||||
{
|
||||
protected Endpoint(string name, EdgeModule module)
|
||||
:base(name, module)
|
||||
{
|
||||
Name = name;
|
||||
Module = module;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
public abstract string RouteName { get; }
|
||||
internal EdgeModule Module { get; set; }
|
||||
}
|
||||
}
|
|
@ -5,18 +5,47 @@ using Microsoft.Azure.IoT.TypeEdge.Modules.Messages;
|
|||
namespace Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints
|
||||
{
|
||||
public class Input<T> : Endpoint
|
||||
where T : IEdgeMessage
|
||||
where T : class, IEdgeMessage, new()
|
||||
{
|
||||
private Volumes.Volume<T> _volume;
|
||||
|
||||
public Input(string name, EdgeModule module) :
|
||||
base(name, module)
|
||||
{
|
||||
if (typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Reference<>))
|
||||
{
|
||||
_volume = new Volumes.Volume<T>(Name, Module);
|
||||
Module.RegisterVolume(name);
|
||||
}
|
||||
}
|
||||
|
||||
public override string RouteName => $"BrokeredEndpoint(\"/modules/{Module.Name}/inputs/{Name}\")";
|
||||
|
||||
public virtual void Subscribe(Endpoint output, Func<T, Task<MessageResult>> handler)
|
||||
{
|
||||
Module.SubscribeRoute(output.Name, output.RouteName, Name, RouteName, handler);
|
||||
var dereference = new Func<T, Task<MessageResult>>((t) =>
|
||||
{
|
||||
if (_volume != null)
|
||||
{
|
||||
//todo: find a typed way to do this
|
||||
var fileName = typeof(T).GetProperty("FileName").GetValue(t) as string;
|
||||
var referenceCount = (int)typeof(T).GetProperty("ReferenceCount").GetValue(t);
|
||||
var message = _volume.Read(fileName);
|
||||
|
||||
if (--referenceCount <= 0)
|
||||
_volume.Delete(fileName);
|
||||
|
||||
return handler(message);
|
||||
}
|
||||
else
|
||||
return handler(t);
|
||||
});
|
||||
|
||||
Module.SubscribeRoute(output.Name,
|
||||
output.RouteName,
|
||||
Name,
|
||||
RouteName,
|
||||
dereference);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,18 +5,33 @@ using Microsoft.Azure.IoT.TypeEdge.Modules.Messages;
|
|||
namespace Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints
|
||||
{
|
||||
public class Output<T> : Endpoint
|
||||
where T : IEdgeMessage
|
||||
where T : class, IEdgeMessage, new()
|
||||
{
|
||||
private Volumes.Volume<T> _volume;
|
||||
|
||||
public Output(string name, EdgeModule module) :
|
||||
base(name, module)
|
||||
{
|
||||
if (typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Reference<>))
|
||||
{
|
||||
_volume = new Volumes.Volume<T>(Name, Module);
|
||||
Module.RegisterVolume(name);
|
||||
}
|
||||
}
|
||||
|
||||
public override string RouteName => $"/messages/modules/{Module.Name}/outputs/{Name}";
|
||||
|
||||
|
||||
public async Task<PublishResult> PublishAsync(T message)
|
||||
{
|
||||
if (_volume != null)
|
||||
{
|
||||
string fileName;
|
||||
if (_volume.TryWrite(message, out fileName))
|
||||
{
|
||||
typeof(T).GetProperty("FileName").SetValue(message, fileName);
|
||||
typeof(T).GetProperty("Message").SetValue(message, null);
|
||||
}
|
||||
}
|
||||
return await Module.PublishMessageAsync(Name, message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints
|
||||
{
|
||||
public class Upstream<T> : Output<T>
|
||||
where T : IEdgeMessage
|
||||
where T : class, IEdgeMessage, new()
|
||||
|
||||
{
|
||||
public Upstream(EdgeModule module) :
|
||||
|
@ -14,7 +14,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints
|
|||
public override string RouteName => "$upstream";
|
||||
|
||||
public void Subscribe<TO>(Output<TO> output)
|
||||
where TO : IEdgeMessage
|
||||
where TO : class, IEdgeMessage, new()
|
||||
{
|
||||
Module.SubscribeRoute(output.Name, output.RouteName, Name, RouteName);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ using System.Text;
|
|||
|
||||
namespace Microsoft.Azure.IoT.TypeEdge.Modules.Messages
|
||||
{
|
||||
public class DiagnosticsMessage : IEdgeMessage
|
||||
public class DiagnosticsMessage : EdgeMessage
|
||||
{
|
||||
private string[] _records;
|
||||
|
||||
|
@ -12,17 +12,5 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules.Messages
|
|||
{
|
||||
_records = data;
|
||||
}
|
||||
|
||||
public IDictionary<string, string> Properties { get; set; }
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(string.Join(Environment.NewLine, _records));
|
||||
}
|
||||
|
||||
public void SetBytes(byte[] bytes)
|
||||
{
|
||||
_records = Encoding.UTF8.GetString(bytes).Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,22 @@
|
|||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.Azure.IoT.TypeEdge;
|
||||
|
||||
namespace Microsoft.Azure.IoT.TypeEdge.Modules.Messages
|
||||
{
|
||||
public interface IEdgeMessage
|
||||
public abstract class EdgeMessage : IEdgeMessage
|
||||
{
|
||||
IDictionary<string, string> Properties { get; set; }
|
||||
byte[] GetBytes();
|
||||
void SetBytes(byte[] bytes);
|
||||
public IDictionary<string, string> Properties { get; set; }
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(this));
|
||||
}
|
||||
public void SetBytes(byte[] bytes)
|
||||
{
|
||||
var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(bytes), GetType());
|
||||
|
||||
this.CopyFrom(obj);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Azure.IoT.TypeEdge.Modules.Messages
|
||||
{
|
||||
public interface IEdgeMessage
|
||||
{
|
||||
IDictionary<string, string> Properties { get; set; }
|
||||
byte[] GetBytes();
|
||||
void SetBytes(byte[] bytes);
|
||||
}
|
||||
}
|
|
@ -3,25 +3,8 @@ using System.Text;
|
|||
|
||||
namespace Microsoft.Azure.IoT.TypeEdge.Modules.Messages
|
||||
{
|
||||
public class JsonMessage : IEdgeMessage
|
||||
public class JsonMessage : EdgeMessage
|
||||
{
|
||||
private string _jsonData;
|
||||
|
||||
public JsonMessage(string data)
|
||||
{
|
||||
_jsonData = data;
|
||||
}
|
||||
|
||||
public IDictionary<string, string> Properties { get; set; }
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(_jsonData);
|
||||
}
|
||||
|
||||
public void SetBytes(byte[] bytes)
|
||||
{
|
||||
_jsonData = Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
public string JsonData { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Azure.IoT.TypeEdge.Modules.Messages
|
||||
{
|
||||
public class Reference<T> : EdgeMessage
|
||||
where T : IEdgeMessage
|
||||
{
|
||||
public Reference()
|
||||
{
|
||||
ReferenceCount = 1;
|
||||
}
|
||||
|
||||
public int ReferenceCount { get; set; }
|
||||
|
||||
public string FileName { get; set; }
|
||||
|
||||
public T Message { get; set; }
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ using Microsoft.Azure.IoT.TypeEdge.Attributes;
|
|||
using Microsoft.Azure.IoT.TypeEdge.Modules;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Twins;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Volumes;
|
||||
|
||||
namespace Microsoft.Azure.IoT.TypeEdge.Proxy
|
||||
{
|
||||
|
@ -34,8 +35,10 @@ namespace Microsoft.Azure.IoT.TypeEdge.Proxy
|
|||
if (!invocation.Method.ReturnType.IsGenericType)
|
||||
return;
|
||||
var genericDef = invocation.Method.ReturnType.GetGenericTypeDefinition();
|
||||
if (!genericDef.IsAssignableFrom(typeof(Input<>)) && !genericDef.IsAssignableFrom(typeof(Output<>)) &&
|
||||
!genericDef.IsAssignableFrom(typeof(ModuleTwin<>)))
|
||||
if (!genericDef.IsAssignableFrom(typeof(Input<>)) &&
|
||||
!genericDef.IsAssignableFrom(typeof(Output<>)) &&
|
||||
!genericDef.IsAssignableFrom(typeof(ModuleTwin<>)) &&
|
||||
!genericDef.IsAssignableFrom(typeof(Volume<>)))
|
||||
return;
|
||||
var value = Activator.CreateInstance(
|
||||
genericDef.MakeGenericType(invocation.Method.ReturnType.GenericTypeArguments),
|
||||
|
|
|
@ -75,12 +75,6 @@ namespace Microsoft.Azure.IoT.TypeEdge
|
|||
break;
|
||||
}
|
||||
|
||||
var directory = Path.GetDirectoryName(fileName);
|
||||
foreach (var file in Directory.EnumerateFiles(directory))
|
||||
{
|
||||
Console.WriteLine(file);
|
||||
}
|
||||
|
||||
Console.WriteLine($"{moduleName}:{fileName} does not exist. Retrying in 1 sec.");
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
|
|
@ -5,17 +5,18 @@ using Microsoft.Azure.IoT.TypeEdge.Modules.Enums;
|
|||
|
||||
namespace Microsoft.Azure.IoT.TypeEdge.Twins
|
||||
{
|
||||
public class ModuleTwin<T>
|
||||
public class ModuleTwin<T> : TypeProperty
|
||||
where T : TypeModuleTwin, new()
|
||||
{
|
||||
public ModuleTwin(string name, EdgeModule module)
|
||||
{
|
||||
Module = module;
|
||||
Name = name;
|
||||
}
|
||||
private object _twinLock = new object();
|
||||
T _lastTwin;
|
||||
|
||||
private string Name { get; }
|
||||
private EdgeModule Module { get; }
|
||||
public T LastKnownTwin { get { lock (_twinLock) return _lastTwin; } set { lock (_twinLock) _lastTwin = value; } }
|
||||
|
||||
public ModuleTwin(string name, EdgeModule module)
|
||||
: base(name, module)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Subscribe(Func<T, Task<TwinResult>> handler)
|
||||
{
|
||||
|
@ -25,16 +26,21 @@ namespace Microsoft.Azure.IoT.TypeEdge.Twins
|
|||
public async Task ReportAsync(T twin)
|
||||
{
|
||||
await Module.ReportTwinAsync(Name, twin);
|
||||
LastKnownTwin = twin;
|
||||
}
|
||||
|
||||
public Task<T> PublishAsync(T twin)
|
||||
public async Task<T> PublishAsync(T twin)
|
||||
{
|
||||
return Module.PublishTwinAsync(Name, twin);
|
||||
var t = await Module.PublishTwinAsync(Name, twin);
|
||||
LastKnownTwin = t;
|
||||
return t;
|
||||
}
|
||||
|
||||
public async Task<T> GetAsync()
|
||||
{
|
||||
return await Module.GetTwinAsync<T>(Name);
|
||||
var t = await Module.GetTwinAsync<T>(Name);
|
||||
LastKnownTwin = t;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,7 +8,10 @@ namespace Microsoft.Azure.IoT.TypeEdge.Twins
|
|||
{
|
||||
public abstract class TypeModuleTwin : IModuleTwin
|
||||
{
|
||||
public Twin LastKnownTwin { get; set; }
|
||||
private object _twinLock = new object();
|
||||
Twin _lastTwin;
|
||||
|
||||
public Twin LastKnownTwin { get { lock (_twinLock) return _lastTwin; } set { lock (_twinLock) _lastTwin = value; } }
|
||||
|
||||
public void SetTwin(string name, Twin twin)
|
||||
{
|
||||
|
@ -18,7 +21,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Twins
|
|||
var settings = new JsonSerializerSettings
|
||||
{
|
||||
ContractResolver = resolver,
|
||||
Converters = new JsonConverter[] {new JsonFlatteningConverter(resolver)}
|
||||
Converters = new JsonConverter[] { new JsonFlatteningConverter(resolver) }
|
||||
};
|
||||
|
||||
JsonConvert.PopulateObject(twin.Properties.Desired.ToJson(), this, settings);
|
||||
|
@ -41,7 +44,15 @@ namespace Microsoft.Azure.IoT.TypeEdge.Twins
|
|||
//todo: use the json serializer here
|
||||
var result = LastKnownTwin;
|
||||
TwinCollection properties;
|
||||
if (result == null) result = desired ? new Twin {Properties = new TwinProperties {Desired = new TwinCollection()}} : new Twin {Properties = new TwinProperties {Reported = new TwinCollection()}};
|
||||
if (result == null) result = desired ?
|
||||
new Twin
|
||||
{
|
||||
Properties = new TwinProperties { Desired = new TwinCollection() }
|
||||
} :
|
||||
new Twin
|
||||
{
|
||||
Properties = new TwinProperties { Reported = new TwinCollection() }
|
||||
};
|
||||
|
||||
if (desired)
|
||||
properties = result.Properties.Desired;
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
using Microsoft.Azure.IoT.TypeEdge.Modules;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Azure.IoT.TypeEdge
|
||||
{
|
||||
public abstract class TypeProperty
|
||||
{
|
||||
protected TypeProperty(string name, EdgeModule module)
|
||||
{
|
||||
Name = name;
|
||||
Module = module;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
internal EdgeModule Module { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
using Microsoft.Azure.IoT.TypeEdge.Modules;
|
||||
using Microsoft.Azure.IoT.TypeEdge.Modules.Messages;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Azure.IoT.TypeEdge.Volumes
|
||||
{
|
||||
public class Volume<T> : TypeProperty
|
||||
where T : class, IEdgeMessage, new()
|
||||
{
|
||||
public Volume(string name, EdgeModule module)
|
||||
: base(name, module)
|
||||
{
|
||||
Module.RegisterVolume(Name);
|
||||
}
|
||||
|
||||
public bool TryWrite(T data, out string fileName)
|
||||
{
|
||||
var fn = $@"{DateTime.Now.Ticks}";
|
||||
if (Module.SetFileData(Name, fn, data))
|
||||
{
|
||||
fileName = fn;
|
||||
return true;
|
||||
}
|
||||
fileName = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public T Read(string fileName)
|
||||
{
|
||||
return Module.GetFileData<T>(Name, fileName);
|
||||
}
|
||||
|
||||
public bool Delete(string fileName)
|
||||
{
|
||||
return Module.DeleteFile(Name, fileName);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -86,7 +86,7 @@ If your modules have system dependencies and you want to debug inside the contai
|
|||
|
||||
Alternatively, you can run your application inside the containers in command line:
|
||||
|
||||
docker-compose -f docker-compose.yml -f docker-compose.override.yml -f docker-compose.vs.debug.yml up
|
||||
docker-compose -f docker-compose.yml -f docker-compose.override.yml up
|
||||
|
||||
> Note: To build the docker containers, temporarily you need to [add the private NuGet feed](#feed) first.
|
||||
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
<add key="typeedge-feed" value="https://msblox-03.pkgs.visualstudio.com/_packaging/typeedge-feed/nuget/v3/index.json" />
|
||||
</packageSources>
|
||||
<packageSourceCredentials>
|
||||
|
||||
<typeedge-feed>
|
||||
<add key="Username" value="spyrosg" />
|
||||
<add key="ClearTextPassword" value="123asd!@#" />
|
||||
</typeedge-feed>
|
||||
</packageSourceCredentials>
|
||||
</configuration>
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.68" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.68" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -13,5 +13,6 @@
|
|||
</packageManagement>
|
||||
<packageSources>
|
||||
<add key="RocksDB ARM" value="https://www.myget.org/F/rocksdb-native-arm/api/v3/index.json" />
|
||||
<add key="SDK" value="https://www.myget.org/F/aziot-device-sdk/api/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
|
@ -15,7 +15,7 @@
|
|||
<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.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Host" Version="0.1.68" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.68" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.68" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Host" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Host" Version="0.1.68" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.68" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.68" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.68" />
|
||||
<PackageReference Include="Python.Runtime" Version="2.4.64" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
</packageManagement>
|
||||
<packageSources>
|
||||
<add key="RocksDB ARM" value="https://www.myget.org/F/rocksdb-native-arm/api/v3/index.json" />
|
||||
<add key="SDK" value="https://www.myget.org/F/aziot-device-sdk/api/v3/index.json" />
|
||||
</packageSources>
|
||||
|
||||
</configuration>
|
|
@ -18,7 +18,7 @@
|
|||
<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.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Host" Version="0.1.68" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.68" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.68" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.68" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.68" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
@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/typeedge-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/typeedge-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..
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Host" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Host" Version="0.1.68" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge" Version="0.1.68" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.55" />
|
||||
<PackageReference Include="Microsoft.Azure.IoT.TypeEdge.Proxy" Version="0.1.68" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
Загрузка…
Ссылка в новой задаче