Skip to content
This repository was archived by the owner on Nov 16, 2023. It is now read-only.

Commit 5d97d5b

Browse files
Merge pull request #94 from timtay-microsoft/dtSamples
Add Digital Twin device and service samples
2 parents 4b57b4e + 86a9822 commit 5d97d5b

20 files changed

+1229
-0
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.29519.87
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EnvironmentalSensorSample", "EnvironmentalSensorSample\EnvironmentalSensorSample.csproj", "{3A11A999-B681-46D1-A94E-8E5245075A4B}"
7+
EndProject
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EnvironmentalSensorLib", "EnvironmentSensorLib\EnvironmentalSensorLib.csproj", "{0D078234-5B32-464D-A56F-D24AC662A89E}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
Release|Any CPU = Release|Any CPU
14+
EndGlobalSection
15+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
16+
{3A11A999-B681-46D1-A94E-8E5245075A4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17+
{3A11A999-B681-46D1-A94E-8E5245075A4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
18+
{3A11A999-B681-46D1-A94E-8E5245075A4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
19+
{3A11A999-B681-46D1-A94E-8E5245075A4B}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{0D078234-5B32-464D-A56F-D24AC662A89E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{0D078234-5B32-464D-A56F-D24AC662A89E}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{0D078234-5B32-464D-A56F-D24AC662A89E}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{0D078234-5B32-464D-A56F-D24AC662A89E}.Release|Any CPU.Build.0 = Release|Any CPU
24+
EndGlobalSection
25+
GlobalSection(SolutionProperties) = preSolution
26+
HideSolutionNode = FALSE
27+
EndGlobalSection
28+
GlobalSection(ExtensibilityGlobals) = postSolution
29+
SolutionGuid = {66A14B8B-7E91-41AB-9530-98CE57947146}
30+
EndGlobalSection
31+
EndGlobal
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Collections.ObjectModel;
6+
using System.Threading.Tasks;
7+
using Microsoft.Azure.Devices.DigitalTwin.Client;
8+
using Microsoft.Azure.Devices.DigitalTwin.Client.Model;
9+
10+
namespace EnvironmentalSensorSample
11+
{
12+
/// <summary>
13+
/// Sample for DigitalTwinInterfaceClient implementation.
14+
/// </summary>
15+
public class EnvironmentalSensorInterface : DigitalTwinInterfaceClient
16+
{
17+
public const string EnvironmentalSensorInterfaceId = "urn:csharp_sdk_sample:EnvironmentalSensor:1";
18+
private const string DeviceState = "state";
19+
private const string CustomerName = "name";
20+
private const string Brightness = "brightness";
21+
private const string Temperature = "temp";
22+
private const string Humidity = "humid";
23+
private const string BlinkCommand = "blink";
24+
private const string TurnOnLightCommand = "turnon";
25+
private const string TurnOffLightCommand = "turnoff";
26+
private const string RunDiagnosticsCommand = "rundiagnostics";
27+
28+
/// <summary>
29+
/// Initializes a new instance of the <see cref="EnvironmentalSensorInterface"/> class.
30+
/// </summary>
31+
/// <param name="interfaceName">interface name.</param>
32+
public EnvironmentalSensorInterface(string interfaceName)
33+
: base(EnvironmentalSensorInterfaceId, interfaceName)
34+
{
35+
}
36+
37+
/// <summary>
38+
/// Sample for reporting a property on an interface.
39+
/// </summary>
40+
/// <param name="state">state property.</param>
41+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
42+
public async Task DeviceStatePropertyAsync(bool state)
43+
{
44+
var deviceStateProperty = new DigitalTwinPropertyReport(DeviceState, state.ToString().ToLower());
45+
await this.ReportPropertiesAsync(new Collection<DigitalTwinPropertyReport> { deviceStateProperty }).ConfigureAwait(false);
46+
}
47+
48+
/// <summary>
49+
/// Send Temperature telemetry.
50+
/// </summary>
51+
/// <param name="temperature">telemetry value.</param>
52+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
53+
public async Task SendTemperatureAsync(double temperature)
54+
{
55+
await this.SendTelemetryAsync(Temperature, temperature.ToString()).ConfigureAwait(false);
56+
}
57+
58+
/// <summary>
59+
/// Send Humidity telemetry.
60+
/// </summary>
61+
/// <param name="humidity">telemetry value.</param>
62+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
63+
public async Task SendHumidityAsync(double humidity)
64+
{
65+
await this.SendTelemetryAsync(Humidity, humidity.ToString()).ConfigureAwait(false);
66+
}
67+
68+
69+
/// <summary>
70+
/// Callback on command received.
71+
/// </summary>
72+
/// <param name="commandRequest">information regarding the command received.</param>
73+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
74+
protected override async Task<DigitalTwinCommandResponse> OnCommandRequest(DigitalTwinCommandRequest commandRequest)
75+
{
76+
Console.WriteLine($"\t Command - {commandRequest.Name} was invoked from the service");
77+
Console.WriteLine($"\t Data - {commandRequest.Payload}");
78+
Console.WriteLine($"\t Request Id - {commandRequest.RequestId}.");
79+
80+
switch (commandRequest.Name)
81+
{
82+
case BlinkCommand:
83+
return new DigitalTwinCommandResponse(StatusCodeCompleted, "{\"description\": \"abc\"}");
84+
case RunDiagnosticsCommand:
85+
var t = Task.Run(async () =>
86+
{
87+
Console.WriteLine("RunDiagnosticAsync started...");
88+
89+
// delay thread to simulate a long running operation
90+
await Task.Delay(5 * 1000).ConfigureAwait(false);
91+
string updateMessage = "25% complete";
92+
Console.WriteLine(updateMessage);
93+
await this.UpdateAsyncCommandStatusAsync(new DigitalTwinAsyncCommandUpdate(commandRequest.Name, commandRequest.RequestId, StatusCodePending, updateMessage)).ConfigureAwait(false);
94+
95+
await Task.Delay(5 * 1000).ConfigureAwait(false);
96+
updateMessage = "50% complete";
97+
Console.WriteLine(updateMessage);
98+
await this.UpdateAsyncCommandStatusAsync(new DigitalTwinAsyncCommandUpdate(commandRequest.Name, commandRequest.RequestId, StatusCodePending, updateMessage)).ConfigureAwait(false);
99+
100+
await Task.Delay(5 * 1000).ConfigureAwait(false);
101+
updateMessage = "75% complete";
102+
Console.WriteLine(updateMessage);
103+
await this.UpdateAsyncCommandStatusAsync(new DigitalTwinAsyncCommandUpdate(commandRequest.Name, commandRequest.RequestId, StatusCodePending, updateMessage)).ConfigureAwait(false);
104+
105+
await Task.Delay(5 * 1000).ConfigureAwait(false);
106+
updateMessage = "100% complete";
107+
Console.WriteLine(updateMessage);
108+
Console.WriteLine("RunDiagnosticAsync done... Send status update.");
109+
await this.UpdateAsyncCommandStatusAsync(new DigitalTwinAsyncCommandUpdate(commandRequest.Name, commandRequest.RequestId, StatusCodeCompleted, updateMessage)).ConfigureAwait(false);
110+
});
111+
return new DigitalTwinCommandResponse(StatusCodePending, null);
112+
case TurnOffLightCommand:
113+
await this.DeviceStatePropertyAsync(false);
114+
return new DigitalTwinCommandResponse(StatusCodeCompleted, null);
115+
case TurnOnLightCommand:
116+
await this.DeviceStatePropertyAsync(true);
117+
return new DigitalTwinCommandResponse(StatusCodeCompleted, null);
118+
default:
119+
Console.WriteLine($"Command name '{commandRequest.Name}' is not handled.");
120+
return new DigitalTwinCommandResponse(StatusCodeNotImplemented, null);
121+
}
122+
}
123+
124+
/// <summary>
125+
/// Callback on property updated.
126+
/// </summary>
127+
/// <param name="propertyUpdate">information regarding the property updated.</param>
128+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
129+
protected override async Task OnPropertyUpdated(DigitalTwinPropertyUpdate propertyUpdate)
130+
{
131+
Console.WriteLine($"Received updates for property '{propertyUpdate.PropertyName}'");
132+
133+
switch (propertyUpdate.PropertyName)
134+
{
135+
case CustomerName:
136+
await this.SetCustomerNameAsync(propertyUpdate).ConfigureAwait(false);
137+
break;
138+
case Brightness:
139+
await this.SetBrightnessAsync(propertyUpdate).ConfigureAwait(false);
140+
break;
141+
default:
142+
Console.WriteLine($"Property name '{propertyUpdate.PropertyName}' is not handled.");
143+
break;
144+
}
145+
}
146+
147+
/// <summary>
148+
/// Callback when registration is completed.
149+
/// </summary>
150+
protected override void OnRegistrationCompleted()
151+
{
152+
Console.WriteLine($"OnRegistrationCompleted.");
153+
}
154+
155+
/// <summary>
156+
/// Process CustomerName property updated.
157+
/// </summary>
158+
/// <param name="customerNameUpdate">information of property to be reported.</param>
159+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
160+
private async Task SetCustomerNameAsync(DigitalTwinPropertyUpdate customerNameUpdate)
161+
{
162+
// code to consume customer value, currently just displaying on screen.
163+
string customerName = customerNameUpdate.PropertyDesired;
164+
Console.WriteLine($"Desired customer name = '{customerName}'.");
165+
Console.WriteLine($"Reported customer name = '{customerNameUpdate.PropertyReported}'.");
166+
Console.WriteLine($"Version is '{customerNameUpdate.DesiredVersion}'.");
167+
168+
// report Completed
169+
var propertyReport = new Collection<DigitalTwinPropertyReport>();
170+
propertyReport.Add(new DigitalTwinPropertyReport(
171+
customerNameUpdate.PropertyName,
172+
customerNameUpdate.PropertyDesired,
173+
new DigitalTwinPropertyResponse(customerNameUpdate.DesiredVersion, StatusCodeCompleted, "Processing Completed")));
174+
await this.ReportPropertiesAsync(propertyReport).ConfigureAwait(false);
175+
Console.WriteLine("Sent completed status.");
176+
}
177+
178+
/// <summary>
179+
/// Process Brightness property updated.
180+
/// </summary>
181+
/// <param name="brightnessUpdate">information of property to be reported.</param>
182+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
183+
private async Task SetBrightnessAsync(DigitalTwinPropertyUpdate brightnessUpdate)
184+
{
185+
// code to consume light brightness value, currently just displaying on screen
186+
string brightness = brightnessUpdate.PropertyDesired;
187+
long current = 0;
188+
189+
Console.WriteLine($"Desired brightness = '{brightness}'.");
190+
Console.WriteLine($"Reported brightness = '{brightnessUpdate.PropertyReported}'.");
191+
Console.WriteLine($"Version is '{brightnessUpdate.DesiredVersion}'.");
192+
193+
// report Pending
194+
var propertyReport = new Collection<DigitalTwinPropertyReport>();
195+
propertyReport.Add(new DigitalTwinPropertyReport(
196+
brightnessUpdate.PropertyName,
197+
current.ToString(),
198+
new DigitalTwinPropertyResponse(brightnessUpdate.DesiredVersion, 102, "Processing Request")));
199+
await this.ReportPropertiesAsync(propertyReport).ConfigureAwait(false);
200+
Console.WriteLine("Sent pending status for brightness property.");
201+
propertyReport.Clear();
202+
203+
// Pretend calling command to Sensor to update brightness
204+
await Task.Delay(5 * 1000).ConfigureAwait(false);
205+
206+
// report Completed
207+
propertyReport.Add(new DigitalTwinPropertyReport(
208+
brightnessUpdate.PropertyName,
209+
brightnessUpdate.PropertyDesired,
210+
new DigitalTwinPropertyResponse(
211+
brightnessUpdate.DesiredVersion,
212+
StatusCodeCompleted,
213+
"Request completed")));
214+
await this.ReportPropertiesAsync(propertyReport).ConfigureAwait(false);
215+
Console.WriteLine("Sent completed status for brightness property.");
216+
}
217+
}
218+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Library</OutputType>
5+
<TargetFramework>netcoreapp2.2</TargetFramework>
6+
<ApplicationIcon />
7+
<StartupObject />
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="Microsoft.Azure.Devices.DigitalTwin.Client" Version="1.0.0-preview-*" />
12+
</ItemGroup>
13+
</Project>

0 commit comments

Comments
 (0)