From 4e514bf0c5553b81b081d1beb092f2cee988de7d Mon Sep 17 00:00:00 2001 From: ridomin Date: Mon, 10 Jan 2022 19:35:42 -0800 Subject: [PATCH 1/3] added core sample --- AssetTrackerDemo.sln | 6 ++ AssetTrackerDevice/AssetTrackerDevice.csproj | 19 +++++ AssetTrackerDevice/Program.cs | 10 +++ .../Properties/launchSettings.json | 12 +++ AssetTrackerDevice/Worker.cs | 63 +++++++++++++++ AssetTrackerDevice/XFAssetTracker.json | 80 +++++++++++++++++++ .../appsettings.Development.json | 8 ++ AssetTrackerDevice/appsettings.json | 8 ++ ...i_assettrackerdemo_xfassettrackert0-1.g.cs | 47 +++++++++++ 9 files changed, 253 insertions(+) create mode 100644 AssetTrackerDevice/AssetTrackerDevice.csproj create mode 100644 AssetTrackerDevice/Program.cs create mode 100644 AssetTrackerDevice/Properties/launchSettings.json create mode 100644 AssetTrackerDevice/Worker.cs create mode 100644 AssetTrackerDevice/XFAssetTracker.json create mode 100644 AssetTrackerDevice/appsettings.Development.json create mode 100644 AssetTrackerDevice/appsettings.json create mode 100644 AssetTrackerDevice/dtmi_assettrackerdemo_xfassettrackert0-1.g.cs 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/Program.cs b/AssetTrackerDevice/Program.cs new file mode 100644 index 0000000..2891255 --- /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..0b76de5 --- /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-surfaceBook;SharedAccessKey=t0AfrCo0jeQo8pad4bvYhBv6BpCoqun7dYeXlaYj+WU=" + } + } + } +} diff --git a/AssetTrackerDevice/Worker.cs b/AssetTrackerDevice/Worker.cs new file mode 100644 index 0000000..b7fb0ed --- /dev/null +++ b/AssetTrackerDevice/Worker.cs @@ -0,0 +1,63 @@ +using dtmi_assettrackerdemo; +using Rido.IoTClient; +using Rido.IoTClient.AzIoTHub; + +namespace AssetTrackerDevice +{ + public class Worker : BackgroundService + { + private readonly ILogger _logger; + private readonly IConfiguration _configuration; + + public Worker(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 => + { + 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); + await client.Property_FrameworkVersion.ReportPropertyAsync(Environment.Version.ToString()); + await client.Property_Manufacturer.ReportPropertyAsync("Contoso"); + await client.Property_SDKVersion.ReportPropertyAsync(typeof(IoTHubPnPClient).Assembly.GetName().Version.ToString()); + + 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/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..7f26a5b --- /dev/null +++ b/AssetTrackerDevice/dtmi_assettrackerdemo_xfassettrackert0-1.g.cs @@ -0,0 +1,47 @@ +// + +using MQTTnet.Client; +using Rido.IoTClient; +using Rido.IoTClient.AzIoTHub; +using Rido.IoTClient.AzIoTHub.TopicBindings; + +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 struct Location + { + public double lat { get; set; } + public double lon { get; set; } + public double alt { get; set; } + } +} From 75c5b717ef7553f1c6cee798622939288720be0b Mon Sep 17 00:00:00 2001 From: ridomin Date: Tue, 11 Jan 2022 07:05:36 -0800 Subject: [PATCH 2/3] send properties in one message --- .../{Worker.cs => DeviceRunner.cs} | 16 ++++++++++------ AssetTrackerDevice/Program.cs | 2 +- ...dtmi_assettrackerdemo_xfassettrackert0-1.g.cs | 9 +++++++++ 3 files changed, 20 insertions(+), 7 deletions(-) rename AssetTrackerDevice/{Worker.cs => DeviceRunner.cs} (78%) diff --git a/AssetTrackerDevice/Worker.cs b/AssetTrackerDevice/DeviceRunner.cs similarity index 78% rename from AssetTrackerDevice/Worker.cs rename to AssetTrackerDevice/DeviceRunner.cs index b7fb0ed..24f7e7c 100644 --- a/AssetTrackerDevice/Worker.cs +++ b/AssetTrackerDevice/DeviceRunner.cs @@ -4,12 +4,12 @@ namespace AssetTrackerDevice { - public class Worker : BackgroundService + public class DeviceRunner : BackgroundService { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly IConfiguration _configuration; - public Worker(ILogger logger, IConfiguration configuration) + public DeviceRunner(ILogger logger, IConfiguration configuration) { _logger = logger; _configuration = configuration; @@ -40,11 +40,15 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) client.Property_Interval.PropertyValue.Value = p.Value; return await Task.FromResult(ack); }; + await client.Property_Interval.InitPropertyAsync(client.InitialState, default_interval, stoppingToken); - await client.Property_FrameworkVersion.ReportPropertyAsync(Environment.Version.ToString()); - await client.Property_Manufacturer.ReportPropertyAsync("Contoso"); - await client.Property_SDKVersion.ReportPropertyAsync(typeof(IoTHubPnPClient).Assembly.GetName().Version.ToString()); + 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); + while (!stoppingToken.IsCancellationRequested) { var location = await locator.GetGeopositionAsync(); diff --git a/AssetTrackerDevice/Program.cs b/AssetTrackerDevice/Program.cs index 2891255..2b6b584 100644 --- a/AssetTrackerDevice/Program.cs +++ b/AssetTrackerDevice/Program.cs @@ -3,7 +3,7 @@ IHost host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { - services.AddHostedService(); + services.AddHostedService(); }) .Build(); diff --git a/AssetTrackerDevice/dtmi_assettrackerdemo_xfassettrackert0-1.g.cs b/AssetTrackerDevice/dtmi_assettrackerdemo_xfassettrackert0-1.g.cs index 7f26a5b..5513567 100644 --- a/AssetTrackerDevice/dtmi_assettrackerdemo_xfassettrackert0-1.g.cs +++ b/AssetTrackerDevice/dtmi_assettrackerdemo_xfassettrackert0-1.g.cs @@ -4,6 +4,7 @@ using Rido.IoTClient; using Rido.IoTClient.AzIoTHub; using Rido.IoTClient.AzIoTHub.TopicBindings; +using System.Reflection.Metadata; namespace dtmi_assettrackerdemo { @@ -36,6 +37,14 @@ public static async Task CreateAsync(string connectionString, 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 From 4dea3e398903b5e388e0eaf2678e633e682a9450 Mon Sep 17 00:00:00 2001 From: ridomin Date: Tue, 11 Jan 2022 07:30:12 -0800 Subject: [PATCH 3/3] add logs --- AssetTrackerDevice/DeviceRunner.cs | 4 +++- AssetTrackerDevice/Properties/launchSettings.json | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/AssetTrackerDevice/DeviceRunner.cs b/AssetTrackerDevice/DeviceRunner.cs index 24f7e7c..23a66bf 100644 --- a/AssetTrackerDevice/DeviceRunner.cs +++ b/AssetTrackerDevice/DeviceRunner.cs @@ -30,6 +30,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) 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, @@ -48,7 +49,8 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) 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(); diff --git a/AssetTrackerDevice/Properties/launchSettings.json b/AssetTrackerDevice/Properties/launchSettings.json index 0b76de5..6fc3b2b 100644 --- a/AssetTrackerDevice/Properties/launchSettings.json +++ b/AssetTrackerDevice/Properties/launchSettings.json @@ -5,7 +5,7 @@ "dotnetRunMessages": true, "environmentVariables": { "DOTNET_ENVIRONMENT": "Development", - "ConnectionStrings__cs": "IdScope=0ne0047D00B;DeviceId=rido-surfaceBook;SharedAccessKey=t0AfrCo0jeQo8pad4bvYhBv6BpCoqun7dYeXlaYj+WU=" + "ConnectionStrings__cs": "IdScope=0ne0047D00B;DeviceId=rido-tracker-01;SharedAccessKey=81gPeOIot+L2cwwOwgnaRBuzqpzihpKurt2nGmp28YU=" } } }