Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/ci-dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ jobs:

- name: Install .NET connector templates
run: |
dotnet new install dotnet/templates/EventDrivenTelemetryConnector
dotnet new install dotnet/templates/PollingTelemetryConnector
dotnet new install dotnet/templates

- name: Build Faultable MQTT Broker
run: dotnet build eng/test/faultablemqttbroker/src/Azure.Iot.Operations.FaultableMqttBroker/Azure.Iot.Operations.FaultableMqttBroker.csproj
Expand Down
42 changes: 29 additions & 13 deletions dotnet/Azure.Iot.Operations.sln
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SqlQualityAnalyzerConnector
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Connectors", "Connectors", "{78562762-96CB-4527-8EE2-43A1CE119A21}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventDrivenTelemetryConnector", "templates\EventDrivenTelemetryConnector\EventDrivenTelemetryConnector.csproj", "{A05529AD-2D62-405A-9C2D-A122F837ECBD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PollingRestThermostatConnector", "samples\Connectors\PollingRestThermostatConnector\PollingRestThermostatConnector.csproj", "{6D8CEBB2-C805-4B45-AAFB-418B1E558146}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleTcpServiceApp", "samples\Connectors\SampleTcpServiceApp\SampleTcpServiceApp.csproj", "{566859E0-8783-92AF-29D8-F8C23A802B45}"
Expand All @@ -87,7 +85,17 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StateChangeSample", "sample
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Iot.Operations.Connector.IntegrationTests", "test\Azure.Iot.Operations.Connector.IntegrationTests\Azure.Iot.Operations.Connector.IntegrationTests.csproj", "{C527ECCE-FBE1-4FBC-9987-F94BACC904F2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PollingTelemetryConnectorTemplate", "templates\PollingTelemetryConnector\PollingTelemetryConnectorTemplate.csproj", "{698D0245-18C6-37E9-08F6-E8EADCBA0880}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Iot.Operations.Templates", "templates\Azure.Iot.Operations.Templates.csproj", "{997B55FE-157D-4EF8-8F56-94A828C9F464}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "content", "content", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EventDrivenTelemetryConnector", "EventDrivenTelemetryConnector", "{4117C707-7647-4CB7-9933-A00D7730664C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PollingTelemetryConnector", "PollingTelemetryConnector", "{8826F302-A3F9-4543-90EE-27196D9179EA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Iot.Operations.Templates.EventDrivenConnectorTemplate", "templates\content\EventDrivenConnectorTemplate\Azure.Iot.Operations.Templates.EventDrivenConnectorTemplate.csproj", "{ADDAE3BF-371C-4D4C-913E-9D165F28D6F2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Iot.Operations.Templates.PollingConnectorTemplate", "templates\content\PollingConnectorTemplate\Azure.Iot.Operations.Templates.PollingConnectorTemplate.csproj", "{2D62BB36-B1A0-4A57-9F13-EA37A6E6FD51}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -199,10 +207,6 @@ Global
{C75E1DD5-0E63-43CB-A16E-6829231059C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C75E1DD5-0E63-43CB-A16E-6829231059C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C75E1DD5-0E63-43CB-A16E-6829231059C1}.Release|Any CPU.Build.0 = Release|Any CPU
{A05529AD-2D62-405A-9C2D-A122F837ECBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A05529AD-2D62-405A-9C2D-A122F837ECBD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A05529AD-2D62-405A-9C2D-A122F837ECBD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A05529AD-2D62-405A-9C2D-A122F837ECBD}.Release|Any CPU.Build.0 = Release|Any CPU
{6D8CEBB2-C805-4B45-AAFB-418B1E558146}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6D8CEBB2-C805-4B45-AAFB-418B1E558146}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6D8CEBB2-C805-4B45-AAFB-418B1E558146}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand All @@ -223,10 +227,18 @@ Global
{C527ECCE-FBE1-4FBC-9987-F94BACC904F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C527ECCE-FBE1-4FBC-9987-F94BACC904F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C527ECCE-FBE1-4FBC-9987-F94BACC904F2}.Release|Any CPU.Build.0 = Release|Any CPU
{698D0245-18C6-37E9-08F6-E8EADCBA0880}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{698D0245-18C6-37E9-08F6-E8EADCBA0880}.Debug|Any CPU.Build.0 = Debug|Any CPU
{698D0245-18C6-37E9-08F6-E8EADCBA0880}.Release|Any CPU.ActiveCfg = Release|Any CPU
{698D0245-18C6-37E9-08F6-E8EADCBA0880}.Release|Any CPU.Build.0 = Release|Any CPU
{997B55FE-157D-4EF8-8F56-94A828C9F464}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{997B55FE-157D-4EF8-8F56-94A828C9F464}.Debug|Any CPU.Build.0 = Debug|Any CPU
{997B55FE-157D-4EF8-8F56-94A828C9F464}.Release|Any CPU.ActiveCfg = Release|Any CPU
{997B55FE-157D-4EF8-8F56-94A828C9F464}.Release|Any CPU.Build.0 = Release|Any CPU
{ADDAE3BF-371C-4D4C-913E-9D165F28D6F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ADDAE3BF-371C-4D4C-913E-9D165F28D6F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ADDAE3BF-371C-4D4C-913E-9D165F28D6F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ADDAE3BF-371C-4D4C-913E-9D165F28D6F2}.Release|Any CPU.Build.0 = Release|Any CPU
{2D62BB36-B1A0-4A57-9F13-EA37A6E6FD51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2D62BB36-B1A0-4A57-9F13-EA37A6E6FD51}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2D62BB36-B1A0-4A57-9F13-EA37A6E6FD51}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2D62BB36-B1A0-4A57-9F13-EA37A6E6FD51}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -263,13 +275,17 @@ Global
{99113A50-9774-4F42-B18D-5284639194A6} = {CE9A7664-594B-43EB-AA48-606B88411FC9}
{C75E1DD5-0E63-43CB-A16E-6829231059C1} = {78562762-96CB-4527-8EE2-43A1CE119A21}
{78562762-96CB-4527-8EE2-43A1CE119A21} = {9126F576-80AE-48DC-8A84-EFC8B487D809}
{A05529AD-2D62-405A-9C2D-A122F837ECBD} = {4636D1F8-ACA6-4138-8EC0-1FF71CAF3A3B}
{6D8CEBB2-C805-4B45-AAFB-418B1E558146} = {78562762-96CB-4527-8EE2-43A1CE119A21}
{566859E0-8783-92AF-29D8-F8C23A802B45} = {78562762-96CB-4527-8EE2-43A1CE119A21}
{E97EAFE6-F4D8-4B9A-B53C-8A479A9BBFB5} = {78562762-96CB-4527-8EE2-43A1CE119A21}
{4992415C-ABB2-2284-D6CD-8FE01910092F} = {4DDB0B28-1830-4B6F-8A10-FB37874D4D57}
{C527ECCE-FBE1-4FBC-9987-F94BACC904F2} = {CE9A7664-594B-43EB-AA48-606B88411FC9}
{698D0245-18C6-37E9-08F6-E8EADCBA0880} = {4636D1F8-ACA6-4138-8EC0-1FF71CAF3A3B}
{997B55FE-157D-4EF8-8F56-94A828C9F464} = {4636D1F8-ACA6-4138-8EC0-1FF71CAF3A3B}
{02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {4636D1F8-ACA6-4138-8EC0-1FF71CAF3A3B}
{4117C707-7647-4CB7-9933-A00D7730664C} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{8826F302-A3F9-4543-90EE-27196D9179EA} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{ADDAE3BF-371C-4D4C-913E-9D165F28D6F2} = {4117C707-7647-4CB7-9933-A00D7730664C}
{2D62BB36-B1A0-4A57-9F13-EA37A6E6FD51} = {8826F302-A3F9-4543-90EE-27196D9179EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F2687BCD-45E3-4094-9656-BF183C816BA0}
Expand Down
39 changes: 39 additions & 0 deletions dotnet/templates/Azure.Iot.Operations.Templates.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<PackageId>Azure.Iot.Operations.Templates</PackageId>
<PackageVersion>0.1.0</PackageVersion>
<Title>Azure IoT Operations Templates</Title>
<Authors>Microsoft</Authors>
<Description>.NET project templates for creating Azure IoT Operations solutions</Description>
<PackageTags>azure;iot;sdk;edge</PackageTags>
<PackageProjectUrl>https://github.com/Azure/iot-operations-sdks</PackageProjectUrl>

<PackageType>Template</PackageType>
<TargetFramework>net9.0</TargetFramework>
<IncludeContentInPack>true</IncludeContentInPack>
<IncludeBuildOutput>false</IncludeBuildOutput>
<ContentTargetFolders>content</ContentTargetFolders>
<NoWarn>$(NoWarn);NU5128</NoWarn>
<NoDefaultExcludes>true</NoDefaultExcludes>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>

<PropertyGroup>
<LocalizeTemplates>false</LocalizeTemplates>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.TemplateEngine.Tasks" Version="*" PrivateAssets="all" IsImplicitlyDefined="true"/>
</ItemGroup>

<ItemGroup>
<Content Include="content\**\*" Exclude="content\**\bin\**;content\**\obj\**" />
<Compile Remove="**\*" />
</ItemGroup>

<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="" />
</ItemGroup>

</Project>

This file was deleted.

This file was deleted.

39 changes: 8 additions & 31 deletions dotnet/templates/README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,13 @@
# Azure IoT Operation .NET Project Templates
# Azure IoT Operations .NET Project Templates

This folder contains .NET project tempate definitions that are useful when developing
applications for your Azure IoT Operations environment.
This package contains the following project templates to help you develop Azure IoT Operations solutions:

## How To Install A .NET Project Template
- Azure.Iot.Operations.Templates.PollingConnectorTemplate
- A template for creating an AIO connector that polls an endpoint and forwards that polled telemetry to the AIO MQTT broker.
- Azure.Iot.Operations.Templates.EventDrivenConnectorTemplate
- A template for creating an AIO connector that listens for events from an endpoint and forwards those events the AIO MQTT broker as telemetry.

To install a project template, simply navigate to the directory of the template you want to install and run the command:

```bash
dotnet new install .
```
For examples on how to fill out these templates, see the completed samples [here](https://github.com/Azure/iot-operations-sdks/tree/main/dotnet/samples).

## How To Create A New Project With An Installed Project Template

You can use this locally installed project template when creating a new project in Visual Studio:

`File -> New Project -> Select the installed project template`

Alternatively, you can create a new project from an installed template from command line:

```bash
dotnet new aiopollingtelemetryconnector -n MyConnectorApp
```

Where "aiopollingtelemetryconnector" is the short name defined in the project template's [template.json file](./PollingTelemetryConnector/.template.config/template.json) and where "MyConnectorApp" is the name of your project.

Note that this command will create the project "MyConnectorApp" in the same directory that the command was run from.

## How To Uninstall A .NET Project Template

Navigate to the directory with the project template to uninstall and run the command:

```bash
dotnet new uninstall .
```
If you have any questions or need any support, please file an issue [here](https://github.com/Azure/iot-operations-sdks/issues)
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "http://json.schemastore.org/template",
"author": "timtay-microsoft",
"classifications": [ "Linux", "Windows", "Service"],
"identity": "AzureIotOperations.EventDrivenTelemetryConnector",
"identity": "Azure.Iot.Operations.Templates.EventDrivenConnectorTemplate",
"name": "Azure IoT Operations Event Driven Telemetry Connector",
"shortName": "aioeventdriventelemetryconnector",
"sourceName":"EventDrivenTelemetryConnector",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Worker">
<Project Sdk="Microsoft.NET.Sdk.Worker">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
Expand All @@ -9,6 +9,6 @@

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
<PackageReference Include="Azure.Iot.Operations.Connector" Version="0.13.0-preview" />
<PackageReference Include="Azure.Iot.Operations.Connector" Version="0.13.0" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Azure.Iot.Operations.Connector;

namespace EventDrivenTelemetryConnector
{
/// <summary>
/// Factory that provides all leader election configurations for this connector.
/// </summary>
/// <remarks>
/// Connectors can have active/passive replication by deploying more than one replica and having each replica
/// provide the same leadership position Id. That way, only one replica is the leader at a time.
///
/// If no replication of this connector is needed, then this class can be deleted.
/// </remarks>
public class LeaderElectionConfigurationProvider : IConnectorLeaderElectionConfigurationProvider
{
public static Func<IServiceProvider, IConnectorLeaderElectionConfigurationProvider> Factory = service =>
{
return new LeaderElectionConfigurationProvider();
};

public ConnectorLeaderElectionConfiguration GetLeaderElectionConfiguration()
{
// This value should be the same across any replicas but should be unique from connector to connector.
string leadershipPositionId = "some-leadership-position-id";
return new(leadershipPositionId, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(9));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@

namespace EventDrivenTelemetryConnector
{
/// <summary>
/// The factory method for determining what message schema should be registered for and attached to each
/// emitted telemetry message for each event handled by this connector. If no message schema is needed,
/// then this class can be left as-is.
/// </summary>
/// <remarks>
/// Registering message schemas allows the receiver of a message to fetch this schema from the schema
/// registry service. With that schema, the receiver can correctly deserialize each received message's payload.
/// </remarks>
internal class MessageSchemaProvider : IMessageSchemaProvider
{
public static Func<IServiceProvider, IMessageSchemaProvider> Factory = service =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@
// Licensed under the MIT License.

using Azure.Iot.Operations.Connector;
using Azure.Iot.Operations.Connector.ConnectorConfigurations;
using Azure.Iot.Operations.Protocol;
using EventDrivenTelemetryConnector;

string connectorClientId = Environment.GetEnvironmentVariable(ConnectorFileMountSettings.ConnectorClientIdEnvVar) ?? throw new InvalidOperationException("No MQTT client Id configured by Akri operator");

IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
Expand Down
27 changes: 27 additions & 0 deletions dotnet/templates/content/EventDrivenConnectorTemplate/Worker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace EventDrivenConnectorTemplate
{
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;

public Worker(ILogger<Worker> logger)
{
_logger = logger;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
if (_logger.IsEnabled(LogLevel.Information))
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
}
await Task.Delay(1000, stoppingToken);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "http://json.schemastore.org/template",
"author": "timtay-microsoft",
"classifications": [ "Linux", "Windows", "Service"],
"identity": "AzureIotOperations.PollingTelemetryConnector",
"identity": "Azure.Iot.Operations.Templates.PollingConnectorTemplate",
"name": "Azure IoT Operations Polling Telemetry Connector",
"shortName": "aiopollingtelemetryconnector",
"sourceName":"PollingTelemetryConnectorTemplate",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Worker">
<Project Sdk="Microsoft.NET.Sdk.Worker">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
Expand All @@ -9,7 +9,6 @@

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
<PackageReference Include="Azure.Iot.Operations.Connector" Version="0.13.0-preview" />
<PackageReference Include="Azure.Iot.Operations.Connector" Version="0.13.0" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

namespace PollingTelemetryConnectorTemplate
{
/// <summary>
/// The factory for creating the samplers for each dataset.
/// </summary>
public class DatasetSamplerProvider : IDatasetSamplerFactory
{
public static Func<IServiceProvider, IDatasetSamplerFactory> Factory = service =>
Expand All @@ -16,8 +19,9 @@ public class DatasetSamplerProvider : IDatasetSamplerFactory

public IDatasetSampler CreateDatasetSampler(string deviceName, Device device, string inboundEndpointName, string assetName, Asset asset, AssetDataset dataset, EndpointCredentials? endpointCredentials)
{
// this method should return the appropriate dataset sampler implementation for the provided asset + dataset. This
// method may be called multiple times if the asset or dataset changes in any way over time.
// As the connector discovers each dataset, it will need to know how to sample that dataset. To figure that
// out, this callback is invoked to provide context on which dataset was discovered and what device + endpoint + asset it
// belongs to. This callback may be called multiple times if the asset or dataset changes in any way over time.
throw new NotImplementedException();
}
}
Expand Down
Loading
Loading