diff --git a/AssetTrackerDemo.sln b/AssetTrackerDemo.sln
index cd78630..a6a2082 100644
--- a/AssetTrackerDemo.sln
+++ b/AssetTrackerDemo.sln
@@ -5,6 +5,8 @@ VisualStudioVersion = 17.1.31911.260
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetTrackerDemo", "AssetTrackerDemo\AssetTrackerDemo.csproj", "{252E24A5-0AC7-4AE7-9CD8-195F7A562D71}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetTrackerDevice", "AssetTrackerDevice\AssetTrackerDevice.csproj", "{AFF7C0F0-3529-45C5-9238-598BD0AACCF1}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
{252E24A5-0AC7-4AE7-9CD8-195F7A562D71}.Debug|Any CPU.Build.0 = Debug|Any CPU
{252E24A5-0AC7-4AE7-9CD8-195F7A562D71}.Release|Any CPU.ActiveCfg = Release|Any CPU
{252E24A5-0AC7-4AE7-9CD8-195F7A562D71}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AFF7C0F0-3529-45C5-9238-598BD0AACCF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AFF7C0F0-3529-45C5-9238-598BD0AACCF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AFF7C0F0-3529-45C5-9238-598BD0AACCF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AFF7C0F0-3529-45C5-9238-598BD0AACCF1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/AssetTrackerDevice/AssetTrackerDevice.csproj b/AssetTrackerDevice/AssetTrackerDevice.csproj
new file mode 100644
index 0000000..640a5ac
--- /dev/null
+++ b/AssetTrackerDevice/AssetTrackerDevice.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net6.0-windows10.0.17763.0
+ disable
+ enable
+ dotnet-AssetTrackerDevice-FE8FBA84-5816-4675-B918-12C1B9B0838C
+
+
+
+
+
+
+
+
+ XFAssetTracker.json
+
+
+
diff --git a/AssetTrackerDevice/DeviceRunner.cs b/AssetTrackerDevice/DeviceRunner.cs
new file mode 100644
index 0000000..23a66bf
--- /dev/null
+++ b/AssetTrackerDevice/DeviceRunner.cs
@@ -0,0 +1,69 @@
+using dtmi_assettrackerdemo;
+using Rido.IoTClient;
+using Rido.IoTClient.AzIoTHub;
+
+namespace AssetTrackerDevice
+{
+ public class DeviceRunner : BackgroundService
+ {
+ private readonly ILogger _logger;
+ private readonly IConfiguration _configuration;
+
+ public DeviceRunner(ILogger logger, IConfiguration configuration)
+ {
+ _logger = logger;
+ _configuration = configuration;
+ }
+
+ const int default_interval = 5;
+
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+ {
+ var locator = new Windows.Devices.Geolocation.Geolocator();
+ var client = await xfassettrackert0.CreateAsync(_configuration.GetConnectionString("cs"), stoppingToken);
+
+ client.Command_Reboot.OnCmdDelegate = async (cmd) =>
+ {
+ _logger.LogInformation("Command Reboot received");
+ return await Task.FromResult(new Rido.IoTClient.EmptyCommandResponse());
+ };
+
+ client.Property_Interval.OnProperty_Updated = async p =>
+ {
+ _logger.LogInformation($"Property Desired Prop received: {p.Name}: {p.Value} v {p.Version}");
+ var ack = new PropertyAck(p.Name)
+ {
+ Value = p.Value,
+ Status = 200,
+ Version = p.Version,
+ Description = "property accepted"
+ };
+ client.Property_Interval.PropertyValue.Value = p.Value;
+ return await Task.FromResult(ack);
+ };
+
+ await client.Property_Interval.InitPropertyAsync(client.InitialState, default_interval, stoppingToken);
+
+ client.Property_FrameworkVersion.PropertyValue = Environment.Version.ToString();
+ client.Property_Manufacturer.PropertyValue = "Contoso";
+ client.Property_SDKVersion.PropertyValue = (typeof(IoTHubPnPClient).Assembly.GetName().Version.ToString());
+
+ await client.ReportPropertyAsync(client.AllReadOnlyProperties, stoppingToken);
+
+ _logger.LogInformation("Loop started with interval: " + client.Property_Interval.PropertyValue.Value);
+ while (!stoppingToken.IsCancellationRequested)
+ {
+ var location = await locator.GetGeopositionAsync();
+ await client.Telemetry_Location.SendTelemetryAsync(new Location
+ {
+ lat = location.Coordinate.Latitude,
+ lon = location.Coordinate.Longitude,
+ alt = location.Coordinate.Altitude.Value
+
+ });
+ _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
+ await Task.Delay(client.Property_Interval.PropertyValue.Value * 1000, stoppingToken);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AssetTrackerDevice/Program.cs b/AssetTrackerDevice/Program.cs
new file mode 100644
index 0000000..2b6b584
--- /dev/null
+++ b/AssetTrackerDevice/Program.cs
@@ -0,0 +1,10 @@
+using AssetTrackerDevice;
+
+IHost host = Host.CreateDefaultBuilder(args)
+ .ConfigureServices(services =>
+ {
+ services.AddHostedService();
+ })
+ .Build();
+
+await host.RunAsync();
diff --git a/AssetTrackerDevice/Properties/launchSettings.json b/AssetTrackerDevice/Properties/launchSettings.json
new file mode 100644
index 0000000..6fc3b2b
--- /dev/null
+++ b/AssetTrackerDevice/Properties/launchSettings.json
@@ -0,0 +1,12 @@
+{
+ "profiles": {
+ "AssetTrackerDevice": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "environmentVariables": {
+ "DOTNET_ENVIRONMENT": "Development",
+ "ConnectionStrings__cs": "IdScope=0ne0047D00B;DeviceId=rido-tracker-01;SharedAccessKey=81gPeOIot+L2cwwOwgnaRBuzqpzihpKurt2nGmp28YU="
+ }
+ }
+ }
+}
diff --git a/AssetTrackerDevice/XFAssetTracker.json b/AssetTrackerDevice/XFAssetTracker.json
new file mode 100644
index 0000000..0e3a71e
--- /dev/null
+++ b/AssetTrackerDevice/XFAssetTracker.json
@@ -0,0 +1,80 @@
+[
+ {
+ "@id": "dtmi:assetTrackerDemo:XFAssetTrackert0;1",
+ "@type": "Interface",
+ "contents": [
+ {
+ "@id": "dtmi:assetTrackerDemo:XFAssetTrackert0:Location;1",
+ "@type": [
+ "Telemetry",
+ "Location"
+ ],
+ "displayName": {
+ "en": "Location"
+ },
+ "name": "Location",
+ "schema": "geopoint"
+ },
+ {
+ "@id": "dtmi:assetTrackerDemo:XFAssetTrackert0:Interval;1",
+ "@type": [
+ "Property",
+ "TimeSpan"
+ ],
+ "displayName": {
+ "en": "Interval"
+ },
+ "name": "Interval",
+ "schema": "integer",
+ "unit": "second",
+ "writable": true
+ },
+ {
+ "@id": "dtmi:assetTrackerDemo:XFAssetTrackert0:Reboot;1",
+ "@type": "Command",
+ "commandType": "synchronous",
+ "displayName": {
+ "en": "Reboot"
+ },
+ "name": "Reboot"
+ },
+ {
+ "@id": "dtmi:assetTrackerDemo:XFAssetTrackert0:FrameworkVersion;1",
+ "@type": "Property",
+ "displayName": {
+ "en": "FrameworkVersion"
+ },
+ "name": "FrameworkVersion",
+ "schema": "string",
+ "writable": false
+ },
+ {
+ "@id": "dtmi:assetTrackerDemo:XFAssetTrackert0:SDKVersion;1",
+ "@type": "Property",
+ "displayName": {
+ "en": "SDKVersion"
+ },
+ "name": "SDKVersion",
+ "schema": "string",
+ "writable": false
+ },
+ {
+ "@id": "dtmi:assetTrackerDemo:XFAssetTrackert0:Manufacturer;1",
+ "@type": "Property",
+ "displayName": {
+ "en": "Manufacturer"
+ },
+ "name": "Manufacturer",
+ "schema": "string",
+ "writable": false
+ }
+ ],
+ "displayName": {
+ "en": "XFAssetTracker"
+ },
+ "@context": [
+ "dtmi:iotcentral:context;2",
+ "dtmi:dtdl:context;2"
+ ]
+ }
+]
\ No newline at end of file
diff --git a/AssetTrackerDevice/appsettings.Development.json b/AssetTrackerDevice/appsettings.Development.json
new file mode 100644
index 0000000..b2dcdb6
--- /dev/null
+++ b/AssetTrackerDevice/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/AssetTrackerDevice/appsettings.json b/AssetTrackerDevice/appsettings.json
new file mode 100644
index 0000000..b2dcdb6
--- /dev/null
+++ b/AssetTrackerDevice/appsettings.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/AssetTrackerDevice/dtmi_assettrackerdemo_xfassettrackert0-1.g.cs b/AssetTrackerDevice/dtmi_assettrackerdemo_xfassettrackert0-1.g.cs
new file mode 100644
index 0000000..5513567
--- /dev/null
+++ b/AssetTrackerDevice/dtmi_assettrackerdemo_xfassettrackert0-1.g.cs
@@ -0,0 +1,56 @@
+//
+
+using MQTTnet.Client;
+using Rido.IoTClient;
+using Rido.IoTClient.AzIoTHub;
+using Rido.IoTClient.AzIoTHub.TopicBindings;
+using System.Reflection.Metadata;
+
+namespace dtmi_assettrackerdemo
+{
+ public class xfassettrackert0 : IoTHubPnPClient
+ {
+ const string modelId = "dtmi:assetTrackerDemo:XFAssetTrackert0;1";
+
+ public Telemetry Telemetry_Location;
+ public WritableProperty Property_Interval;
+ public Command Command_Reboot;
+ public ReadOnlyProperty Property_FrameworkVersion;
+ public ReadOnlyProperty Property_SDKVersion;
+ public ReadOnlyProperty Property_Manufacturer;
+
+ public xfassettrackert0(IMqttClient c) : base(c)
+ {
+ Property_Interval = new WritableProperty(c, "Interval");
+ Telemetry_Location = new Telemetry(c, "Location");
+ Command_Reboot = new Command(c, "Reboot");
+ Property_FrameworkVersion = new ReadOnlyProperty(c, "FrameworkVersion");
+ Property_SDKVersion = new ReadOnlyProperty(c, "SDKVersion");
+ Property_Manufacturer = new ReadOnlyProperty(c, "Manufacturer");
+ }
+
+ public static async Task CreateAsync(string connectionString, CancellationToken cancellationToken)
+ {
+ var cs = new ConnectionSettings(connectionString) { ModelId = modelId };
+ var client = new xfassettrackert0(await IoTHubConnectionFactory.CreateAsync(cs, cancellationToken)) { ConnectionSettings = cs };
+ client.InitialState = await client.GetTwinAsync(cancellationToken);
+ return client;
+ }
+
+ public Dictionary AllReadOnlyProperties => new Dictionary()
+ {
+ { Property_FrameworkVersion.Name, Property_FrameworkVersion.PropertyValue },
+ { Property_SDKVersion.Name, Property_SDKVersion.PropertyValue },
+ { Property_Manufacturer.Name, Property_Manufacturer.PropertyValue }
+ };
+
+
+ }
+
+ public struct Location
+ {
+ public double lat { get; set; }
+ public double lon { get; set; }
+ public double alt { get; set; }
+ }
+}