This commit is contained in:
Spyros Garyfallos 2018-09-28 13:40:06 -07:00
Родитель 6efa9a0a27 a8a00cb7c6
Коммит 4c8fd14432
27 изменённых файлов: 1048 добавлений и 1 удалений

@ -1 +0,0 @@
Subproject commit 9c72c053f74540b8c113e8f16a4f6de2c72662e5

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

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

1
Examples/QuickStart/.env Normal file
Просмотреть файл

@ -0,0 +1 @@
DOCKER_REGISTRY=typeedge.azurecr.io/

262
Examples/QuickStart/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,262 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
Templates/build/*
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
project.fragment.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
#*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

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

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Spyros Garyfallos
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

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

@ -0,0 +1,21 @@
ARG base_tag=2.1.2-runtime-bionic
FROM microsoft/dotnet:${base_tag} AS base
WORKDIR /app
FROM microsoft/dotnet:2.1.302-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.TypeEdge;
namespace Modules
{
internal class Program
{
public static async Task Main(string[] args)
{
await Startup.DockerEntryPoint(args);
}
}
}

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

@ -0,0 +1,128 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.TypeEdge.Enums;
using Microsoft.Azure.TypeEdge.Modules;
using Microsoft.Azure.TypeEdge.Modules.Endpoints;
using Microsoft.Azure.TypeEdge.Modules.Enums;
using Microsoft.Azure.TypeEdge.Twins;
using Microsoft.Extensions.Logging;
using ThermostatApplication.Messages;
using ThermostatApplication.Modules;
using ThermostatApplication.Twins;
using WaveGenerator;
namespace Modules
{
public class TemperatureSensor : TypeModule, ITemperatureSensor
{
//default values
private static readonly TemperatureTwin _defaultTwin = new TemperatureTwin
{
SamplingHz = 10,
Amplitude = 10,
Frequency = 2,
WaveType = WaveformType.Sine,
Offset = 60
};
private readonly DateTime _startTimeStamp;
private readonly object _sync = new object();
private double _anomalyOffset;
private WaveGenerator.WaveGenerator _dataGenerator;
private double _samplingRateHz = 1.0;
public TemperatureSensor(TemperatureTwin defaultTwin = null)
{
_startTimeStamp = DateTime.Now;
Twin.SetDefault(defaultTwin ?? _defaultTwin);
Twin.Subscribe(async twin =>
{
Logger.LogInformation("Twin update");
ConfigureGenerator(twin);
await Twin.ReportAsync(twin);
return TwinResult.Ok;
});
}
public Output<Temperature> Temperature { get; set; }
public ModuleTwin<TemperatureTwin> Twin { get; set; }
public void GenerateAnomaly(int value)
{
Logger.LogInformation($"GenerateAnomaly called with value:{value}");
lock (_sync)
{
_anomalyOffset = value;
}
}
private void ConfigureGenerator(TemperatureTwin twin)
{
lock (_sync)
{
if (twin == null
|| twin.SamplingHz <= 0
|| twin.Amplitude <= 0
|| twin.Frequency <= 0)
return;
_samplingRateHz = twin.SamplingHz;
var waveConfiguration = new[]
{
new WaveConfig
{
Amplitude = twin.Amplitude,
FrequencyInKilohertz = twin.Frequency / 1000,
WaveType = (WaveType) (int) twin.WaveType,
Offset = twin.Offset
}
};
_dataGenerator = new WaveGenerator.WaveGenerator(waveConfiguration);
}
}
public override async Task<ExecutionResult> RunAsync(CancellationToken cancellationToken)
{
var twin = await Twin.GetAsync();
ConfigureGenerator(twin);
while (!cancellationToken.IsCancellationRequested)
{
double newValue;
double offset;
double sleepTimeMs = 0;
if (_dataGenerator != null)
{
lock (_sync)
{
offset = _anomalyOffset;
newValue = _dataGenerator.Read();
sleepTimeMs = 1000.0 / _samplingRateHz;
_anomalyOffset = 0.0;
}
var message = new Temperature
{
Value = newValue + offset,
TimeStamp = DateTime.Now.Subtract(_startTimeStamp).TotalMilliseconds / 1000
};
await Temperature.PublishAsync(message);
}
await Task.Delay((int) sleepTimeMs);
}
return ExecutionResult.Ok;
}
}
}

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

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<ApplicationIcon />
<OutputType>Exe</OutputType>
<LangVersion>latest</LangVersion>
<Configurations>Debug;Release;TemplateDevelopment</Configurations>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>TRACE;DEBUG</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.TypeEdge" Version="0.4.4" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
<PackageReference Include="WaveGenerator" Version="1.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\Microsoft.Azure.TypeEdge\Microsoft.Azure.TypeEdge.csproj" Condition="'$(Configuration)|$(Platform)'=='TemplateDevelopment|AnyCPU'" />
<ProjectReference Include="..\..\Thermostat.Shared\Thermostat.Shared.csproj" />
</ItemGroup>
</Project>

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

@ -0,0 +1,2 @@
# TypeEdge.QuickStart
A simple IoT edge application example that uses TypeEdge

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

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

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

@ -0,0 +1,61 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Azure.Devices.Edge.Agent.Docker;
using Microsoft.Azure.TypeEdge;
using Microsoft.Azure.TypeEdge.Host;
using Microsoft.Extensions.Configuration;
using Modules;
using ThermostatApplication.Modules;
namespace ThermostatApplication
{
internal class Program
{
private static async Task Main(string[] args)
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appSettings.json")
.AddEnvironmentVariables()
.AddDotΕnv()
.AddCommandLine(args)
.Build();
var host = new TypeEdgeHost(configuration);
//register the modules
host.RegisterModule<ITemperatureSensor, TemperatureSensor>();
//host.RegisterExternalModule(new TypeEdge.Host.Docker.DockerModule("tempSensor",
// new HostingSettings("mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0", null),
// null,
// null));
//add cross-module routes
host.Upstream.Subscribe(host.GetProxy<ITemperatureSensor>().Temperature);
//customize the runtime configuration
var dockerRegistry = configuration.GetValue<string>("DOCKER_REGISTRY") ?? "";
var manifest = host.GenerateDeviceManifest((e, settings) =>
{
//this is the opportunity for the host to change the hosting settings of the module e
if (!settings.IsExternalModule)
settings.Config = new DockerConfig($"{dockerRegistry}{e}:1.0", settings.Config.CreateOptions);
return settings;
});
File.WriteAllText("../../../manifest.json", manifest);
//provision a new device with the new manifest
var sasToken = host.ProvisionDevice(manifest);
//build an emulated device in memory
host.BuildEmulatedDevice(sasToken);
//run the emulated device
await host.RunAsync();
Console.WriteLine("Press <ENTER> to exit..");
Console.ReadLine();
}
}
}

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

@ -0,0 +1,51 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<LangVersion>latest</LangVersion>
<Configurations>Debug;Release;TemplateDevelopment</Configurations>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>TRACE;DEBUG</DefineConstants>
</PropertyGroup>
<ItemGroup>
<None Include="..\.env" Link=".env" Visible="false">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="rocksdb-native-arm" Version="5.4.6" />
<PackageReference Include="RocksDbNative" Version="5.4.6.10" />
<PackageReference Include="Microsoft.Azure.TypeEdge.Host" Version="0.4.4" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Microsoft.Azure.TypeEdge.Host\Microsoft.Azure.TypeEdge.Host.csproj" Condition="'$(Configuration)|$(Platform)'=='TemplateDevelopment|AnyCPU'" />
<ProjectReference Include="..\Modules\TemperatureSensor\TemperatureSensor.csproj" />
<ProjectReference Include="..\Thermostat.Shared\Thermostat.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\Microsoft.Azure.TypeEdge.Host\Certificates\**\*.*" CopyToOutputDirectory="PreserveNewest" Condition="'$(Configuration)|$(Platform)'=='TemplateDevelopment|AnyCPU'">
<Link>Certificates\%(RecursiveDir)%(FileName)%(Extension)</Link>
</None>
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\Microsoft.Azure.TypeEdge.Host\appsettings_hub.json" CopyToOutputDirectory="PreserveNewest" Condition="'$(Configuration)|$(Platform)'=='TemplateDevelopment|AnyCPU'">
<Link>appsettings_hub.json</Link>
</None>
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

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

@ -0,0 +1,68 @@
{
"modulesContent": {
"$edgeAgent": {
"properties.desired": {
"schemaVersion": "1.0",
"runtime": {
"type": "docker",
"settings": {
"minDockerVersion": "v1.25",
"loggingOptions": ""
}
},
"systemModules": {
"edgeAgent": {
"type": "docker",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-agent:1.0",
"createOptions": ""
}
},
"edgeHub": {
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-hub:1.0",
"createOptions": "{\n \"HostConfig\": {\n \"PortBindings\": {\n \"8883/tcp\": [\n {\n \"HostPort\": \"8883\"\n }\n ],\n \"443/tcp\": [\n {\n \"HostPort\": \"443\"\n }\n ],\n \"5671/tcp\": [\n {\n \"HostPort\": \"5671\"\n }\n ]\n }\n }\n}"
}
}
},
"modules": {
"temperaturesensor": {
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "on-failure",
"settings": {
"image": "typeedge.azurecr.io/temperaturesensor:1.0",
"createOptions": "{\"Env\":[\"moduleName=temperaturesensor\"]}"
}
}
}
}
},
"$edgeHub": {
"properties.desired": {
"schemaVersion": "1.0",
"routes": {
"route0": "FROM /messages/modules/temperaturesensor/outputs/Temperature INTO $upstream"
},
"storeAndForwardConfiguration": {
"timeToLiveSecs": 20
}
}
},
"temperaturesensor": {
"properties.desired": {
"SamplingHz": "10",
"Frequency": "2",
"Amplitude": "10",
"WaveType": "Sine",
"Offset": "60",
"___Twin": true
}
}
},
"deviceContent": null
}

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

@ -0,0 +1,100 @@
using System;
using System.Threading.Tasks;
using Microsoft.Azure.TypeEdge.Proxy;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using ThermostatApplication.Modules;
using ThermostatApplication.Twins;
namespace Thermostat.ServiceApp
{
internal class Program
{
private static async Task Main(string[] args)
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appSettings.json")
.AddEnvironmentVariables()
.Build();
ProxyFactory.Configure(configuration["IotHubConnectionString"],
configuration["DeviceId"]);
while (true)
{
Console.WriteLine("Select Action: (T)emperatureSensorTwin, (E)xit");
var res = Console.ReadLine()?.ToUpper();
switch (res)
{
case "T":
await SetTemperatureSensorTwin();
break;
case "E":
return;
}
}
}
private static async Task SetTemperatureSensorTwin()
{
Console.WriteLine("Set Default?(Y/N)");
var res = Console.ReadLine()?.ToUpper();
if (res == "Y")
{
await SetTemperatureDefaults();
return;
}
var temperatureSensor = ProxyFactory.GetModuleProxy<ITemperatureSensor>();
var twin = await temperatureSensor.Twin.GetAsync();
Console.WriteLine($"Set the SamplingHz:{twin.SamplingHz}");
res = Console.ReadLine();
if (!string.IsNullOrEmpty(res))
twin.SamplingHz = double.Parse(res);
Console.WriteLine($"Set the Amplitude:{twin.Amplitude}");
res = Console.ReadLine();
if (!string.IsNullOrEmpty(res))
twin.Amplitude = double.Parse(res);
Console.WriteLine($"Set the Frequency:{twin.Frequency}");
res = Console.ReadLine();
if (!string.IsNullOrEmpty(res))
twin.Frequency = double.Parse(res);
Console.WriteLine($"Set the WaveType:{twin.WaveType.ToString()}");
res = Console.ReadLine();
if (!string.IsNullOrEmpty(res))
twin.WaveType = (WaveformType) Enum.Parse(typeof(WaveformType), res);
Console.WriteLine($"Set the VerticalShift:{twin.Offset}");
res = Console.ReadLine();
if (!string.IsNullOrEmpty(res))
twin.Offset = double.Parse(res);
Console.WriteLine(JsonConvert.SerializeObject(twin, Formatting.Indented));
await temperatureSensor.Twin.PublishAsync(twin);
}
private static async Task SetTemperatureDefaults()
{
Console.WriteLine("Setting TemperatureDefaults");
var temperatureSensor = ProxyFactory.GetModuleProxy<ITemperatureSensor>();
var twin = await temperatureSensor.Twin.GetAsync();
twin.SamplingHz = 10;
twin.Amplitude = 10;
twin.Frequency = 2;
twin.WaveType = WaveformType.Sine;
twin.Offset = 60;
var res = await temperatureSensor.Twin.PublishAsync(twin);
Console.WriteLine(JsonConvert.SerializeObject(twin, Formatting.Indented));
}
}
}

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

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<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.TypeEdge.Proxy" Version="0.4.4" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Microsoft.Azure.TypeEdge.Proxy\Microsoft.Azure.TypeEdge.Proxy.csproj" Condition="'$(Configuration)|$(Platform)'=='TemplateDevelopment|AnyCPU'" />
<ProjectReference Include="..\Thermostat.Shared\Thermostat.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

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

@ -0,0 +1,10 @@
using Microsoft.Azure.TypeEdge.Modules.Messages;
namespace ThermostatApplication.Messages
{
public class Temperature : EdgeMessage
{
public double Value { get; set; }
public double TimeStamp { get; set; }
}
}

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

@ -0,0 +1,17 @@
using Microsoft.Azure.TypeEdge.Attributes;
using Microsoft.Azure.TypeEdge.Modules.Endpoints;
using Microsoft.Azure.TypeEdge.Twins;
using ThermostatApplication.Messages;
using ThermostatApplication.Twins;
namespace ThermostatApplication.Modules
{
[TypeModule]
public interface ITemperatureSensor
{
Output<Temperature> Temperature { get; set; }
ModuleTwin<TemperatureTwin> Twin { get; set; }
void GenerateAnomaly(int value);
}
}

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

@ -0,0 +1,8 @@
namespace ThermostatApplication
{
public enum TemperatureScale
{
Celsius,
Fahrenheit
}
}

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

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<Configurations>Debug;Release;TemplateDevelopment</Configurations>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>TRACE;DEBUG</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.TypeEdge" Version="0.4.4" Condition="'$(Configuration)|$(Platform)'!='TemplateDevelopment|AnyCPU'" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Microsoft.Azure.TypeEdge\Microsoft.Azure.TypeEdge.csproj" Condition="'$(Configuration)|$(Platform)'=='TemplateDevelopment|AnyCPU'" />
</ItemGroup>
</Project>

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

@ -0,0 +1,16 @@
using Microsoft.Azure.TypeEdge.Twins;
namespace ThermostatApplication.Twins
{
public class TemperatureTwin : TypeTwin
{
public double SamplingHz { get; set; }
public double Frequency { get; set; }
public double Amplitude { get; set; }
public WaveformType WaveType { get; set; }
public double Offset { get; set; }
//TODO: convert this to array-ish
//public Waveform Waveform { get; set; }
}
}

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

@ -0,0 +1,10 @@
namespace ThermostatApplication.Twins
{
public class Waveform
{
public double Frequency { get; set; }
public double Amplitude { get; set; }
public WaveformType WaveType { get; set; }
public double VerticalShift { get; set; }
}
}

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

@ -0,0 +1,11 @@
namespace ThermostatApplication.Twins
{
public enum WaveformType
{
Flat = 0,
Sine = 1,
Sawtooth = 2,
Square = 3,
Triangle = 4
}
}

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

@ -0,0 +1,65 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27703.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{8D822B22-E5A9-4165-B27B-458A70D2B44F}"
EndProject
Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{1373DBDC-DC13-429E-8C17-2E4D85CF42BA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thermostat.Emulator", "Thermostat.Emulator\Thermostat.Emulator.csproj", "{1A622C23-B9BD-4903-A28D-28B446BB358E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thermostat.Shared", "Thermostat.Shared\Thermostat.Shared.csproj", "{7DB0AED8-EA6D-466E-B173-6C6BA4A692CF}"
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}") = "TemperatureSensor", "Modules\TemperatureSensor\TemperatureSensor.csproj", "{D6E0653E-E1CB-46CD-8D2B-0D6D430A5DFA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
TemplateDevelopment|Any CPU = TemplateDevelopment|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1373DBDC-DC13-429E-8C17-2E4D85CF42BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1373DBDC-DC13-429E-8C17-2E4D85CF42BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1373DBDC-DC13-429E-8C17-2E4D85CF42BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1373DBDC-DC13-429E-8C17-2E4D85CF42BA}.Release|Any CPU.Build.0 = Release|Any CPU
{1373DBDC-DC13-429E-8C17-2E4D85CF42BA}.TemplateDevelopment|Any CPU.ActiveCfg = Release|Any CPU
{1373DBDC-DC13-429E-8C17-2E4D85CF42BA}.TemplateDevelopment|Any CPU.Build.0 = Release|Any CPU
{1A622C23-B9BD-4903-A28D-28B446BB358E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A622C23-B9BD-4903-A28D-28B446BB358E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A622C23-B9BD-4903-A28D-28B446BB358E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A622C23-B9BD-4903-A28D-28B446BB358E}.Release|Any CPU.Build.0 = Release|Any CPU
{1A622C23-B9BD-4903-A28D-28B446BB358E}.TemplateDevelopment|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
{1A622C23-B9BD-4903-A28D-28B446BB358E}.TemplateDevelopment|Any CPU.Build.0 = TemplateDevelopment|Any CPU
{7DB0AED8-EA6D-466E-B173-6C6BA4A692CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7DB0AED8-EA6D-466E-B173-6C6BA4A692CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7DB0AED8-EA6D-466E-B173-6C6BA4A692CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7DB0AED8-EA6D-466E-B173-6C6BA4A692CF}.Release|Any CPU.Build.0 = Release|Any CPU
{7DB0AED8-EA6D-466E-B173-6C6BA4A692CF}.TemplateDevelopment|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
{7DB0AED8-EA6D-466E-B173-6C6BA4A692CF}.TemplateDevelopment|Any CPU.Build.0 = TemplateDevelopment|Any CPU
{258D1CCE-A112-46A2-88F1-D9BA50450C7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{258D1CCE-A112-46A2-88F1-D9BA50450C7B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{258D1CCE-A112-46A2-88F1-D9BA50450C7B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{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
{D6E0653E-E1CB-46CD-8D2B-0D6D430A5DFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D6E0653E-E1CB-46CD-8D2B-0D6D430A5DFA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D6E0653E-E1CB-46CD-8D2B-0D6D430A5DFA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D6E0653E-E1CB-46CD-8D2B-0D6D430A5DFA}.Release|Any CPU.Build.0 = Release|Any CPU
{D6E0653E-E1CB-46CD-8D2B-0D6D430A5DFA}.TemplateDevelopment|Any CPU.ActiveCfg = TemplateDevelopment|Any CPU
{D6E0653E-E1CB-46CD-8D2B-0D6D430A5DFA}.TemplateDevelopment|Any CPU.Build.0 = TemplateDevelopment|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{D6E0653E-E1CB-46CD-8D2B-0D6D430A5DFA} = {8D822B22-E5A9-4165-B27B-458A70D2B44F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E7BE10A1-BBA6-43BB-BC65-A9D38A168E00}
EndGlobalSection
EndGlobal

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

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" Sdk="Microsoft.Docker.Sdk">
<PropertyGroup Label="Globals">
<ProjectVersion>2.1</ProjectVersion>
<DockerTargetOS>Linux</DockerTargetOS>
<ProjectGuid>1373dbdc-dc13-429e-8c17-2e4d85cf42ba</ProjectGuid>
<DockerLaunchAction>LaunchBrowser</DockerLaunchAction>
<DockerServiceUrl>{Scheme}://localhost:{ServicePort}</DockerServiceUrl>
<DockerServiceName>visualizationweb</DockerServiceName>
</PropertyGroup>
<ItemGroup>
<None Include=".env" />
<None Include="docker-compose.override.yml">
<DependentUpon>docker-compose.yml</DependentUpon>
</None>
<None Include="docker-compose.yml" />
<None Include=".dockerignore" />
</ItemGroup>
</Project>

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

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

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

@ -0,0 +1,20 @@
version: '3.4'
volumes:
env:
services:
thermostat.emulator:
image: ${DOCKER_REGISTRY}thermostatemulator
build:
context: .
dockerfile: Thermostat.Emulator/Dockerfile
volumes:
- env:/app/env
temperaturesensor:
image: ${DOCKER_REGISTRY}temperaturesensor
build:
context: .
dockerfile: Modules/TemperatureSensor/Dockerfile
volumes:
- env:/app/env