{"id":13629608,"url":"https://github.com/alonf/IoTHubClientGenerator","last_synced_at":"2025-04-17T09:35:09.883Z","repository":{"id":48950048,"uuid":"322324531","full_name":"alonf/IoTHubClientGenerator","owner":"alonf","description":"C# Source Generator for IoTHub C# Client","archived":false,"fork":false,"pushed_at":"2023-09-09T15:26:25.000Z","size":957,"stargazers_count":17,"open_issues_count":2,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-08-01T22:44:01.624Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alonf.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-12-17T14:46:29.000Z","updated_at":"2024-04-18T22:28:35.000Z","dependencies_parsed_at":"2024-01-06T02:09:59.003Z","dependency_job_id":"c33aa832-14a9-468b-8be7-44906f06fdca","html_url":"https://github.com/alonf/IoTHubClientGenerator","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alonf%2FIoTHubClientGenerator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alonf%2FIoTHubClientGenerator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alonf%2FIoTHubClientGenerator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alonf%2FIoTHubClientGenerator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alonf","download_url":"https://codeload.github.com/alonf/IoTHubClientGenerator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223751289,"owners_count":17196603,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T22:01:14.775Z","updated_at":"2024-11-08T20:31:25.576Z","avatar_url":"https://github.com/alonf.png","language":"C#","readme":"# IoT Hub Client C# code generator.\n\nInstallation: use the [NuGet package](https://www.nuget.org/packages/IoTHubClientGenerator/)  \nTo get started, follow this [walk-through](Doc/Text/Walkthrough.md)\n\n\nThis project takes advantage of the new C# 9.0 ability to have a code generation as part of the C# code compilation process. With this code generator, you can build an IoT Device client program in seconds. For example, the following code creates a device client that can send telemetry, receive commands, update twin reported property, get desired twin properties updates, get the current connection state, and handle direct method calls:\n\n```\nnamespace EasyIoTHubClient\n{\n    [IoTHub(GeneratedSendMethodName = \"SendAsync\")]\n    partial class IoTDemo\n    {\n        [Reported(\"BatteryLevel\")] private string _batteryLevel;\n\n        [Desired] private int ReportingFrequencyInHz { get; set; } = 1;\n\n        static async Task Main(string[] args)\n        {\n            var iotDemo = new IoTDemo();\n            await iotDemo.InitIoTHubClientAsync();\n            iotDemo.BatteryLevel = \"100%\";\n            await iotDemo.SendDataAsync();\n        }\n\n        private async Task SendDataAsync()\n        {\n            for (int i = 1000; i \u003e= 0; --i)\n            {\n                BatteryLevel = $\"{i % 100}%\";\n                await SendAsync($\"{{\\\"data\\\":\\\"{i}\\\"\", i.ToString(), new CancellationToken());\n                await Task.Delay(TimeSpan.FromMilliseconds(1000.0 / ReportingFrequencyInHz));\n            }\n        }\n\n        [C2DMessage(AutoComplete = true)]\n        private void Cloud2DeviceMessage(Message receivedMessage)\n        {\n            string messageData = Encoding.ASCII.GetString(receivedMessage.GetBytes());\n            Console.WriteLine($\"Received message: [{messageData}]\");\n        }\n\n        [DirectMethod]\n        private Task\u003cMethodResponse\u003e EchoAsync(MethodRequest request)\n        {\n            var response = new MethodResponse(request.Data, 200);\n            return Task.FromResult(response);\n        }\n\n\n        [ConnectionStatus]\n        private (ConnectionStatus Status, ConnectionStatusChangeReason Reason) DeviceConnectionStatus { get; set; }\n        \n        [IoTHubErrorHandler]\n        void IoTHubErrorHandler(string errorMessage, Exception exception)\n        {\n            Console.WriteLine($\"{errorMessage}, Exception: {exception.Message}\");\n        }\n    }\n}\n```\n\n## Advanced Features\nYou may use one of the ```[Device]``` or the ```[DPS*]``` attributes to decorate a ```DeviceClient``` property. With these attributes and their properties, we can manipulate the IoT Hub device client creation parameters.\nEach property value can be set as a text or can be set as an environment variable value by wrapping the value with the `````%````` character, for example:\n```\n[Device(ConnectionString=\"%ConStr%\")]\nDeviceClient MyClient {get;set;}\n```\nEach property value can be set as a variable name or code expression by wrapping the value with the `````[varName]````` character, for example:\n```\n[Device(ConnectionString=\"[ConStr]\")]\nDeviceClient MyClient {get;set;}\n```\nThe ```[Device]``` attribute has a long list of properties and a set of other attributes (```[ClientOptions]```, ```[TransportSetting]```, and ```[AuthenticationMethod]```)  that creates the parameter of the IoT device client Create method. The code generator chooses the correct overload version of the device client ```Create()``` function by collecting all these parameters and selecting the suitable function version. If there is a missing parameter or a collision between parameters, the code generator emits an error.\nExample of non-trivial device creation:\n\n```\n    [Device(ConnectionString = \"%conString%\", DeviceId = \"%deviceId%\")]\n    public DeviceClient DeviceClient { get; set; }\n\n    [TransportSetting]\n    public ITransportSettings AmqpTransportSettings { get; } = new AmqpTransportSettings(TransportType.Amqp)\n    {\n        AmqpConnectionPoolSettings = new AmqpConnectionPoolSettings {MaxPoolSize = 5}, IdleTimeout = TimeSpan.FromMinutes(1)\n    };\n\n    [TransportSetting]\n    public ITransportSettings MqttTransportSetting { get; } = new MqttTransportSettings(TransportType.Mqtt)\n    {\n        DefaultReceiveTimeout = TimeSpan.FromMinutes(2)\n    };\n\n    [ClientOptions]\n    public ClientOptions ClientOptions { get; } = new();\n```\nThe following code is the result of the example:\n```\nprivate Microsoft.Azure.Devices.Client.DeviceClient CreateDeviceClient()\n{\n    var theConnectionString = System.Environment.GetEnvironmentVariable(\"conString\");\n    var theDeviceId = System.Environment.GetEnvironmentVariable(\"deviceId\");\n    ITransportSettings[] transportSettings = new[]{AmqpTransportSettings, MqttTransportSetting};\n    var deviceClient = DeviceClient.CreateFromConnectionString(theConnectionString, theDeviceId, transportSettings, ClientOptions);\n    return deviceClient;\n}\n```\nOr if you want to set the authentication method:\n```\n    [Device(Hostname = \"%hostName%\", TransportType = TransportType.Mqtt)]\n    public DeviceClient DeviceClient { get; set; }\n\n    [AuthenticationMethod]\n    public IAuthenticationMethod DeviceAuthenticationWithRegistrySymmetricKey { get; } = new DeviceAuthenticationWithRegistrySymmetricKey(\"deviceId\", \"key\");\n```\nAnd the result generated code is:\n```\nprivate Microsoft.Azure.Devices.Client.DeviceClient CreateDeviceClient()\n{\n    var theHostname = System.Environment.GetEnvironmentVariable(\"hostName\");\n    var theTransportType = TransportType.Mqtt;\n    var deviceClient = DeviceClient.Create(theHostname, DeviceAuthenticationWithRegistrySymmetricKey, theTransportType);\n    return deviceClient;\n}\n```\nTo use the Device Provisioning Service of Azure IoT, decorate the Device Client property with one of ```[DpsSymmetricKeyDevice]```, ```[DpsTpmDevice]```, ```[DpsX509CertificateDevice]```\n\nExample:\n```\n        [DpsSymmetricKeyDevice(DPSIdScope=\"scope\", DPSTransportType=TransportType.Mqtt, TransportType=TransportType.Mqtt,\n            EnrollmentGroupId=\"%EnrollmentGroupId%\", EnrollmentType=DPSEnrollmentType.Group, \n            Id=\"%RegistrationId%\", PrimarySymmetricKey=\"%SymKey%\")]\n        public DeviceClient DeviceClient { get; set; }\n```\nTo compile the code, we need to add the NuGet Packages: ```Microsoft.Azure.Devices.Provisioning.Client``` and ```Microsoft.Azure.Devices.Provisioning.Transport.Mqtt```\n\nThe resulting generated code:\n```\n    private async Task\u003cMicrosoft.Azure.Devices.Client.DeviceClient\u003e CreateDeviceClientAsync()\n    {\n        var theDPSIdScope = \"scope\";\n        var theDPSTransportType = TransportType.Mqtt;\n        var theTransportType = TransportType.Mqtt;\n        var theEnrollmentGroupId = System.Environment.GetEnvironmentVariable(\"EnrollmentGroupId\");\n        var theEnrollmentType = DPSEnrollmentType.Group;\n        var theId = System.Environment.GetEnvironmentVariable(\"RegistrationId\");\n        var thePrimarySymmetricKey = System.Environment.GetEnvironmentVariable(\"SymKey\");\n        using var security = new SecurityProviderSymmetricKey(theId, thePrimarySymmetricKey, null);\n        using var transport = new ProvisioningTransportHandlerMqtt();\n        var theGlobalDeviceEndpoint = \"global.azure-devices-provisioning.net\";\n        ProvisioningDeviceClient provClient = ProvisioningDeviceClient.Create(theGlobalDeviceEndpoint, theDPSIdScope, security, transport);\n        DeviceRegistrationResult result = await provClient.RegisterAsync();\n        if (result.Status != ProvisioningRegistrationStatusType.Assigned)\n        {\n            throw new Exception($\"Registration status did not assign a hub, status: {result.Status}\");\n        }\n\n        IAuthenticationMethod auth = new DeviceAuthenticationWithRegistrySymmetricKey(result.DeviceId, security.GetPrimaryKey());\n        var deviceClient = DeviceClient.Create(result.AssignedHub, auth, theTransportType);\n        return deviceClient;\n    }\n```\n\n## IoTHubClientGeneratorSDK Namespace\n### Classes\n- [AuthenticationMethodAttribute](/Doc/AutoGenerated/IoTHubClientGeneratorSDK-AuthenticationMethodAttribute.md 'IoTHubClientGeneratorSDK.AuthenticationMethodAttribute')\n- [C2DMessageAttribute](/Doc/AutoGenerated/IotHubClientGeneratorSDK/Doc/AutoGenerated/IoTHubClientGeneratorSDK-C2DMessageAttribute.md 'IoTHubClientGeneratorSDK.C2DMessageAttribute')\n- [ClientOptionsAttribute](/Doc/AutoGenerated/IoTHubClientGeneratorSDK-ClientOptionsAttribute.md 'IoTHubClientGeneratorSDK.ClientOptionsAttribute')\n- [ConnectionStatusAttribute](/Doc/AutoGenerated/IoTHubClientGeneratorSDK-ConnectionStatusAttribute.md 'IoTHubClientGeneratorSDK.ConnectionStatusAttribute')\n- [DesiredAttribute](/Doc/AutoGenerated/IoTHubClientGeneratorSDK-DesiredAttribute.md 'IoTHubClientGeneratorSDK.DesiredAttribute')\n- [DeviceAttribute](/Doc/AutoGenerated/IoTHubClientGeneratorSDK-DeviceAttribute.md 'IoTHubClientGeneratorSDK.DeviceAttribute')\n- [DirectMethodAttribute](/Doc/AutoGenerated/IoTHubClientGeneratorSDK-DirectMethodAttribute.md 'IoTHubClientGeneratorSDK.DirectMethodAttribute')\n- [DpsDeviceAttribute](/Doc/AutoGenerated/IoTHubClientGeneratorSDK-DpsDeviceAttribute.md 'IoTHubClientGeneratorSDK.DpsDeviceAttribute')\n- [DpsSymmetricKeyDeviceAttribute](/Doc/AutoGenerated/IoTHubClientGeneratorSDK-DpsSymmetricKeyDeviceAttribute.md 'IoTHubClientGeneratorSDK.DpsSymmetricKeyDeviceAttribute')\n- [DpsTpmDeviceAttribute](/Doc/AutoGenerated/IoTHubClientGeneratorSDK-DpsTpmDeviceAttribute.md 'IoTHubClientGeneratorSDK.DpsTpmDeviceAttribute')\n- [DpsX509CertificateDeviceAttribute](/Doc/AutoGenerated/IoTHubClientGeneratorSDK-DpsX509CertificateDeviceAttribute.md 'IoTHubClientGeneratorSDK.DpsX509CertificateDeviceAttribute')\n- [IoTHubAttribute](/Doc/AutoGenerated/IoTHubClientGeneratorSDK-IoTHubAttribute.md 'IoTHubClientGeneratorSDK.IoTHubAttribute')\n- [IoTHubDeviceStatusChangesHandlerAttribute](/Doc/AutoGenerated/IoTHubClientGeneratorSDK-IoTHubDeviceStatusChangesHandlerAttribute.md 'IoTHubClientGeneratorSDK.IoTHubDeviceStatusChangesHandlerAttribute')\n- [IoTHubErrorHandlerAttribute](/Doc/AutoGenerated/IoTHubClientGeneratorSDK-IoTHubErrorHandlerAttribute.md 'IoTHubClientGeneratorSDK.IoTHubErrorHandlerAttribute')\n- [ReportedAttribute](/Doc/AutoGenerated/IoTHubClientGeneratorSDK-ReportedAttribute.md 'IoTHubClientGeneratorSDK.ReportedAttribute')\n- [TransportSettingAttribute](/Doc/AutoGenerated/IoTHubClientGeneratorSDK-TransportSettingAttribute.md 'IoTHubClientGeneratorSDK.TransportSettingAttribute')\n### Enums\n- [DPSEnrollmentType](/Doc/AutoGenerated/IoTHubClientGeneratorSDK-DPSEnrollmentType.md 'IoTHubClientGeneratorSDK.DPSEnrollmentType')\n\n\n\n## Missing features and known issues:\n- Move some of the implementation to rely on the semantic data and not the syntax tree, it will solve several issues such as spaces around =\n- Have a separate error handler for each attribute instead (or as override rule) of one global handler\n- Add the ability for the user to provide the ```MessageSchema``` ```ContentType``` and ```ContentEncoding``` to the send-telemetry method in compile and at runtime\n- Have the ability to postponed update of reported properties, and only after setting a group of them, ask for a batch update of all\n- Add support for:\n  - File Uploads\n  - Device Modules\n  - Device Streams  \n\n","funding_links":[],"categories":["Source Generators","Do not want to test 112 ( old ISourceGenerator )"],"sub_categories":["Communication","1. [ThisAssembly](https://ignatandrei.github.io/RSCG_Examples/v2/docs/ThisAssembly) , in the [EnhancementProject](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#enhancementproject) category"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falonf%2FIoTHubClientGenerator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falonf%2FIoTHubClientGenerator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falonf%2FIoTHubClientGenerator/lists"}