diff --git a/Example/Modules/AnomalyDetection/AnomalyDetection.cs b/Example/Modules/AnomalyDetection/AnomalyDetection.cs new file mode 100644 index 0000000..14e29c8 --- /dev/null +++ b/Example/Modules/AnomalyDetection/AnomalyDetection.cs @@ -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 { get; set; } + public Input> Samples { get; set; } + public Output 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; + }); + } + } +} diff --git a/Example/Modules/AnomalyDetection/AnomalyDetection.csproj b/Example/Modules/AnomalyDetection/AnomalyDetection.csproj new file mode 100644 index 0000000..7c35a2c --- /dev/null +++ b/Example/Modules/AnomalyDetection/AnomalyDetection.csproj @@ -0,0 +1,26 @@ + + + netcoreapp2.1 + + latest + Exe + Debug;Release;TemplateDevelopment + + + + + + TRACE;DEBUG + + + + + + + + + + + + + diff --git a/Example/Modules/AnomalyDetection/Dockerfile b/Example/Modules/AnomalyDetection/Dockerfile new file mode 100644 index 0000000..527ef92 --- /dev/null +++ b/Example/Modules/AnomalyDetection/Dockerfile @@ -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"] + \ No newline at end of file diff --git a/Example/Modules/NormalizeTemperatureModule/Program.cs b/Example/Modules/AnomalyDetection/Program.cs similarity index 100% rename from Example/Modules/NormalizeTemperatureModule/Program.cs rename to Example/Modules/AnomalyDetection/Program.cs diff --git a/Example/Modules/DataSampling/DataSampling.cs b/Example/Modules/DataSampling/DataSampling.cs new file mode 100644 index 0000000..cbe7409 --- /dev/null +++ b/Example/Modules/DataSampling/DataSampling.cs @@ -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 _sample; + + public Input Temperature { get; set; } + public Output> Samples { get; set; } + + public DataSampling(IPreprocessor proxy) + { + _sample = new List(); + Temperature.Subscribe(proxy.Training, async signal => + { + _sample.Add(signal); + if (_sample.Count > 999) + { + await Samples.PublishAsync(new Reference() + { + Message = new Sample() { Data = _sample.ToArray() } + }); + _sample.Clear(); + } + return MessageResult.Ok; + }); + + } + } +} diff --git a/Example/Modules/DataSampling/DataSampling.csproj b/Example/Modules/DataSampling/DataSampling.csproj new file mode 100644 index 0000000..a5e5ac6 --- /dev/null +++ b/Example/Modules/DataSampling/DataSampling.csproj @@ -0,0 +1,26 @@ + + + + netcoreapp2.1 + + latest + Exe + Debug;Release;TemplateDevelopment + + + + + TRACE;DEBUG + + + + + + + + + + + + + diff --git a/Example/Modules/DataSampling/Dockerfile b/Example/Modules/DataSampling/Dockerfile new file mode 100644 index 0000000..9b817e6 --- /dev/null +++ b/Example/Modules/DataSampling/Dockerfile @@ -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"] + \ No newline at end of file diff --git a/Example/Modules/TemperatureModule/Program.cs b/Example/Modules/DataSampling/Program.cs similarity index 100% rename from Example/Modules/TemperatureModule/Program.cs rename to Example/Modules/DataSampling/Program.cs diff --git a/Example/Modules/NormalizeTemperatureModule/Dockerfile b/Example/Modules/NormalizeTemperatureModule/Dockerfile deleted file mode 100644 index 67b1019..0000000 --- a/Example/Modules/NormalizeTemperatureModule/Dockerfile +++ /dev/null @@ -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"] - \ No newline at end of file diff --git a/Example/Modules/NormalizeTemperatureModule/NormalizeTemperatureModule.cs b/Example/Modules/NormalizeTemperatureModule/NormalizeTemperatureModule.cs deleted file mode 100644 index 1660911..0000000 --- a/Example/Modules/NormalizeTemperatureModule/NormalizeTemperatureModule.cs +++ /dev/null @@ -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 Temperature { get; set; } - public Output NormalizedTemperature { get; set; } - public ModuleTwin Twin { get; set; } - - public override async Task RunAsync() - { - var twin = await Twin.GetAsync(); - _scale = twin.Scale; - - return ExecutionResult.Ok; - } - } -} \ No newline at end of file diff --git a/Example/Modules/Preprocessor/Dockerfile b/Example/Modules/Preprocessor/Dockerfile new file mode 100644 index 0000000..ecc6ea7 --- /dev/null +++ b/Example/Modules/Preprocessor/Dockerfile @@ -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"] + \ No newline at end of file diff --git a/Example/Modules/Preprocessor/Preprocessor.cs b/Example/Modules/Preprocessor/Preprocessor.cs new file mode 100644 index 0000000..b139435 --- /dev/null +++ b/Example/Modules/Preprocessor/Preprocessor.cs @@ -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 { get; set; } + public Output Training { get; set; } + public Output Detection { get; set; } + public ModuleTwin 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[] { + Training.PublishAsync(signal), + Detection.PublishAsync(signal) + }; + await Task.WhenAll(results); + break; + default: + break; + } + } + + public override async Task RunAsync() + { + await Twin.GetAsync(); + return ExecutionResult.Ok; + } + } +} \ No newline at end of file diff --git a/Example/Modules/NormalizeTemperatureModule/NormalizeTemperatureModule.csproj b/Example/Modules/Preprocessor/Preprocessor.csproj similarity index 90% rename from Example/Modules/NormalizeTemperatureModule/NormalizeTemperatureModule.csproj rename to Example/Modules/Preprocessor/Preprocessor.csproj index 8ade4fb..9baa9b8 100644 --- a/Example/Modules/NormalizeTemperatureModule/NormalizeTemperatureModule.csproj +++ b/Example/Modules/Preprocessor/Preprocessor.csproj @@ -13,7 +13,7 @@ - + diff --git a/Example/Modules/Preprocessor/Program.cs b/Example/Modules/Preprocessor/Program.cs new file mode 100644 index 0000000..a594fe6 --- /dev/null +++ b/Example/Modules/Preprocessor/Program.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/Example/Modules/TemperatureModule/Dockerfile b/Example/Modules/TemperatureModule/Dockerfile deleted file mode 100644 index f92e97a..0000000 --- a/Example/Modules/TemperatureModule/Dockerfile +++ /dev/null @@ -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"] diff --git a/Example/Modules/TemperatureSensor/Dockerfile b/Example/Modules/TemperatureSensor/Dockerfile new file mode 100644 index 0000000..f8bbea0 --- /dev/null +++ b/Example/Modules/TemperatureSensor/Dockerfile @@ -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"] diff --git a/Example/Modules/TemperatureSensor/Program.cs b/Example/Modules/TemperatureSensor/Program.cs new file mode 100644 index 0000000..a594fe6 --- /dev/null +++ b/Example/Modules/TemperatureSensor/Program.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/Example/Modules/TemperatureModule/TemperatureModule.cs b/Example/Modules/TemperatureSensor/TemperatureSensor.cs similarity index 53% rename from Example/Modules/TemperatureModule/TemperatureModule.cs rename to Example/Modules/TemperatureSensor/TemperatureSensor.cs index e1cbf80..6f90472 100644 --- a/Example/Modules/TemperatureModule/TemperatureModule.cs +++ b/Example/Modules/TemperatureSensor/TemperatureSensor.cs @@ -12,9 +12,9 @@ using ThermostatApplication.Twins; namespace Modules { - public class TemperatureModule : EdgeModule, ITemperatureModule + public class TemperatureSensor : EdgeModule, ITemperatureSensor { - public Output Temperature { get; set; } + public Output Temperature { get; set; } public ModuleTwin Twin { get; set; } public bool ResetSensor(int sensitivity) @@ -25,16 +25,32 @@ namespace Modules public override async Task 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(); } } diff --git a/Example/Modules/TemperatureModule/TemperatureModule.csproj b/Example/Modules/TemperatureSensor/TemperatureSensor.csproj similarity index 90% rename from Example/Modules/TemperatureModule/TemperatureModule.csproj rename to Example/Modules/TemperatureSensor/TemperatureSensor.csproj index 8ade4fb..9baa9b8 100644 --- a/Example/Modules/TemperatureModule/TemperatureModule.csproj +++ b/Example/Modules/TemperatureSensor/TemperatureSensor.csproj @@ -13,7 +13,7 @@ - + diff --git a/Example/Thermostat.Emulator/Dockerfile b/Example/Thermostat.Emulator/Dockerfile index abbfdda..ccf1f44 100644 --- a/Example/Thermostat.Emulator/Dockerfile +++ b/Example/Thermostat.Emulator/Dockerfile @@ -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 diff --git a/Example/Thermostat.Emulator/Program.cs b/Example/Thermostat.Emulator/Program.cs index e96f55d..6eb6e18 100644 --- a/Example/Thermostat.Emulator/Program.cs +++ b/Example/Thermostat.Emulator/Program.cs @@ -21,10 +21,12 @@ namespace ThermostatApplication var host = new TypeEdgeHost(configuration); - host.RegisterModule(); - host.RegisterModule(); + host.RegisterModule(); + host.RegisterModule(); + host.RegisterModule(); + host.RegisterModule(); - host.Upstream.Subscribe(host.GetProxy().NormalizedTemperature); + host.Upstream.Subscribe(host.GetProxy().Detection); host.Build(); diff --git a/Example/Thermostat.Emulator/Thermostat.Emulator.csproj b/Example/Thermostat.Emulator/Thermostat.Emulator.csproj index bafc3ca..4346b5f 100644 --- a/Example/Thermostat.Emulator/Thermostat.Emulator.csproj +++ b/Example/Thermostat.Emulator/Thermostat.Emulator.csproj @@ -18,15 +18,17 @@ - + - - + + + + diff --git a/Example/Thermostat.Emulator/appsettings_thermostat.json b/Example/Thermostat.Emulator/appsettings_thermostat.json index 133b362..80d1406 100644 --- a/Example/Thermostat.Emulator/appsettings_thermostat.json +++ b/Example/Thermostat.Emulator/appsettings_thermostat.json @@ -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" } } \ No newline at end of file diff --git a/Example/Thermostat.ServiceApp/Program.cs b/Example/Thermostat.ServiceApp/Program.cs index d3ac6d3..f1e0685 100644 --- a/Example/Thermostat.ServiceApp/Program.cs +++ b/Example/Thermostat.ServiceApp/Program.cs @@ -11,9 +11,29 @@ namespace Thermostat.ServiceApp { private static async Task Main(string[] args) { - Console.WriteLine("Press 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(); + var normalizer = ProxyFactory.GetModuleProxy(); var twin = await normalizer.Twin.GetAsync(); twin.Scale = TemperatureScale.Celsius; + twin.RoutingMode = routing; await normalizer.Twin.PublishAsync(twin); - var result = ProxyFactory.GetModuleProxy().ResetSensor(10); + //var result = ProxyFactory.GetModuleProxy().ResetSensor(10); Console.WriteLine("Press to exit.."); Console.ReadLine(); diff --git a/Example/Thermostat.ServiceApp/Thermostat.ServiceApp.csproj b/Example/Thermostat.ServiceApp/Thermostat.ServiceApp.csproj index c4a121c..12b0c28 100644 --- a/Example/Thermostat.ServiceApp/Thermostat.ServiceApp.csproj +++ b/Example/Thermostat.ServiceApp/Thermostat.ServiceApp.csproj @@ -12,7 +12,7 @@ - + diff --git a/Example/Thermostat.ServiceApp/appsettings_thermostat.json b/Example/Thermostat.ServiceApp/appsettings_thermostat.json index 7a57245..eef4da7 100644 --- a/Example/Thermostat.ServiceApp/appsettings_thermostat.json +++ b/Example/Thermostat.ServiceApp/appsettings_thermostat.json @@ -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=" } \ No newline at end of file diff --git a/Example/Thermostat.Shared/Messages/Anomaly.cs b/Example/Thermostat.Shared/Messages/Anomaly.cs new file mode 100644 index 0000000..0962da4 --- /dev/null +++ b/Example/Thermostat.Shared/Messages/Anomaly.cs @@ -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; } + } +} diff --git a/Example/Thermostat.Shared/Messages/Sample.cs b/Example/Thermostat.Shared/Messages/Sample.cs new file mode 100644 index 0000000..3532c3f --- /dev/null +++ b/Example/Thermostat.Shared/Messages/Sample.cs @@ -0,0 +1,9 @@ +using Microsoft.Azure.IoT.TypeEdge.Modules.Messages; + +namespace ThermostatApplication.Messages +{ + public class Sample : EdgeMessage + { + public Temperature[] Data { get; set; } + } +} diff --git a/Example/Thermostat.Shared/Messages/Temperature.cs b/Example/Thermostat.Shared/Messages/Temperature.cs new file mode 100644 index 0000000..27fda84 --- /dev/null +++ b/Example/Thermostat.Shared/Messages/Temperature.cs @@ -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; } + } +} \ No newline at end of file diff --git a/Example/Thermostat.Shared/Messages/TemperatureModuleInput.cs b/Example/Thermostat.Shared/Messages/TemperatureModuleInput.cs deleted file mode 100644 index 083d62e..0000000 --- a/Example/Thermostat.Shared/Messages/TemperatureModuleInput.cs +++ /dev/null @@ -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 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)); - Properties = obj.Properties; - MyData = obj.MyData; - } - } -} \ No newline at end of file diff --git a/Example/Thermostat.Shared/Messages/TemperatureModuleOutput.cs b/Example/Thermostat.Shared/Messages/TemperatureModuleOutput.cs deleted file mode 100644 index cea3da7..0000000 --- a/Example/Thermostat.Shared/Messages/TemperatureModuleOutput.cs +++ /dev/null @@ -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 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)); - Properties = obj.Properties; - Scale = obj.Scale; - Temperature = obj.Temperature; - } - } -} \ No newline at end of file diff --git a/Example/Thermostat.Shared/Modules/IAnomalyDetection.cs b/Example/Thermostat.Shared/Modules/IAnomalyDetection.cs new file mode 100644 index 0000000..88f44d9 --- /dev/null +++ b/Example/Thermostat.Shared/Modules/IAnomalyDetection.cs @@ -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 { get; set; } + Input> Samples { get; set; } + + Output Anomaly { get; set; } + } +} \ No newline at end of file diff --git a/Example/Thermostat.Shared/Modules/IDataSampling.cs b/Example/Thermostat.Shared/Modules/IDataSampling.cs new file mode 100644 index 0000000..1fe7e86 --- /dev/null +++ b/Example/Thermostat.Shared/Modules/IDataSampling.cs @@ -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 { get; set; } + Output> Samples { get; set; } + } +} \ No newline at end of file diff --git a/Example/Thermostat.Shared/Modules/INormalizeTemperatureModule.cs b/Example/Thermostat.Shared/Modules/IPreprocessor.cs similarity index 53% rename from Example/Thermostat.Shared/Modules/INormalizeTemperatureModule.cs rename to Example/Thermostat.Shared/Modules/IPreprocessor.cs index 2ec3f89..cb76d07 100644 --- a/Example/Thermostat.Shared/Modules/INormalizeTemperatureModule.cs +++ b/Example/Thermostat.Shared/Modules/IPreprocessor.cs @@ -7,10 +7,13 @@ using ThermostatApplication.Twins; namespace ThermostatApplication.Modules { [TypeModule] - public interface INormalizeTemperatureModule + public interface IPreprocessor { - Output NormalizedTemperature { get; set; } + Input Temperature { get; set; } - ModuleTwin Twin { get; set; } + Output Training { get; set; } + Output Detection { get; set; } + + ModuleTwin Twin { get; set; } } } \ No newline at end of file diff --git a/Example/Thermostat.Shared/Modules/ITemperatureModule.cs b/Example/Thermostat.Shared/Modules/ITemperatureSensor.cs similarity index 78% rename from Example/Thermostat.Shared/Modules/ITemperatureModule.cs rename to Example/Thermostat.Shared/Modules/ITemperatureSensor.cs index b5adfdc..88462d8 100644 --- a/Example/Thermostat.Shared/Modules/ITemperatureModule.cs +++ b/Example/Thermostat.Shared/Modules/ITemperatureSensor.cs @@ -7,9 +7,9 @@ using ThermostatApplication.Twins; namespace ThermostatApplication.Modules { [TypeModule] - public interface ITemperatureModule + public interface ITemperatureSensor { - Output Temperature { get; set; } + Output Temperature { get; set; } ModuleTwin Twin { get; set; } bool ResetSensor(int sensitivity); diff --git a/Example/Thermostat.Shared/Thermostat.Shared.csproj b/Example/Thermostat.Shared/Thermostat.Shared.csproj index 5978142..e8fa1b3 100644 --- a/Example/Thermostat.Shared/Thermostat.Shared.csproj +++ b/Example/Thermostat.Shared/Thermostat.Shared.csproj @@ -10,7 +10,7 @@ - + diff --git a/Example/Thermostat.Shared/Twins/NormalizerTwin.cs b/Example/Thermostat.Shared/Twins/NormalizerTwin.cs deleted file mode 100644 index 4de9d62..0000000 --- a/Example/Thermostat.Shared/Twins/NormalizerTwin.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Microsoft.Azure.IoT.TypeEdge.Twins; - -namespace ThermostatApplication.Twins -{ - public class NormalizerTwin : TypeModuleTwin - { - public TemperatureScale Scale { get; set; } - } -} \ No newline at end of file diff --git a/Example/Thermostat.Shared/Twins/PreprocessorTwin.cs b/Example/Thermostat.Shared/Twins/PreprocessorTwin.cs new file mode 100644 index 0000000..b21844f --- /dev/null +++ b/Example/Thermostat.Shared/Twins/PreprocessorTwin.cs @@ -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; } + } +} \ No newline at end of file diff --git a/Example/Thermostat.Shared/Volumes/ISharedVolume.cs b/Example/Thermostat.Shared/Volumes/ISharedVolume.cs new file mode 100644 index 0000000..ca62da9 --- /dev/null +++ b/Example/Thermostat.Shared/Volumes/ISharedVolume.cs @@ -0,0 +1,10 @@ +using Microsoft.Azure.IoT.TypeEdge.Volumes; +using ThermostatApplication.Messages; + +namespace ThermostatApplication.Modules +{ + public interface ISharedVolume + { + Volume Samples { get; set; } + } +} \ No newline at end of file diff --git a/Example/ThermostatApplication.sln b/Example/ThermostatApplication.sln index c48cb8b..2d7dad7 100644 --- a/Example/ThermostatApplication.sln +++ b/Example/ThermostatApplication.sln @@ -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} diff --git a/Microsoft.Azure.IoT.TypeEdge-WithExample.sln b/Microsoft.Azure.IoT.TypeEdge-WithExample.sln index d8df084..9a8e78f 100644 --- a/Microsoft.Azure.IoT.TypeEdge-WithExample.sln +++ b/Microsoft.Azure.IoT.TypeEdge-WithExample.sln @@ -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} diff --git a/Microsoft.Azure.IoT.TypeEdge.Host/.nuspec b/Microsoft.Azure.IoT.TypeEdge.Host/.nuspec index 9935d70..1f56fdd 100644 --- a/Microsoft.Azure.IoT.TypeEdge.Host/.nuspec +++ b/Microsoft.Azure.IoT.TypeEdge.Host/.nuspec @@ -2,14 +2,14 @@ Microsoft.Azure.IoT.TypeEdge.Host - 0.1.55 + 0.1.68 paloukari paloukari false Package Description - + diff --git a/Microsoft.Azure.IoT.TypeEdge.Host/Dockerfile b/Microsoft.Azure.IoT.TypeEdge.Host/Dockerfile index ac6a110..5084305 100644 --- a/Microsoft.Azure.IoT.TypeEdge.Host/Dockerfile +++ b/Microsoft.Azure.IoT.TypeEdge.Host/Dockerfile @@ -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 diff --git a/Microsoft.Azure.IoT.TypeEdge.Host/TypeEdgeHost.cs b/Microsoft.Azure.IoT.TypeEdge.Host/TypeEdgeHost.cs index 1bfa998..d945952 100644 --- a/Microsoft.Azure.IoT.TypeEdge.Host/TypeEdgeHost.cs +++ b/Microsoft.Azure.IoT.TypeEdge.Host/TypeEdgeHost.cs @@ -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} }}" } })); diff --git a/Microsoft.Azure.IoT.TypeEdge.Proxy/Microsoft.Azure.IoT.TypeEdge.Proxy.csproj b/Microsoft.Azure.IoT.TypeEdge.Proxy/Microsoft.Azure.IoT.TypeEdge.Proxy.csproj index bee17a1..f4a1d50 100644 --- a/Microsoft.Azure.IoT.TypeEdge.Proxy/Microsoft.Azure.IoT.TypeEdge.Proxy.csproj +++ b/Microsoft.Azure.IoT.TypeEdge.Proxy/Microsoft.Azure.IoT.TypeEdge.Proxy.csproj @@ -3,7 +3,7 @@ $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb Microsoft.Azure.IoT.TypeEdge.Proxy - 0.1.55 + 0.1.68 paloukari Microsoft diff --git a/Microsoft.Azure.IoT.TypeEdge.Proxy/Proxy.cs b/Microsoft.Azure.IoT.TypeEdge.Proxy/Proxy.cs index ed05981..f969108 100644 --- a/Microsoft.Azure.IoT.TypeEdge.Proxy/Proxy.cs +++ b/Microsoft.Azure.IoT.TypeEdge.Proxy/Proxy.cs @@ -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), diff --git a/Microsoft.Azure.IoT.TypeEdge/Attributes/InputAttribute.cs b/Microsoft.Azure.IoT.TypeEdge/Attributes/InputAttribute.cs deleted file mode 100644 index e356cc7..0000000 --- a/Microsoft.Azure.IoT.TypeEdge/Attributes/InputAttribute.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; - -namespace Microsoft.Azure.IoT.TypeEdge.Attributes -{ - internal class InputAttribute : Attribute - { - } -} \ No newline at end of file diff --git a/Microsoft.Azure.IoT.TypeEdge/Attributes/OutputAttribute.cs b/Microsoft.Azure.IoT.TypeEdge/Attributes/OutputAttribute.cs deleted file mode 100644 index 8fc8bd4..0000000 --- a/Microsoft.Azure.IoT.TypeEdge/Attributes/OutputAttribute.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; - -namespace Microsoft.Azure.IoT.TypeEdge.Attributes -{ - internal class OutputAttribute : Attribute - { - } -} \ No newline at end of file diff --git a/Microsoft.Azure.IoT.TypeEdge/DovEnv/DotenvExtension.cs b/Microsoft.Azure.IoT.TypeEdge/DovEnv/DotenvExtension.cs index 346520b..ceaa982 100644 --- a/Microsoft.Azure.IoT.TypeEdge/DovEnv/DotenvExtension.cs +++ b/Microsoft.Azure.IoT.TypeEdge/DovEnv/DotenvExtension.cs @@ -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; diff --git a/Microsoft.Azure.IoT.TypeEdge/Extensions.cs b/Microsoft.Azure.IoT.TypeEdge/Extensions.cs new file mode 100644 index 0000000..fc7c93b --- /dev/null +++ b/Microsoft.Azure.IoT.TypeEdge/Extensions.cs @@ -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(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; + } + } +} diff --git a/Microsoft.Azure.IoT.TypeEdge/Microsoft.Azure.IoT.TypeEdge.csproj b/Microsoft.Azure.IoT.TypeEdge/Microsoft.Azure.IoT.TypeEdge.csproj index c710806..240d5af 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Microsoft.Azure.IoT.TypeEdge.csproj +++ b/Microsoft.Azure.IoT.TypeEdge/Microsoft.Azure.IoT.TypeEdge.csproj @@ -3,7 +3,7 @@ $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb Microsoft.Azure.IoT.TypeEdge - 0.1.55 + 0.1.68 paloukari Microsoft ../../TypeEdgeNuGets diff --git a/Microsoft.Azure.IoT.TypeEdge/Modules/EdgeModule.cs b/Microsoft.Azure.IoT.TypeEdge/Modules/EdgeModule.cs index a1d7aed..f15057b 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Modules/EdgeModule.cs +++ b/Microsoft.Azure.IoT.TypeEdge/Modules/EdgeModule.cs @@ -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 _methodSubscriptions; private readonly Dictionary _routeSubscriptions; - private readonly Dictionary _twinSubscriptions; private string _connectionString; private ModuleClient _ioTHubModuleClient; @@ -39,6 +38,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules _routeSubscriptions = new Dictionary(); _twinSubscriptions = new Dictionary(); _methodSubscriptions = new Dictionary(); + Volumes = new Dictionary(); Routes = new List(); @@ -60,6 +60,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules internal List Routes { get; set; } + public Dictionary Volumes { get; } internal virtual Task PublishTwinAsync(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 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($"{Constants.EdgeHubConnectionStringKey}"); if (string.IsNullOrEmpty(_connectionString)) @@ -171,9 +174,9 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules internal async Task PublishMessageAsync(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> 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(string name, Func> 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 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 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(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(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(Encoding.UTF8.GetString(bytes)); + return result; + } + } + catch (Exception ex) + { + Console.WriteLine($"{Name}:ERROR:{ex}"); + } + return null; + } + + internal bool SetFileData(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 { } + } + } } } \ No newline at end of file diff --git a/Microsoft.Azure.IoT.TypeEdge/Modules/Endpoints/Endpoint.cs b/Microsoft.Azure.IoT.TypeEdge/Modules/Endpoints/Endpoint.cs index c5bc74a..595ff60 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Modules/Endpoints/Endpoint.cs +++ b/Microsoft.Azure.IoT.TypeEdge/Modules/Endpoints/Endpoint.cs @@ -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; } } } \ No newline at end of file diff --git a/Microsoft.Azure.IoT.TypeEdge/Modules/Endpoints/Input.cs b/Microsoft.Azure.IoT.TypeEdge/Modules/Endpoints/Input.cs index 238b26d..537e640 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Modules/Endpoints/Input.cs +++ b/Microsoft.Azure.IoT.TypeEdge/Modules/Endpoints/Input.cs @@ -5,18 +5,47 @@ using Microsoft.Azure.IoT.TypeEdge.Modules.Messages; namespace Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints { public class Input : Endpoint - where T : IEdgeMessage + where T : class, IEdgeMessage, new() { + private Volumes.Volume _volume; + public Input(string name, EdgeModule module) : base(name, module) { + if (typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Reference<>)) + { + _volume = new Volumes.Volume(Name, Module); + Module.RegisterVolume(name); + } } public override string RouteName => $"BrokeredEndpoint(\"/modules/{Module.Name}/inputs/{Name}\")"; public virtual void Subscribe(Endpoint output, Func> handler) { - Module.SubscribeRoute(output.Name, output.RouteName, Name, RouteName, handler); + var dereference = new Func>((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); } } } \ No newline at end of file diff --git a/Microsoft.Azure.IoT.TypeEdge/Modules/Endpoints/Output.cs b/Microsoft.Azure.IoT.TypeEdge/Modules/Endpoints/Output.cs index 62c12db..80bc4d4 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Modules/Endpoints/Output.cs +++ b/Microsoft.Azure.IoT.TypeEdge/Modules/Endpoints/Output.cs @@ -5,18 +5,33 @@ using Microsoft.Azure.IoT.TypeEdge.Modules.Messages; namespace Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints { public class Output : Endpoint - where T : IEdgeMessage + where T : class, IEdgeMessage, new() { + private Volumes.Volume _volume; + public Output(string name, EdgeModule module) : base(name, module) { + if (typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Reference<>)) + { + _volume = new Volumes.Volume(Name, Module); + Module.RegisterVolume(name); + } } public override string RouteName => $"/messages/modules/{Module.Name}/outputs/{Name}"; - public async Task 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); } } diff --git a/Microsoft.Azure.IoT.TypeEdge/Modules/Endpoints/Upstream.cs b/Microsoft.Azure.IoT.TypeEdge/Modules/Endpoints/Upstream.cs index 1cb0ed3..c389996 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Modules/Endpoints/Upstream.cs +++ b/Microsoft.Azure.IoT.TypeEdge/Modules/Endpoints/Upstream.cs @@ -3,7 +3,7 @@ namespace Microsoft.Azure.IoT.TypeEdge.Modules.Endpoints { public class Upstream : Output - 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(Output output) - where TO : IEdgeMessage + where TO : class, IEdgeMessage, new() { Module.SubscribeRoute(output.Name, output.RouteName, Name, RouteName); } diff --git a/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/DiagnosticsMessage.cs b/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/DiagnosticsMessage.cs index e87a998..5b07326 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/DiagnosticsMessage.cs +++ b/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/DiagnosticsMessage.cs @@ -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 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); - } } } \ No newline at end of file diff --git a/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/EdgeMessage.cs b/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/EdgeMessage.cs index 81cb67a..c806fdf 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/EdgeMessage.cs +++ b/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/EdgeMessage.cs @@ -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 Properties { get; set; } - byte[] GetBytes(); - void SetBytes(byte[] bytes); + public IDictionary 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); + } } } \ No newline at end of file diff --git a/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/IEdgeMessage.cs b/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/IEdgeMessage.cs new file mode 100644 index 0000000..81cb67a --- /dev/null +++ b/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/IEdgeMessage.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace Microsoft.Azure.IoT.TypeEdge.Modules.Messages +{ + public interface IEdgeMessage + { + IDictionary Properties { get; set; } + byte[] GetBytes(); + void SetBytes(byte[] bytes); + } +} \ No newline at end of file diff --git a/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/JsonMessage.cs b/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/JsonMessage.cs index 019cd63..7efe40d 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/JsonMessage.cs +++ b/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/JsonMessage.cs @@ -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 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; } } } \ No newline at end of file diff --git a/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/Reference.cs b/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/Reference.cs new file mode 100644 index 0000000..521c290 --- /dev/null +++ b/Microsoft.Azure.IoT.TypeEdge/Modules/Messages/Reference.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.Azure.IoT.TypeEdge.Modules.Messages +{ + public class Reference : EdgeMessage + where T : IEdgeMessage + { + public Reference() + { + ReferenceCount = 1; + } + + public int ReferenceCount { get; set; } + + public string FileName { get; set; } + + public T Message { get; set; } + } +} diff --git a/Microsoft.Azure.IoT.TypeEdge/Proxy/ModuleProxyBase.cs b/Microsoft.Azure.IoT.TypeEdge/Proxy/ModuleProxyBase.cs index 0ab81c3..79d3c69 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Proxy/ModuleProxyBase.cs +++ b/Microsoft.Azure.IoT.TypeEdge/Proxy/ModuleProxyBase.cs @@ -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), diff --git a/Microsoft.Azure.IoT.TypeEdge/Startup.cs b/Microsoft.Azure.IoT.TypeEdge/Startup.cs index a03d3f5..7010d91 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Startup.cs +++ b/Microsoft.Azure.IoT.TypeEdge/Startup.cs @@ -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); } diff --git a/Microsoft.Azure.IoT.TypeEdge/Twins/ModuleTwin.cs b/Microsoft.Azure.IoT.TypeEdge/Twins/ModuleTwin.cs index 1765ba2..c1b0a45 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Twins/ModuleTwin.cs +++ b/Microsoft.Azure.IoT.TypeEdge/Twins/ModuleTwin.cs @@ -5,17 +5,18 @@ using Microsoft.Azure.IoT.TypeEdge.Modules.Enums; namespace Microsoft.Azure.IoT.TypeEdge.Twins { - public class ModuleTwin + public class ModuleTwin : 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> 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 PublishAsync(T twin) + public async Task PublishAsync(T twin) { - return Module.PublishTwinAsync(Name, twin); + var t = await Module.PublishTwinAsync(Name, twin); + LastKnownTwin = t; + return t; } public async Task GetAsync() { - return await Module.GetTwinAsync(Name); + var t = await Module.GetTwinAsync(Name); + LastKnownTwin = t; + return t; } } } \ No newline at end of file diff --git a/Microsoft.Azure.IoT.TypeEdge/Twins/TypeModuleTwin.cs b/Microsoft.Azure.IoT.TypeEdge/Twins/TypeModuleTwin.cs index 8afaa4c..431c069 100644 --- a/Microsoft.Azure.IoT.TypeEdge/Twins/TypeModuleTwin.cs +++ b/Microsoft.Azure.IoT.TypeEdge/Twins/TypeModuleTwin.cs @@ -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; diff --git a/Microsoft.Azure.IoT.TypeEdge/TypeProperty.cs b/Microsoft.Azure.IoT.TypeEdge/TypeProperty.cs new file mode 100644 index 0000000..c91fe6a --- /dev/null +++ b/Microsoft.Azure.IoT.TypeEdge/TypeProperty.cs @@ -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; } + } +} diff --git a/Microsoft.Azure.IoT.TypeEdge/Volumes/Volume.cs b/Microsoft.Azure.IoT.TypeEdge/Volumes/Volume.cs new file mode 100644 index 0000000..b4be335 --- /dev/null +++ b/Microsoft.Azure.IoT.TypeEdge/Volumes/Volume.cs @@ -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 : 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(Name, fileName); + } + + public bool Delete(string fileName) + { + return Module.DeleteFile(Name, fileName); + } + } +} diff --git a/README.md b/README.md index fd65898..a32ffcb 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/Templates/NuGet.Config b/Templates/NuGet.Config index 3d8db4a..11a36bd 100644 --- a/Templates/NuGet.Config +++ b/Templates/NuGet.Config @@ -7,6 +7,9 @@ - + + + + \ No newline at end of file diff --git a/Templates/TypeEdgeApplication/Modules/TypeEdgeModule1/TypeEdgeModule1.csproj b/Templates/TypeEdgeApplication/Modules/TypeEdgeModule1/TypeEdgeModule1.csproj index ae81089..6010d7f 100644 --- a/Templates/TypeEdgeApplication/Modules/TypeEdgeModule1/TypeEdgeModule1.csproj +++ b/Templates/TypeEdgeApplication/Modules/TypeEdgeModule1/TypeEdgeModule1.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/TypeEdgeApplication/Modules/TypeEdgeModule2/TypeEdgeModule2.csproj b/Templates/TypeEdgeApplication/Modules/TypeEdgeModule2/TypeEdgeModule2.csproj index ae81089..6010d7f 100644 --- a/Templates/TypeEdgeApplication/Modules/TypeEdgeModule2/TypeEdgeModule2.csproj +++ b/Templates/TypeEdgeApplication/Modules/TypeEdgeModule2/TypeEdgeModule2.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/TypeEdgeApplication/NuGet.Config b/Templates/TypeEdgeApplication/NuGet.Config index bb85f42..ff2e413 100644 --- a/Templates/TypeEdgeApplication/NuGet.Config +++ b/Templates/TypeEdgeApplication/NuGet.Config @@ -13,5 +13,6 @@ + \ No newline at end of file diff --git a/Templates/TypeEdgeApplication/TypeEdgeApplication.Emulator/TypeEdgeApplication.Emulator.csproj b/Templates/TypeEdgeApplication/TypeEdgeApplication.Emulator/TypeEdgeApplication.Emulator.csproj index cc2ca29..e9943a9 100644 --- a/Templates/TypeEdgeApplication/TypeEdgeApplication.Emulator/TypeEdgeApplication.Emulator.csproj +++ b/Templates/TypeEdgeApplication/TypeEdgeApplication.Emulator/TypeEdgeApplication.Emulator.csproj @@ -15,7 +15,7 @@ - + diff --git a/Templates/TypeEdgeApplication/TypeEdgeApplication.Proxy/TypeEdgeApplication.Proxy.csproj b/Templates/TypeEdgeApplication/TypeEdgeApplication.Proxy/TypeEdgeApplication.Proxy.csproj index 70ce8d5..14d141e 100644 --- a/Templates/TypeEdgeApplication/TypeEdgeApplication.Proxy/TypeEdgeApplication.Proxy.csproj +++ b/Templates/TypeEdgeApplication/TypeEdgeApplication.Proxy/TypeEdgeApplication.Proxy.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/TypeEdgeApplication/TypeEdgeApplication.Shared/TypeEdgeApplication.Shared.csproj b/Templates/TypeEdgeApplication/TypeEdgeApplication.Shared/TypeEdgeApplication.Shared.csproj index 380fb05..b3631d3 100644 --- a/Templates/TypeEdgeApplication/TypeEdgeApplication.Shared/TypeEdgeApplication.Shared.csproj +++ b/Templates/TypeEdgeApplication/TypeEdgeApplication.Shared/TypeEdgeApplication.Shared.csproj @@ -5,7 +5,7 @@ - + diff --git a/Templates/TypeEdgeEmulator/TypeEdgeEmulator.csproj b/Templates/TypeEdgeEmulator/TypeEdgeEmulator.csproj index fc73d7f..ab1847a 100644 --- a/Templates/TypeEdgeEmulator/TypeEdgeEmulator.csproj +++ b/Templates/TypeEdgeEmulator/TypeEdgeEmulator.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/TypeEdgeML/Modules/TypeEdgeModule1/TypeEdgeModule1.csproj b/Templates/TypeEdgeML/Modules/TypeEdgeModule1/TypeEdgeModule1.csproj index 4f7cf7b..39413f4 100644 --- a/Templates/TypeEdgeML/Modules/TypeEdgeModule1/TypeEdgeModule1.csproj +++ b/Templates/TypeEdgeML/Modules/TypeEdgeModule1/TypeEdgeModule1.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/TypeEdgeML/Modules/TypeEdgeModule2/TypeEdgeModule2.csproj b/Templates/TypeEdgeML/Modules/TypeEdgeModule2/TypeEdgeModule2.csproj index 4f7cf7b..39413f4 100644 --- a/Templates/TypeEdgeML/Modules/TypeEdgeModule2/TypeEdgeModule2.csproj +++ b/Templates/TypeEdgeML/Modules/TypeEdgeModule2/TypeEdgeModule2.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/TypeEdgeML/Modules/TypeEdgeModule3/TypeEdgeModule3.csproj b/Templates/TypeEdgeML/Modules/TypeEdgeModule3/TypeEdgeModule3.csproj index 816d620..ff6f9e8 100644 --- a/Templates/TypeEdgeML/Modules/TypeEdgeModule3/TypeEdgeModule3.csproj +++ b/Templates/TypeEdgeML/Modules/TypeEdgeModule3/TypeEdgeModule3.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/TypeEdgeML/NuGet.Config b/Templates/TypeEdgeML/NuGet.Config index c9222b4..56b26bb 100644 --- a/Templates/TypeEdgeML/NuGet.Config +++ b/Templates/TypeEdgeML/NuGet.Config @@ -13,6 +13,7 @@ + \ No newline at end of file diff --git a/Templates/TypeEdgeML/TypeEdgeML.Emulator/TypeEdgeML.Emulator.csproj b/Templates/TypeEdgeML/TypeEdgeML.Emulator/TypeEdgeML.Emulator.csproj index 70afd12..0e92805 100644 --- a/Templates/TypeEdgeML/TypeEdgeML.Emulator/TypeEdgeML.Emulator.csproj +++ b/Templates/TypeEdgeML/TypeEdgeML.Emulator/TypeEdgeML.Emulator.csproj @@ -18,7 +18,7 @@ - + diff --git a/Templates/TypeEdgeML/TypeEdgeML.Proxy/TypeEdgeML.Proxy.csproj b/Templates/TypeEdgeML/TypeEdgeML.Proxy/TypeEdgeML.Proxy.csproj index 4805c2a..e09ba3a 100644 --- a/Templates/TypeEdgeML/TypeEdgeML.Proxy/TypeEdgeML.Proxy.csproj +++ b/Templates/TypeEdgeML/TypeEdgeML.Proxy/TypeEdgeML.Proxy.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/TypeEdgeML/TypeEdgeML.Shared/TypeEdgeML.Shared.csproj b/Templates/TypeEdgeML/TypeEdgeML.Shared/TypeEdgeML.Shared.csproj index 380fb05..b3631d3 100644 --- a/Templates/TypeEdgeML/TypeEdgeML.Shared/TypeEdgeML.Shared.csproj +++ b/Templates/TypeEdgeML/TypeEdgeML.Shared/TypeEdgeML.Shared.csproj @@ -5,7 +5,7 @@ - + diff --git a/Templates/TypeEdgeModule/TypeEdgeModule.csproj b/Templates/TypeEdgeModule/TypeEdgeModule.csproj index 744fa24..3c4f470 100644 --- a/Templates/TypeEdgeModule/TypeEdgeModule.csproj +++ b/Templates/TypeEdgeModule/TypeEdgeModule.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/TypeEdgeProxy/TypeEdgeProxy.csproj b/Templates/TypeEdgeProxy/TypeEdgeProxy.csproj index 3481d4f..9c0a65e 100644 --- a/Templates/TypeEdgeProxy/TypeEdgeProxy.csproj +++ b/Templates/TypeEdgeProxy/TypeEdgeProxy.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/addPrivateSource.bat b/Templates/addPrivateSource.bat deleted file mode 100644 index 8c9097e..0000000 --- a/Templates/addPrivateSource.bat +++ /dev/null @@ -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.. \ No newline at end of file diff --git a/Templates/build/TypeEdgeEmulator/content/TypeEdgeEmulator.csproj b/Templates/build/TypeEdgeEmulator/content/TypeEdgeEmulator.csproj index fc73d7f..ab1847a 100644 --- a/Templates/build/TypeEdgeEmulator/content/TypeEdgeEmulator.csproj +++ b/Templates/build/TypeEdgeEmulator/content/TypeEdgeEmulator.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/build/TypeEdgeModule/content/TypeEdgeModule.csproj b/Templates/build/TypeEdgeModule/content/TypeEdgeModule.csproj index 744fa24..3c4f470 100644 --- a/Templates/build/TypeEdgeModule/content/TypeEdgeModule.csproj +++ b/Templates/build/TypeEdgeModule/content/TypeEdgeModule.csproj @@ -7,7 +7,7 @@ - + diff --git a/Templates/build/TypeEdgeProxy/content/TypeEdgeProxy.csproj b/Templates/build/TypeEdgeProxy/content/TypeEdgeProxy.csproj index 3481d4f..9c0a65e 100644 --- a/Templates/build/TypeEdgeProxy/content/TypeEdgeProxy.csproj +++ b/Templates/build/TypeEdgeProxy/content/TypeEdgeProxy.csproj @@ -7,7 +7,7 @@ - +