diff --git a/.github/workflows/ci-dotnet.yml b/.github/workflows/ci-dotnet.yml
index 49014d5d12..4ba7449014 100644
--- a/.github/workflows/ci-dotnet.yml
+++ b/.github/workflows/ci-dotnet.yml
@@ -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
diff --git a/dotnet/Azure.Iot.Operations.sln b/dotnet/Azure.Iot.Operations.sln
index 08731dcfeb..bb3c80ff6d 100644
--- a/dotnet/Azure.Iot.Operations.sln
+++ b/dotnet/Azure.Iot.Operations.sln
@@ -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}"
@@ -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
@@ -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
@@ -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
@@ -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}
diff --git a/dotnet/templates/Azure.Iot.Operations.Templates.csproj b/dotnet/templates/Azure.Iot.Operations.Templates.csproj
new file mode 100644
index 0000000000..48700f723f
--- /dev/null
+++ b/dotnet/templates/Azure.Iot.Operations.Templates.csproj
@@ -0,0 +1,42 @@
+
+
+
+ Azure.Iot.Operations.Templates
+ 0.1.0
+ Azure IoT Operations Templates
+ Microsoft
+ .NET project templates for creating Azure IoT Operations solutions
+ azure;iot;sdk;edge
+ https://github.com/Azure/iot-operations-sdks/
+ https://github.com/Azure/iot-operations-sdks/blob/main/LICENSE
+ MIT
+ © Microsoft Corporation. All rights reserved.
+
+ Template
+ net9.0
+ true
+ false
+ content
+ $(NoWarn);NU5128
+ true
+ README.md
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/templates/EventDrivenTelemetryConnector/LeaderElectionConfigurationProvider.cs b/dotnet/templates/EventDrivenTelemetryConnector/LeaderElectionConfigurationProvider.cs
deleted file mode 100644
index 54e383d4d1..0000000000
--- a/dotnet/templates/EventDrivenTelemetryConnector/LeaderElectionConfigurationProvider.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using Azure.Iot.Operations.Connector;
-
-namespace EventDrivenTelemetryConnector
-{
- public class LeaderElectionConfigurationProvider : IConnectorLeaderElectionConfigurationProvider
- {
- public static Func Factory = service =>
- {
- return new LeaderElectionConfigurationProvider();
- };
-
- public ConnectorLeaderElectionConfiguration GetLeaderElectionConfiguration()
- {
- return new("some-http-leadership-position-id", TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(9));
- }
- }
-}
diff --git a/dotnet/templates/PollingTelemetryConnector/LeaderElectionConfigurationProvider.cs b/dotnet/templates/PollingTelemetryConnector/LeaderElectionConfigurationProvider.cs
deleted file mode 100644
index 0d1f47c37a..0000000000
--- a/dotnet/templates/PollingTelemetryConnector/LeaderElectionConfigurationProvider.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using Azure.Iot.Operations.Connector;
-
-namespace PollingTelemetryConnectorTemplate
-{
- public class LeaderElectionConfigurationProvider : IConnectorLeaderElectionConfigurationProvider
- {
- public static Func Factory = service =>
- {
- return new LeaderElectionConfigurationProvider();
- };
-
- public ConnectorLeaderElectionConfiguration GetLeaderElectionConfiguration()
- {
- return new("some-http-leadership-position-id", TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(9));
- }
- }
-}
diff --git a/dotnet/templates/README.md b/dotnet/templates/README.md
index 38ae9361ea..97e9f1f432 100644
--- a/dotnet/templates/README.md
+++ b/dotnet/templates/README.md
@@ -1,11 +1,26 @@
-# 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:
+
+ - 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.
+
+
+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).
+
+If you have any questions or need any support, please file an issue [here](https://github.com/Azure/iot-operations-sdks/issues)
## How To Install A .NET Project Template
-To install a project template, simply navigate to the directory of the template you want to install and run the command:
+To install these templates using the published package in Nuget.org, run the following command:
+
+```bash
+dotnet new install Azure.Iot.Operations.Template
+```
+
+Alternatively, to install these templates from source, run the following command in this directory:
```bash
dotnet new install .
@@ -23,14 +38,20 @@ Alternatively, you can create a new project from an installed template from comm
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.
+Where "aiopollingtelemetryconnector" is the short name defined in the project template's [template.json file](./content/PollingConnectorTemplate/.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:
+To uninstall these templates when they were installed from the published package in Nuget.org, run the following command:
```bash
-dotnet new uninstall .
+dotnet new uninstall Azure.Iot.Operations.Template
```
+
+Alternatively, to uninstall these templates when they were installed from source, run the following command in this directory:
+
+```bash
+dotnet new uninstall .
+```
\ No newline at end of file
diff --git a/dotnet/templates/EventDrivenTelemetryConnector/.template.config/template.json b/dotnet/templates/content/EventDrivenConnectorTemplate/.template.config/template.json
similarity index 83%
rename from dotnet/templates/EventDrivenTelemetryConnector/.template.config/template.json
rename to dotnet/templates/content/EventDrivenConnectorTemplate/.template.config/template.json
index 70d6b54c9a..997081d551 100644
--- a/dotnet/templates/EventDrivenTelemetryConnector/.template.config/template.json
+++ b/dotnet/templates/content/EventDrivenConnectorTemplate/.template.config/template.json
@@ -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",
diff --git a/dotnet/templates/PollingTelemetryConnector/PollingTelemetryConnectorTemplate.csproj b/dotnet/templates/content/EventDrivenConnectorTemplate/Azure.Iot.Operations.Templates.EventDrivenConnectorTemplate.csproj
similarity index 84%
rename from dotnet/templates/PollingTelemetryConnector/PollingTelemetryConnectorTemplate.csproj
rename to dotnet/templates/content/EventDrivenConnectorTemplate/Azure.Iot.Operations.Templates.EventDrivenConnectorTemplate.csproj
index 96bb591866..65119de126 100644
--- a/dotnet/templates/PollingTelemetryConnector/PollingTelemetryConnectorTemplate.csproj
+++ b/dotnet/templates/content/EventDrivenConnectorTemplate/Azure.Iot.Operations.Templates.EventDrivenConnectorTemplate.csproj
@@ -1,4 +1,4 @@
-
+
net9.0
@@ -9,6 +9,6 @@
-
+
diff --git a/dotnet/templates/content/EventDrivenConnectorTemplate/LeaderElectionConfigurationProvider.cs b/dotnet/templates/content/EventDrivenConnectorTemplate/LeaderElectionConfigurationProvider.cs
new file mode 100644
index 0000000000..e39cdc3d6a
--- /dev/null
+++ b/dotnet/templates/content/EventDrivenConnectorTemplate/LeaderElectionConfigurationProvider.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Azure.Iot.Operations.Connector;
+
+namespace EventDrivenTelemetryConnector
+{
+ ///
+ /// Factory that provides all leader election configurations for this connector.
+ ///
+ ///
+ /// 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.
+ ///
+ public class LeaderElectionConfigurationProvider : IConnectorLeaderElectionConfigurationProvider
+ {
+ public static Func 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));
+ }
+ }
+}
diff --git a/dotnet/templates/EventDrivenTelemetryConnector/MessageSchemaProvider.cs b/dotnet/templates/content/EventDrivenConnectorTemplate/MessageSchemaProvider.cs
similarity index 68%
rename from dotnet/templates/EventDrivenTelemetryConnector/MessageSchemaProvider.cs
rename to dotnet/templates/content/EventDrivenConnectorTemplate/MessageSchemaProvider.cs
index 640bfb4483..93e1434642 100644
--- a/dotnet/templates/EventDrivenTelemetryConnector/MessageSchemaProvider.cs
+++ b/dotnet/templates/content/EventDrivenConnectorTemplate/MessageSchemaProvider.cs
@@ -6,6 +6,15 @@
namespace EventDrivenTelemetryConnector
{
+ ///
+ /// 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.
+ ///
+ ///
+ /// 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.
+ ///
internal class MessageSchemaProvider : IMessageSchemaProvider
{
public static Func Factory = service =>
diff --git a/dotnet/templates/EventDrivenTelemetryConnector/Program.cs b/dotnet/templates/content/EventDrivenConnectorTemplate/Program.cs
similarity index 74%
rename from dotnet/templates/EventDrivenTelemetryConnector/Program.cs
rename to dotnet/templates/content/EventDrivenConnectorTemplate/Program.cs
index 8202d139e4..82b3caad0b 100644
--- a/dotnet/templates/EventDrivenTelemetryConnector/Program.cs
+++ b/dotnet/templates/content/EventDrivenConnectorTemplate/Program.cs
@@ -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 =>
{
diff --git a/dotnet/templates/EventDrivenTelemetryConnector/TemplateConnectorWorker.cs b/dotnet/templates/content/EventDrivenConnectorTemplate/TemplateConnectorWorker.cs
similarity index 100%
rename from dotnet/templates/EventDrivenTelemetryConnector/TemplateConnectorWorker.cs
rename to dotnet/templates/content/EventDrivenConnectorTemplate/TemplateConnectorWorker.cs
diff --git a/dotnet/templates/content/EventDrivenConnectorTemplate/Worker.cs b/dotnet/templates/content/EventDrivenConnectorTemplate/Worker.cs
new file mode 100644
index 0000000000..e140dc4403
--- /dev/null
+++ b/dotnet/templates/content/EventDrivenConnectorTemplate/Worker.cs
@@ -0,0 +1,27 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace EventDrivenConnectorTemplate
+{
+ public class Worker : BackgroundService
+ {
+ private readonly ILogger _logger;
+
+ public Worker(ILogger 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);
+ }
+ }
+ }
+}
diff --git a/dotnet/templates/EventDrivenTelemetryConnector/appsettings.Development.json b/dotnet/templates/content/EventDrivenConnectorTemplate/appsettings.Development.json
similarity index 100%
rename from dotnet/templates/EventDrivenTelemetryConnector/appsettings.Development.json
rename to dotnet/templates/content/EventDrivenConnectorTemplate/appsettings.Development.json
diff --git a/dotnet/templates/EventDrivenTelemetryConnector/appsettings.json b/dotnet/templates/content/EventDrivenConnectorTemplate/appsettings.json
similarity index 100%
rename from dotnet/templates/EventDrivenTelemetryConnector/appsettings.json
rename to dotnet/templates/content/EventDrivenConnectorTemplate/appsettings.json
diff --git a/dotnet/templates/PollingTelemetryConnector/.template.config/template.json b/dotnet/templates/content/PollingConnectorTemplate/.template.config/template.json
similarity index 83%
rename from dotnet/templates/PollingTelemetryConnector/.template.config/template.json
rename to dotnet/templates/content/PollingConnectorTemplate/.template.config/template.json
index 2fa8beb702..0408c72e8d 100644
--- a/dotnet/templates/PollingTelemetryConnector/.template.config/template.json
+++ b/dotnet/templates/content/PollingConnectorTemplate/.template.config/template.json
@@ -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",
diff --git a/dotnet/templates/EventDrivenTelemetryConnector/EventDrivenTelemetryConnector.csproj b/dotnet/templates/content/PollingConnectorTemplate/Azure.Iot.Operations.Templates.PollingConnectorTemplate.csproj
similarity index 84%
rename from dotnet/templates/EventDrivenTelemetryConnector/EventDrivenTelemetryConnector.csproj
rename to dotnet/templates/content/PollingConnectorTemplate/Azure.Iot.Operations.Templates.PollingConnectorTemplate.csproj
index 4c4720298f..65119de126 100644
--- a/dotnet/templates/EventDrivenTelemetryConnector/EventDrivenTelemetryConnector.csproj
+++ b/dotnet/templates/content/PollingConnectorTemplate/Azure.Iot.Operations.Templates.PollingConnectorTemplate.csproj
@@ -1,4 +1,4 @@
-
+
net9.0
@@ -9,7 +9,6 @@
-
+
-
diff --git a/dotnet/templates/PollingTelemetryConnector/DatasetSampler.cs b/dotnet/templates/content/PollingConnectorTemplate/DatasetSampler.cs
similarity index 100%
rename from dotnet/templates/PollingTelemetryConnector/DatasetSampler.cs
rename to dotnet/templates/content/PollingConnectorTemplate/DatasetSampler.cs
diff --git a/dotnet/templates/PollingTelemetryConnector/DatasetSamplerProvider.cs b/dotnet/templates/content/PollingConnectorTemplate/DatasetSamplerProvider.cs
similarity index 62%
rename from dotnet/templates/PollingTelemetryConnector/DatasetSamplerProvider.cs
rename to dotnet/templates/content/PollingConnectorTemplate/DatasetSamplerProvider.cs
index 5b957b15d4..46c7e55d8b 100644
--- a/dotnet/templates/PollingTelemetryConnector/DatasetSamplerProvider.cs
+++ b/dotnet/templates/content/PollingConnectorTemplate/DatasetSamplerProvider.cs
@@ -7,6 +7,9 @@
namespace PollingTelemetryConnectorTemplate
{
+ ///
+ /// The factory for creating the samplers for each dataset.
+ ///
public class DatasetSamplerProvider : IDatasetSamplerFactory
{
public static Func Factory = service =>
@@ -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();
}
}
diff --git a/dotnet/templates/content/PollingConnectorTemplate/LeaderElectionConfigurationProvider.cs b/dotnet/templates/content/PollingConnectorTemplate/LeaderElectionConfigurationProvider.cs
new file mode 100644
index 0000000000..2fb3b5addf
--- /dev/null
+++ b/dotnet/templates/content/PollingConnectorTemplate/LeaderElectionConfigurationProvider.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Azure.Iot.Operations.Connector;
+
+namespace PollingTelemetryConnectorTemplate
+{
+ ///
+ /// Factory that provides all leader election configurations for this connector.
+ ///
+ ///
+ /// 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.
+ ///
+ public class LeaderElectionConfigurationProvider : IConnectorLeaderElectionConfigurationProvider
+ {
+ public static Func 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));
+ }
+ }
+}
diff --git a/dotnet/templates/PollingTelemetryConnector/MessageSchemaProvider.cs b/dotnet/templates/content/PollingConnectorTemplate/MessageSchemaProvider.cs
similarity index 68%
rename from dotnet/templates/PollingTelemetryConnector/MessageSchemaProvider.cs
rename to dotnet/templates/content/PollingConnectorTemplate/MessageSchemaProvider.cs
index 5b05c252bf..f5bbfb8f74 100644
--- a/dotnet/templates/PollingTelemetryConnector/MessageSchemaProvider.cs
+++ b/dotnet/templates/content/PollingConnectorTemplate/MessageSchemaProvider.cs
@@ -6,6 +6,15 @@
namespace PollingTelemetryConnectorTemplate
{
+ ///
+ /// The factory method for determining what message schema should be registered for and attached to each
+ /// emitted telemetry message for each dataset handled by this connector. If no message schema is needed,
+ /// then this class can be left as-is.
+ ///
+ ///
+ /// 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.
+ ///
internal class MessageSchemaProvider : IMessageSchemaProvider
{
public static Func Factory = service =>
diff --git a/dotnet/templates/PollingTelemetryConnector/Program.cs b/dotnet/templates/content/PollingConnectorTemplate/Program.cs
similarity index 76%
rename from dotnet/templates/PollingTelemetryConnector/Program.cs
rename to dotnet/templates/content/PollingConnectorTemplate/Program.cs
index 3cc6ad22f5..5babcb83d2 100644
--- a/dotnet/templates/PollingTelemetryConnector/Program.cs
+++ b/dotnet/templates/content/PollingConnectorTemplate/Program.cs
@@ -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 PollingTelemetryConnectorTemplate;
-string connectorClientId = Environment.GetEnvironmentVariable(ConnectorFileMountSettings.ConnectorClientIdEnvVar) ?? throw new InvalidOperationException("No MQTT client Id configured by Akri operator");
-
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
diff --git a/dotnet/templates/content/PollingConnectorTemplate/Worker.cs b/dotnet/templates/content/PollingConnectorTemplate/Worker.cs
new file mode 100644
index 0000000000..80e2283560
--- /dev/null
+++ b/dotnet/templates/content/PollingConnectorTemplate/Worker.cs
@@ -0,0 +1,27 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Azure.Iot.Operations.Templates.PollingConnectorTemplate
+{
+ public class Worker : BackgroundService
+ {
+ private readonly ILogger _logger;
+
+ public Worker(ILogger 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);
+ }
+ }
+ }
+}
diff --git a/dotnet/templates/PollingTelemetryConnector/appsettings.Development.json b/dotnet/templates/content/PollingConnectorTemplate/appsettings.Development.json
similarity index 100%
rename from dotnet/templates/PollingTelemetryConnector/appsettings.Development.json
rename to dotnet/templates/content/PollingConnectorTemplate/appsettings.Development.json
diff --git a/dotnet/templates/PollingTelemetryConnector/appsettings.json b/dotnet/templates/content/PollingConnectorTemplate/appsettings.json
similarity index 100%
rename from dotnet/templates/PollingTelemetryConnector/appsettings.json
rename to dotnet/templates/content/PollingConnectorTemplate/appsettings.json