├── .editorconfig ├── README.md ├── docs └── media │ └── docs-link-buttons │ ├── azure-documentation.svg │ ├── azure-how-to-guide.svg │ ├── azure-quickstart.svg │ └── azure-tutorial.svg ├── helpers └── ColorConsoleLogger │ ├── ColorConsoleLogger.cs │ ├── ColorConsoleLogger.csproj │ ├── ColorConsoleLoggerConfiguration.cs │ ├── ColorConsoleLoggerExtensions.cs │ ├── ColorConsoleLoggerProvider.cs │ └── ConsoleEventListener.cs ├── horizontal-arm ├── arm-read-write.sln ├── arm-read-write │ ├── Program.cs │ └── arm-read-write.csproj ├── arm-template │ └── template_iothub.json └── testenvvars_SET.cmd ├── iot-hub ├── Quickstarts │ ├── InvokeDeviceMethod │ │ └── readme.md │ ├── ReadD2cMessages │ │ └── README.md │ ├── SimulatedDevice │ │ └── readme.md │ └── SimulatedDeviceWithCommand │ │ └── readme.md ├── Samples │ ├── device │ │ ├── DeviceReconnectionSample │ │ │ └── readme.md │ │ ├── FileUploadSample │ │ │ └── readme.md │ │ ├── MessageReceiveSample │ │ │ └── readme.md │ │ ├── MethodSample │ │ │ └── readme.md │ │ ├── PnpDeviceSamples │ │ │ └── readme.md │ │ ├── TwinSample │ │ │ └── readme.md │ │ ├── X509DeviceCertWithChainSample │ │ │ └── readme.md │ │ └── XamarinSample │ │ │ └── readme.md │ ├── module │ │ └── ModuleSample │ │ │ └── readme.md │ └── service │ │ ├── AutomaticDeviceManagementSample │ │ └── readme.md │ │ ├── AzureSasCredentialAuthenticationSample │ │ └── readme.md │ │ ├── CleanupDevicesSample │ │ └── readme.md │ │ ├── DigitalTwinClientSamples │ │ └── readme.md │ │ ├── EdgeDeploymentSample │ │ └── readme.md │ │ ├── FileUploadNotificationReceiverSample │ │ └── readme.md │ │ ├── ImportExportDevicesSample │ │ └── readme.md │ │ ├── ImportExportDevicesWithManagedIdentitySample │ │ └── readme.md │ │ ├── JobsSample │ │ └── readme.md │ │ ├── PnpServiceSamples │ │ └── readme.md │ │ ├── RegistryManagerSample │ │ └── readme.md │ │ ├── RoleBasedAuthenticationSample │ │ └── readme.md │ │ └── ServiceClientSample │ │ └── readme.md └── Tutorials │ └── Routing │ ├── IoT_SimulatedDevice.sln │ └── SimulatedDevice │ ├── Parameters.cs │ ├── Program.cs │ ├── SimulatedDevice.csproj │ └── resources │ ├── iothub_msgenrichment_cli.azcli │ ├── iothub_routing_cli.azcli │ ├── iothub_routing_psh.ps1 │ ├── template_iothub.json │ ├── template_iothub_parameters.json │ └── template_messageenrichments.json ├── nuget.config ├── provisioning └── Samples │ ├── device │ ├── ComputeDerivedSymmetricKeySample │ │ └── readme.md │ ├── SymmetricKeySample │ │ └── readme.md │ ├── TpmSample │ │ └── readme.md │ ├── X509Sample │ │ └── readme.md │ └── readme.md │ └── service │ ├── BulkOperationSample │ └── readme.md │ ├── CleanupEnrollmentsSample │ └── readme.md │ ├── EnrollmentGroupSample │ └── readme.md │ ├── EnrollmentSample │ └── readme.md │ └── GroupCertificateVerificationSample │ └── readme.md └── vsts ├── CredScanSuppressions.json └── vsts.yaml /.editorconfig: -------------------------------------------------------------------------------- 1 | # Remove the line below if you want to inherit .editorconfig settings from higher directories 2 | root = true 3 | 4 | # C# files 5 | [*.cs] 6 | 7 | #### Core EditorConfig Options #### 8 | 9 | # Indentation and spacing 10 | indent_size = 4 11 | indent_style = space 12 | tab_width = 4 13 | 14 | # New line preferences 15 | end_of_line = crlf 16 | insert_final_newline = false 17 | 18 | #### .NET Coding Conventions #### 19 | 20 | # Organize usings 21 | dotnet_separate_import_directive_groups = false 22 | dotnet_sort_system_directives_first = true 23 | 24 | # this. and Me. preferences 25 | dotnet_style_qualification_for_event = false:suggestion 26 | dotnet_style_qualification_for_field = false:suggestion 27 | dotnet_style_qualification_for_method = false:suggestion 28 | dotnet_style_qualification_for_property = false:suggestion 29 | 30 | # Language keywords vs BCL types preferences 31 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion 32 | dotnet_style_predefined_type_for_member_access = true:suggestion 33 | 34 | # Parentheses preferences 35 | dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:suggestion 36 | dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:suggestion 37 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion 38 | dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:suggestion 39 | 40 | # Modifier preferences 41 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion 42 | 43 | # Expression-level preferences 44 | dotnet_style_coalesce_expression = true:suggestion 45 | dotnet_style_collection_initializer = true:suggestion 46 | dotnet_style_explicit_tuple_names = true:suggestion 47 | dotnet_style_null_propagation = true:suggestion 48 | dotnet_style_object_initializer = true:suggestion 49 | dotnet_style_prefer_auto_properties = true:suggestion 50 | dotnet_style_prefer_compound_assignment = true:suggestion 51 | dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion 52 | dotnet_style_prefer_conditional_expression_over_return = true:suggestion 53 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion 54 | dotnet_style_prefer_inferred_tuple_names = true:suggestion 55 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion 56 | 57 | # Field preferences 58 | dotnet_style_readonly_field = true:suggestion 59 | 60 | # Parameter preferences 61 | dotnet_code_quality_unused_parameters = all:suggestion 62 | 63 | #### C# Coding Conventions #### 64 | 65 | # var preferences 66 | csharp_style_var_elsewhere = false:suggestion 67 | csharp_style_var_for_built_in_types = false:suggestion 68 | csharp_style_var_when_type_is_apparent = true:suggestion 69 | 70 | # Expression-bodied members 71 | csharp_style_expression_bodied_accessors = true:suggestion 72 | csharp_style_expression_bodied_constructors = false:silent 73 | csharp_style_expression_bodied_indexers = true:silent 74 | csharp_style_expression_bodied_lambdas = true:silent 75 | csharp_style_expression_bodied_local_functions = false:silent 76 | csharp_style_expression_bodied_methods = false:silent 77 | csharp_style_expression_bodied_operators = false:silent 78 | csharp_style_expression_bodied_properties = true:suggestion 79 | 80 | # Pattern matching preferences 81 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion 82 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion 83 | csharp_style_prefer_switch_expression = true:suggestion 84 | 85 | # Null-checking preferences 86 | csharp_style_conditional_delegate_call = true:suggestion 87 | 88 | # Modifier preferences 89 | csharp_prefer_static_local_function = true:suggestion 90 | csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async 91 | 92 | # Code-block preferences 93 | csharp_prefer_braces = true:suggestion 94 | csharp_prefer_simple_using_statement = true:suggestion 95 | 96 | # Expression-level preferences 97 | csharp_prefer_simple_default_expression = true:suggestion 98 | csharp_style_deconstructed_variable_declaration = true:suggestion 99 | csharp_style_inlined_variable_declaration = true:suggestion 100 | csharp_style_pattern_local_over_anonymous_function = true:suggestion 101 | csharp_style_prefer_index_operator = true:suggestion 102 | csharp_style_prefer_range_operator = true:suggestion 103 | csharp_style_throw_expression = true:suggestion 104 | csharp_style_unused_value_assignment_preference = discard_variable:suggestion 105 | csharp_style_unused_value_expression_statement_preference = discard_variable:silent 106 | 107 | # 'using' directive preferences 108 | csharp_using_directive_placement = outside_namespace:suggestion 109 | 110 | #### C# Formatting Rules #### 111 | 112 | # New line preferences 113 | csharp_new_line_before_catch = true 114 | csharp_new_line_before_else = true 115 | csharp_new_line_before_finally = true 116 | csharp_new_line_before_members_in_anonymous_types = true 117 | csharp_new_line_before_members_in_object_initializers = true 118 | csharp_new_line_before_open_brace = all 119 | csharp_new_line_between_query_expression_clauses = true 120 | 121 | # Indentation preferences 122 | csharp_indent_block_contents = true 123 | csharp_indent_braces = false 124 | csharp_indent_case_contents = true 125 | csharp_indent_case_contents_when_block = true 126 | csharp_indent_labels = flush_left 127 | csharp_indent_switch_labels = true 128 | 129 | # Space preferences 130 | csharp_space_after_cast = false 131 | csharp_space_after_colon_in_inheritance_clause = true 132 | csharp_space_after_comma = true 133 | csharp_space_after_dot = false 134 | csharp_space_after_keywords_in_control_flow_statements = true 135 | csharp_space_after_semicolon_in_for_statement = true 136 | csharp_space_around_binary_operators = before_and_after 137 | csharp_space_around_declaration_statements = false 138 | csharp_space_before_colon_in_inheritance_clause = true 139 | csharp_space_before_comma = false 140 | csharp_space_before_dot = false 141 | csharp_space_before_open_square_brackets = false 142 | csharp_space_before_semicolon_in_for_statement = false 143 | csharp_space_between_empty_square_brackets = false 144 | csharp_space_between_method_call_empty_parameter_list_parentheses = false 145 | csharp_space_between_method_call_name_and_opening_parenthesis = false 146 | csharp_space_between_method_call_parameter_list_parentheses = false 147 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false 148 | csharp_space_between_method_declaration_name_and_open_parenthesis = false 149 | csharp_space_between_method_declaration_parameter_list_parentheses = false 150 | csharp_space_between_parentheses = false 151 | csharp_space_between_square_brackets = false 152 | 153 | # Wrapping preferences 154 | csharp_preserve_single_line_blocks = true 155 | csharp_preserve_single_line_statements = true 156 | 157 | #### Naming styles #### 158 | 159 | # Naming rules 160 | 161 | dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion 162 | dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface 163 | dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i 164 | 165 | dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion 166 | dotnet_naming_rule.types_should_be_pascal_case.symbols = types 167 | dotnet_naming_rule.types_should_be_pascal_case.style = non_private_static_field_style 168 | 169 | dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion 170 | dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members 171 | dotnet_naming_rule.non_field_members_should_be_pascal_case.style = non_private_static_field_style 172 | 173 | dotnet_naming_rule.public_members_must_be_capitalized.symbols = public_symbols 174 | dotnet_naming_symbols.public_symbols.applicable_kinds = property,method,field,event,delegate 175 | dotnet_naming_symbols.public_symbols.applicable_accessibilities = public 176 | dotnet_naming_symbols.public_symbols.required_modifiers = readonly 177 | dotnet_naming_rule.public_members_must_be_capitalized.style = first_word_upper_case_style 178 | dotnet_naming_style.first_word_upper_case_style.capitalization = first_word_upper 179 | 180 | dotnet_naming_rule.public_members_must_be_capitalized.severity = suggestion 181 | 182 | # Non-private static fields are PascalCase 183 | dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = suggestion 184 | dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields 185 | dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style 186 | 187 | dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field 188 | dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected 189 | dotnet_naming_symbols.non_private_static_fields.required_modifiers = static 190 | 191 | dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case 192 | 193 | # Non-private readonly fields are PascalCase 194 | dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = suggestion 195 | dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields 196 | dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_static_field_style 197 | 198 | dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field 199 | dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected 200 | dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly 201 | 202 | dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case 203 | 204 | # Constants are PascalCase 205 | dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion 206 | dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants 207 | dotnet_naming_rule.constants_should_be_pascal_case.style = non_private_static_field_style 208 | 209 | dotnet_naming_symbols.constants.applicable_kinds = field 210 | dotnet_naming_symbols.constants.required_modifiers = const 211 | 212 | dotnet_naming_style.constant_style.capitalization = pascal_case 213 | 214 | # Static fields are camelCase and start with s_ 215 | dotnet_naming_rule.static_fields_should_be_camel_case.severity = suggestion 216 | dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields 217 | dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style 218 | 219 | dotnet_naming_symbols.static_fields.applicable_kinds = field 220 | dotnet_naming_symbols.static_fields.required_modifiers = static 221 | 222 | dotnet_naming_style.static_field_style.capitalization = camel_case 223 | dotnet_naming_style.static_field_style.required_prefix = s_ 224 | 225 | # Instance fields are camelCase and start with _ 226 | dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion 227 | dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields 228 | dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style 229 | 230 | dotnet_naming_symbols.instance_fields.applicable_kinds = field 231 | 232 | dotnet_naming_style.instance_field_style.capitalization = camel_case 233 | dotnet_naming_style.instance_field_style.required_prefix = _ 234 | 235 | # Locals and parameters are camelCase 236 | dotnet_naming_rule.locals_should_be_camel_case.severity = suggestion 237 | dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters 238 | dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style 239 | 240 | dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local 241 | 242 | dotnet_naming_style.camel_case_style.capitalization = camel_case 243 | 244 | # Local functions are PascalCase 245 | dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion 246 | dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions 247 | dotnet_naming_rule.local_functions_should_be_pascal_case.style = non_private_static_field_style 248 | 249 | dotnet_naming_symbols.local_functions.applicable_kinds = local_function 250 | 251 | dotnet_naming_style.local_function_style.capitalization = pascal_case 252 | 253 | # By default, name items with PascalCase 254 | dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion 255 | dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members 256 | dotnet_naming_rule.members_should_be_pascal_case.style = non_private_static_field_style 257 | 258 | dotnet_naming_symbols.all_members.applicable_kinds = * 259 | 260 | dotnet_naming_style.pascal_case_style.capitalization = pascal_case 261 | 262 | # Symbol specifications 263 | 264 | dotnet_naming_symbols.interface.applicable_kinds = interface 265 | dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected 266 | dotnet_naming_symbols.interface.required_modifiers = 267 | 268 | dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum 269 | dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected 270 | dotnet_naming_symbols.types.required_modifiers = 271 | 272 | dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method 273 | dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected 274 | dotnet_naming_symbols.non_field_members.required_modifiers = 275 | 276 | # Naming styles 277 | 278 | dotnet_naming_style.pascal_case.required_prefix = 279 | dotnet_naming_style.pascal_case.required_suffix = 280 | dotnet_naming_style.pascal_case.word_separator = 281 | dotnet_naming_style.pascal_case.capitalization = pascal_case 282 | 283 | dotnet_naming_style.begins_with_i.required_prefix = I 284 | dotnet_naming_style.begins_with_i.required_suffix = 285 | dotnet_naming_style.begins_with_i.word_separator = 286 | dotnet_naming_style.begins_with_i.capitalization = pascal_case 287 | 288 | # Async methods should have "Async" suffix 289 | dotnet_naming_rule.async_methods_end_in_async.symbols = any_async_methods 290 | dotnet_naming_rule.async_methods_end_in_async.style = end_in_async 291 | dotnet_naming_rule.async_methods_end_in_async.severity = suggestion 292 | 293 | dotnet_naming_symbols.any_async_methods.applicable_kinds = method 294 | dotnet_naming_symbols.any_async_methods.applicable_accessibilities = * 295 | dotnet_naming_symbols.any_async_methods.required_modifiers = async 296 | 297 | dotnet_naming_style.end_in_async.required_prefix = 298 | dotnet_naming_style.end_in_async.required_suffix = Async 299 | dotnet_naming_style.end_in_async.capitalization = pascal_case 300 | dotnet_naming_style.end_in_async.word_separator = 301 | 302 | # Exclude extension method 'this' parameter 303 | # 304 | # For all methods the default behaivor of the analyzer is to check to see if any argument is being 305 | # used without a null check (this is good). However, for extension methods, this means that 306 | # the "this" argument to the extension method is checked alongside of the other arguments. 307 | # 308 | # This is not great behavior as an extension method should behave like an instance method and we should 309 | # allow a NullRefException be generated if we attempt to access the "this" object. 310 | # 311 | # This flag ignores all of the "this" arguments but still reports the others. 312 | dotnet_code_quality.CA1062.exclude_extension_method_this_parameter = true 313 | 314 | 315 | # All of these severity changes below were because of an upgrade to the 3.3.1 analyzers which turned them 316 | # from warnings to errors. As we fix these warnings we should remove these lines to allow the default behaivor 317 | # and break the build. 318 | # CA2016: Forward the 'CancellationToken' parameter to methods that take one 319 | dotnet_diagnostic.CA2016.severity = warning 320 | # CA1805: Do not initialize unnecessarily 321 | dotnet_diagnostic.CA1805.severity = warning 322 | # CA1834: Consider using 'StringBuilder.Append(char)' when applicable 323 | dotnet_diagnostic.CA1834.severity = warning 324 | # CA2000: Dispose objects before losing scope 325 | dotnet_diagnostic.CA2000.severity = warning 326 | 327 | # CA2208: Instantiate argument exceptions correctly 328 | # CA2208 is suggesting that the argument that is passed to ArgumentNullException should match a name of a parameter 329 | # in the signature of the method that is throwing the exception. However, many of the CA2208 warning instances is 330 | # because the code throws an ArgumentNullException while passing in a property (or a field) on the object that is 331 | # passed into the method that is throwing the exception. A proper fix for this would be to throw an ArgumentException 332 | # instead. However, many of these instances are of a public method. So changing the exception being thrown is a breaking change. 333 | dotnet_diagnostic.CA2208.severity = suggestion 334 | csharp_style_namespace_declarations = block_scoped:silent 335 | csharp_style_prefer_method_group_conversion = true:silent 336 | [*.{cs,vb}] 337 | dotnet_style_operator_placement_when_wrapping = beginning_of_line 338 | tab_width = 4 339 | indent_size = 4 340 | end_of_line = crlf 341 | dotnet_style_coalesce_expression = true:suggestion 342 | dotnet_style_null_propagation = true:suggestion 343 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion 344 | dotnet_style_prefer_auto_properties = true:suggestion 345 | dotnet_style_object_initializer = true:suggestion 346 | dotnet_style_collection_initializer = true:suggestion 347 | dotnet_style_prefer_simplified_boolean_expressions = true:suggestion 348 | dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion 349 | dotnet_style_prefer_conditional_expression_over_return = true:suggestion 350 | dotnet_style_explicit_tuple_names = true:suggestion 351 | dotnet_style_prefer_inferred_tuple_names = true:suggestion 352 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion 353 | dotnet_style_prefer_compound_assignment = true:suggestion -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### All samples have been [moved](https://github.com/Azure/azure-iot-sdk-csharp#samples) to the main [Azure IoT SDK for C#](https://github.com/Azure/azure-iot-sdk-csharp) Repository -------------------------------------------------------------------------------- /docs/media/docs-link-buttons/azure-documentation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /docs/media/docs-link-buttons/azure-how-to-guide.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /docs/media/docs-link-buttons/azure-quickstart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /docs/media/docs-link-buttons/azure-tutorial.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /helpers/ColorConsoleLogger/ColorConsoleLogger.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Extensions.Logging; 5 | using System; 6 | using System.Globalization; 7 | using System.Linq; 8 | 9 | namespace Microsoft.Azure.Devices.Logging 10 | { 11 | /// 12 | /// The ILogger implementation for writing color log entries to console. 13 | /// For additional details, see https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.ilogger?view=dotnet-plat-ext-3.1. 14 | /// 15 | public class ColorConsoleLogger : ILogger 16 | { 17 | private readonly ColorConsoleLoggerConfiguration _config; 18 | 19 | /// 20 | /// Initializes an instance of . 21 | /// 22 | /// The settings to be used for logging. 23 | public ColorConsoleLogger(ColorConsoleLoggerConfiguration config) 24 | { 25 | _config = config; 26 | } 27 | 28 | /// 29 | /// Begin a group of logical operations. 30 | /// 31 | /// The type of the state to begin scope for. 32 | /// The identifier for the scope. 33 | public IDisposable BeginScope(TState state) 34 | { 35 | throw new NotImplementedException(); 36 | } 37 | 38 | /// 39 | /// Checks if the given log level is enabled. 40 | /// 41 | /// The log level to be checked. 42 | public bool IsEnabled(LogLevel logLevel) 43 | { 44 | return logLevel >= _config.MinLogLevel; 45 | } 46 | 47 | /// 48 | /// Writes the log entry to console output. 49 | /// 50 | /// The type of the object to be written. 51 | /// The log level of the log entry to be written. 52 | /// The event Id of the log entry to be written. 53 | /// The log entry to be written. 54 | /// The exception related to the log entry. 55 | /// The formatter to be used for formatting the log message. 56 | public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) 57 | { 58 | if (!IsEnabled(logLevel)) 59 | { 60 | return; 61 | } 62 | 63 | var color = _config.LogLevelToColorMapping[logLevel]; 64 | if (_config.EventIds.Contains(ColorConsoleLoggerConfiguration.DefaultEventId) || _config.EventIds.Contains(eventId.Id)) 65 | { 66 | ConsoleColor initialColor = Console.ForegroundColor; 67 | 68 | Console.ForegroundColor = ConsoleColor.Green; 69 | Console.Write($"{DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffffff", CultureInfo.InvariantCulture)}>> "); 70 | 71 | Console.ForegroundColor = color; 72 | Console.WriteLine($"{logLevel} - {formatter(state, exception)}"); 73 | Console.ForegroundColor = initialColor; 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /helpers/ColorConsoleLogger/ColorConsoleLogger.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /helpers/ColorConsoleLogger/ColorConsoleLoggerConfiguration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Extensions.Logging; 5 | using System; 6 | using System.Collections.Generic; 7 | 8 | namespace Microsoft.Azure.Devices.Logging 9 | { 10 | /// 11 | /// A color console logger configuration that creates different color console entries per log level, sets the default log level to Information and logs all events. 12 | /// 13 | public class ColorConsoleLoggerConfiguration 14 | { 15 | // If the EventId is set to 0, the logger will log all events. 16 | internal const int DefaultEventId = 0; 17 | 18 | /// 19 | /// A dictionary containing the log level to console color mappings to be used while writing log entries to the console. 20 | /// 21 | public IReadOnlyDictionary LogLevelToColorMapping { get; } = new Dictionary 22 | { 23 | { LogLevel.Trace, ConsoleColor.Blue }, 24 | { LogLevel.Debug, ConsoleColor.DarkYellow }, 25 | { LogLevel.Information, ConsoleColor.Cyan }, 26 | { LogLevel.Warning, ConsoleColor.DarkMagenta }, 27 | { LogLevel.Error, ConsoleColor.Red }, 28 | { LogLevel.Critical, ConsoleColor.DarkRed }, 29 | }; 30 | 31 | /// 32 | /// The min log level that will be written to the console, defaults to . 33 | /// 34 | public LogLevel MinLogLevel { get; set; } = LogLevel.Information; 35 | 36 | /// 37 | /// The list of event Ids to be written to the console. By default, all event Ids are written. 38 | /// 39 | public IEnumerable EventIds { get; } = new int[] { DefaultEventId }; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /helpers/ColorConsoleLogger/ColorConsoleLoggerExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace Microsoft.Azure.Devices.Logging 7 | { 8 | /// 9 | /// Extension methods to help simplify creation of a new instance. 10 | /// 11 | public static class ColorConsoleLoggerExtensions 12 | { 13 | /// 14 | /// Add a new instance, with the supplied settings. 15 | /// 16 | /// The type for which this extension method is defined. 17 | /// The settings to be used for logging. 18 | /// The instance. 19 | public static ILoggerFactory AddColorConsoleLogger(this ILoggerFactory loggerFactory, ColorConsoleLoggerConfiguration config) 20 | { 21 | loggerFactory.AddProvider(new ColorConsoleLoggerProvider(config)); 22 | return loggerFactory; 23 | } 24 | 25 | /// 26 | /// Add a new instance, with the default settings. 27 | /// 28 | /// The type for which this extension method is defined. 29 | /// The instance. 30 | public static ILoggerFactory AddColorConsoleLogger(this ILoggerFactory loggerFactory) 31 | { 32 | var config = new ColorConsoleLoggerConfiguration(); 33 | return loggerFactory.AddColorConsoleLogger(config); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /helpers/ColorConsoleLogger/ColorConsoleLoggerProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Extensions.Logging; 5 | using System.Collections.Concurrent; 6 | 7 | namespace Microsoft.Azure.Devices.Logging 8 | { 9 | /// 10 | /// The implementation that creates the instance. 11 | /// 12 | public class ColorConsoleLoggerProvider : ILoggerProvider 13 | { 14 | private readonly ColorConsoleLoggerConfiguration _config; 15 | private readonly ConcurrentDictionary _loggers = new ConcurrentDictionary(); 16 | 17 | /// 18 | /// Initialize an instance of with the supplied . 19 | /// 20 | /// The settings to be used for logging. 21 | public ColorConsoleLoggerProvider(ColorConsoleLoggerConfiguration config) 22 | { 23 | _config = config; 24 | } 25 | 26 | /// 27 | /// Create a new instance. 28 | /// 29 | /// The category name for the instance. This is usually the class name where the logger is initialized. 30 | /// The created instance. 31 | public ILogger CreateLogger(string categoryName) 32 | { 33 | return _loggers.GetOrAdd(categoryName, name => new ColorConsoleLogger(_config)); 34 | } 35 | 36 | /// 37 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 38 | /// 39 | public void Dispose() 40 | { 41 | _loggers.Clear(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /helpers/ColorConsoleLogger/ConsoleEventListener.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Extensions.Logging; 5 | using System; 6 | using System.Diagnostics.Tracing; 7 | using System.Linq; 8 | 9 | namespace Microsoft.Azure.Devices.Logging 10 | { 11 | /// 12 | /// Prints SDK events to Console output - the log level is set to TRACE 13 | /// 14 | public sealed class ConsoleEventListener : EventListener 15 | { 16 | private readonly string[] _eventFilters; 17 | private readonly ILogger _logger; 18 | private readonly object _lock = new object(); 19 | 20 | public ConsoleEventListener(string filter, ILogger logger) 21 | { 22 | _eventFilters = new string[1]; 23 | _eventFilters[0] = filter ?? throw new ArgumentNullException(nameof(filter)); 24 | _logger = logger; 25 | 26 | InitializeEventSources(); 27 | } 28 | 29 | public ConsoleEventListener(string[] filters, ILogger logger) 30 | { 31 | _eventFilters = filters ?? throw new ArgumentNullException(nameof(filters)); 32 | if (_eventFilters.Length == 0) throw new ArgumentException("Filters cannot be empty", nameof(filters)); 33 | 34 | foreach (string filter in _eventFilters) 35 | { 36 | if (string.IsNullOrWhiteSpace(filter)) 37 | { 38 | throw new ArgumentNullException(nameof(filters)); 39 | } 40 | } 41 | _logger = logger; 42 | 43 | InitializeEventSources(); 44 | } 45 | 46 | private void InitializeEventSources() 47 | { 48 | foreach (EventSource source in EventSource.GetSources()) 49 | { 50 | EnableEvents(source, EventLevel.LogAlways); 51 | } 52 | } 53 | 54 | protected override void OnEventSourceCreated(EventSource eventSource) 55 | { 56 | base.OnEventSourceCreated(eventSource); 57 | EnableEvents( 58 | eventSource, 59 | EventLevel.LogAlways 60 | #if !NET451 61 | , EventKeywords.All 62 | #endif 63 | ); 64 | } 65 | 66 | protected override void OnEventWritten(EventWrittenEventArgs eventData) 67 | { 68 | if (_eventFilters == null) return; 69 | 70 | lock (_lock) 71 | { 72 | if (_eventFilters.Any(ef => eventData.EventSource.Name.StartsWith(ef, StringComparison.Ordinal))) 73 | { 74 | string eventIdent; 75 | #if NET451 76 | // net451 doesn't have EventName, so we'll settle for EventId 77 | eventIdent = eventData.EventId.ToString(CultureInfo.InvariantCulture); 78 | #else 79 | eventIdent = eventData.EventName; 80 | #endif 81 | string text = $"[{eventData.EventSource.Name}-{eventIdent}]{(eventData.Payload != null ? $" ({string.Join(", ", eventData.Payload)})." : "")}"; 82 | _logger.LogTrace(text); 83 | } 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /horizontal-arm/arm-read-write.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.1169 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "arm-read-write", "arm-read-write\arm-read-write.csproj", "{C460F13E-C424-477B-90BD-E2BF7BCB063F}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {C460F13E-C424-477B-90BD-E2BF7BCB063F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {C460F13E-C424-477B-90BD-E2BF7BCB063F}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {C460F13E-C424-477B-90BD-E2BF7BCB063F}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {C460F13E-C424-477B-90BD-E2BF7BCB063F}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {3F87CEC5-340F-47ED-89D9-A746F4EBCA05} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /horizontal-arm/arm-read-write/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | //This code that messages to an IoT Hub for testing the routing as defined 5 | // in this article: https://docs.microsoft.com/en-us/azure/iot-hub/tutorial-routing 6 | //The scripts for creating the resources are included in the resources folder in this 7 | // Visual Studio solution. 8 | 9 | using Microsoft.Azure.Devices.Client; 10 | using Newtonsoft.Json; 11 | using System; 12 | using System.Text; 13 | using System.Threading; 14 | using System.Threading.Tasks; 15 | 16 | namespace arm_read_write 17 | { 18 | class Program 19 | { 20 | //This is the arm-read-write application that simulates a virtual device. 21 | //It writes messages to the IoT Hub, which routes the messages automatically to a storage account, 22 | //where you can view them. 23 | 24 | // This was derived by the (more complicated) tutorial for routing 25 | // https://docs.microsoft.com/en-us/azure/iot-hub/tutorial-routing 26 | 27 | private static DeviceClient s_deviceClient; 28 | private static string s_myDeviceId; 29 | private static string s_iotHubUri; 30 | private static string s_deviceKey; 31 | 32 | private static async Task Main() 33 | { 34 | if (!ReadEnvironmentVariables()) 35 | { 36 | Console.WriteLine(); 37 | Console.WriteLine("Error! One or more environment variables not set"); 38 | return; 39 | } 40 | 41 | Console.WriteLine("write messages to a hub and use routing to write them to storage"); 42 | 43 | s_deviceClient = DeviceClient.Create(s_iotHubUri, 44 | new DeviceAuthenticationWithRegistrySymmetricKey(s_myDeviceId, s_deviceKey), TransportType.Mqtt); 45 | 46 | var cts = new CancellationTokenSource(); 47 | 48 | var messages = SendDeviceToCloudMessagesAsync(cts.Token); 49 | 50 | Console.WriteLine("Press the Enter key to stop."); 51 | Console.ReadLine(); 52 | cts.Cancel(); 53 | await messages; 54 | } 55 | 56 | /// 57 | /// Read local process environment variables for required values 58 | /// 59 | /// 60 | /// True if all required environment variables are set 61 | /// 62 | private static bool ReadEnvironmentVariables() 63 | { 64 | bool result = true; 65 | 66 | s_myDeviceId = Environment.GetEnvironmentVariable("IOT_DEVICE_ID"); 67 | s_iotHubUri = Environment.GetEnvironmentVariable("IOT_HUB_URI"); 68 | s_deviceKey = Environment.GetEnvironmentVariable("IOT_DEVICE_KEY"); 69 | 70 | if ((s_myDeviceId is null) || (s_iotHubUri is null) || (s_deviceKey is null)) 71 | { 72 | result = false; 73 | } 74 | 75 | return result; 76 | } 77 | 78 | /// 79 | /// Send message to the Iot hub. This generates the object to be sent to the hub in the message. 80 | /// 81 | private static async Task SendDeviceToCloudMessagesAsync(CancellationToken token) 82 | { 83 | double minTemperature = 20; 84 | double minHumidity = 60; 85 | Random rand = new Random(); 86 | 87 | while (!token.IsCancellationRequested) 88 | { 89 | 90 | double currentTemperature = minTemperature + rand.NextDouble() * 15; 91 | double currentHumidity = minHumidity + rand.NextDouble() * 20; 92 | 93 | string infoString; 94 | string levelValue; 95 | 96 | if (rand.NextDouble() > 0.7) 97 | { 98 | if (rand.NextDouble() > 0.5) 99 | { 100 | levelValue = "critical"; 101 | infoString = "This is a critical message."; 102 | } 103 | else 104 | { 105 | levelValue = "storage"; 106 | infoString = "This is a storage message."; 107 | } 108 | } 109 | else 110 | { 111 | levelValue = "normal"; 112 | infoString = "This is a normal message."; 113 | } 114 | 115 | var telemetryDataPoint = new 116 | { 117 | deviceId = s_myDeviceId, 118 | temperature = currentTemperature, 119 | humidity = currentHumidity, 120 | pointInfo = infoString 121 | }; 122 | // serialize the telemetry data and convert it to JSON. 123 | var telemetryDataString = JsonConvert.SerializeObject(telemetryDataPoint); 124 | 125 | // Encode the serialized object using UTF-8 so it can be parsed by IoT Hub when 126 | // processing messaging rules. 127 | using var message = new Message(Encoding.UTF8.GetBytes(telemetryDataString)) 128 | { 129 | ContentEncoding = "utf-8", 130 | ContentType = "application/json", 131 | }; 132 | 133 | //Add one property to the message. 134 | message.Properties.Add("level", levelValue); 135 | 136 | // Submit the message to the hub. 137 | await s_deviceClient.SendEventAsync(message); 138 | 139 | // Print out the message. 140 | Console.WriteLine("{0} > Sent message: {1}", DateTime.Now, telemetryDataString); 141 | 142 | await Task.Delay(1000); 143 | } 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /horizontal-arm/arm-read-write/arm-read-write.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | arm_read_write 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /horizontal-arm/arm-template/template_iothub.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "randomValue": { 6 | "defaultValue": "[substring(uniqueString(utcNow()),0,8)]", 7 | "type": "string", 8 | "metadata": { 9 | "description": "Random alphanumeric string to make the assets have a unique name." 10 | } 11 | }, 12 | "subscriptionId": { 13 | "type": "string", 14 | "defaultValue": "[subscription().subscriptionid]", 15 | "metadata": { 16 | "description": "The subscription ID of the Azure subscription to deploy into." 17 | } 18 | }, 19 | "IoTHubName_in": { 20 | "type": "string", 21 | "defaultValue": "ContosoTestHub", 22 | "metadata": { 23 | "description": "The name of the IoT Hub to create." 24 | } 25 | }, 26 | "location": { 27 | "type": "string", 28 | "defaultValue": "westus2", 29 | "metadata": { 30 | "description": "The datacenter to use for the deployment." 31 | } 32 | }, 33 | "sku_name": { 34 | "type": "string", 35 | "defaultValue": "S1", 36 | "metadata": { 37 | "description": "The SKU to use for the IoT Hub." 38 | } 39 | }, 40 | "sku_units": { 41 | "type": "string", 42 | "defaultValue": "1", 43 | "metadata": { 44 | "description": "The number of IoT Hub units." 45 | } 46 | }, 47 | "d2c_partitions": { 48 | "type": "string", 49 | "defaultValue": "4", 50 | "metadata": { 51 | "description": "Partitions used for the event stream." 52 | } 53 | }, 54 | "storageAccountName_in": { 55 | "type": "string", 56 | "defaultValue": "contosostorage", 57 | "metadata": { 58 | "description": "Name of storage account to be created." 59 | } 60 | }, 61 | "storageContainerName": { 62 | "type": "string", 63 | "defaultValue": "contosoresults", 64 | "metadata": { 65 | "description": "Name of the container in which to place the routed data." 66 | } 67 | }, 68 | "storage_endpoint": { 69 | "type": "string", 70 | "defaultValue": "ContosoStorageEndpoint", 71 | "metadata": { 72 | "description": "Name of the endpoint for the storage account." 73 | } 74 | } 75 | }, 76 | "variables": { 77 | "iotHubName": "[concat(parameters('IotHubName_in'),parameters('randomValue'))]", 78 | "storageAccountName": "[concat(parameters('storageAccountName_in'),parameters('randomValue'))]" 79 | }, 80 | "resources": [ 81 | { 82 | "type": "Microsoft.Storage/storageAccounts", 83 | "name": "[variables('storageAccountName')]", 84 | "apiVersion": "2018-07-01", 85 | "location": "[parameters('location')]", 86 | "sku": { 87 | "name": "Standard_LRS", 88 | "tier": "Standard" 89 | }, 90 | "kind": "Storage", 91 | "properties": {}, 92 | "resources": [ 93 | { 94 | "type": "blobServices/containers", 95 | "apiVersion": "2018-07-01", 96 | "name": "[concat('default/', parameters('storageContainerName'))]", 97 | "properties": { 98 | "publicAccess": "None" 99 | } , 100 | "dependsOn": [ 101 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]" 102 | ] 103 | } 104 | ] 105 | }, 106 | { 107 | "apiVersion": "2018-04-01", 108 | "type": "Microsoft.Devices/IotHubs", 109 | "name": "[variables('IoTHubName')]", 110 | "location": "[parameters('location')]", 111 | "dependsOn": [ 112 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]" 113 | ], 114 | "properties": { 115 | "eventHubEndpoints": { 116 | "events": { 117 | "retentionTimeInDays": 1, 118 | "partitionCount": "[parameters('d2c_partitions')]" 119 | } 120 | }, 121 | "routing": { 122 | "endpoints": { 123 | "serviceBusQueues": [], 124 | "serviceBusTopics": [], 125 | "eventHubs": [], 126 | "storageContainers": [ 127 | { 128 | "connectionString": 129 | "[Concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]", 130 | "containerName": "[parameters('storageContainerName')]", 131 | "fileNameFormat": "{iothub}/{partition}/{YYYY}/{MM}/{DD}/{HH}/{mm}", 132 | "batchFrequencyInSeconds": 100, 133 | "maxChunkSizeInBytes": 104857600, 134 | "encoding": "json", 135 | "name": "[parameters('storage_endpoint')]", 136 | "subscriptionId": "[parameters('subscriptionId')]", 137 | "resourceGroup": "[resourceGroup().Name]" 138 | } 139 | ] 140 | }, 141 | "routes": [ 142 | { 143 | "name": "ContosoStorageRoute", 144 | "source": "DeviceMessages", 145 | "condition": "level=\"storage\"", 146 | "endpointNames": [ 147 | "[parameters('storage_endpoint')]" 148 | ], 149 | "isEnabled": true 150 | } 151 | ], 152 | "fallbackRoute": { 153 | "name": "$fallback", 154 | "source": "DeviceMessages", 155 | "condition": "true", 156 | "endpointNames": [ 157 | "events" 158 | ], 159 | "isEnabled": true 160 | } 161 | }, 162 | "storageEndpoints": { 163 | "$default": { 164 | "sasTtlAsIso8601": "PT1H", 165 | "connectionString": "", 166 | "containerName": "" 167 | } 168 | }, 169 | "messagingEndpoints": { 170 | "fileNotifications": { 171 | "lockDurationAsIso8601": "PT1M", 172 | "ttlAsIso8601": "PT1H", 173 | "maxDeliveryCount": 10 174 | } 175 | }, 176 | "enableFileUploadNotifications": false, 177 | "cloudToDevice": { 178 | "maxDeliveryCount": 10, 179 | "defaultTtlAsIso8601": "PT1H", 180 | "feedback": { 181 | "lockDurationAsIso8601": "PT1M", 182 | "ttlAsIso8601": "PT1H", 183 | "maxDeliveryCount": 10 184 | } 185 | } 186 | }, 187 | "sku": { 188 | "name": "[parameters('sku_name')]", 189 | "capacity": "[parameters('sku_units')]" 190 | } 191 | } 192 | ], 193 | "outputs": { 194 | } 195 | } -------------------------------------------------------------------------------- /horizontal-arm/testenvvars_SET.cmd: -------------------------------------------------------------------------------- 1 | 2 | echo on 3 | //set environment variables. Fill in the fields below, then run each line in the command window one at a time 4 | //then run the .NET Core app from the command window. You should be in the same folder as the arm-read-write.csproj file. 5 | CMD> dotnet run 6 | 7 | //Doing this instead of hardcoding these variables ensures that you don't accidentally save them to github. 8 | // 9 | SET IOT_DEVICE_ID=Contoso-Test-Device 10 | SET IOT_HUB_URI="IOT-HUB-NAME-GOES-HERE.azure-devices-net"; 11 | SET IOT_DEVICE_KEY="IoT-device-key-goes-here" 12 | // 13 | //to see local environment variables, type set and hit return, and it will show them all -------------------------------------------------------------------------------- /iot-hub/Quickstarts/InvokeDeviceMethod/readme.md: -------------------------------------------------------------------------------- 1 | # Azure IoT Hub InvokeDeviceMethodSample 2 | 3 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [InvokeDeviceMethodSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /iot-hub/Quickstarts/ReadD2cMessages/README.md: -------------------------------------------------------------------------------- 1 | # Azure IoT Hub ReadD2cMessagesSample 2 | 3 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [ReadD2cMessagesSample]https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). 6 | -------------------------------------------------------------------------------- /iot-hub/Quickstarts/SimulatedDevice/readme.md: -------------------------------------------------------------------------------- 1 | # Azure IoT Hub SimulatedDeviceSample 2 | 3 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [SimulatedDeviceSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /iot-hub/Quickstarts/SimulatedDeviceWithCommand/readme.md: -------------------------------------------------------------------------------- 1 | # Azure IoT Hub SimulatedDeviceWithCommandSample 2 | 3 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [SimulatedDeviceWithCommandSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /iot-hub/Samples/device/DeviceReconnectionSample/readme.md: -------------------------------------------------------------------------------- 1 | # Device Reconnection Sample 2 | 3 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [DeviceReconnectionSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). 6 | -------------------------------------------------------------------------------- /iot-hub/Samples/device/FileUploadSample/readme.md: -------------------------------------------------------------------------------- 1 | # FileUploadSample 2 | 3 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [FileUploadSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). 6 | 7 | -------------------------------------------------------------------------------- /iot-hub/Samples/device/MessageReceiveSample/readme.md: -------------------------------------------------------------------------------- 1 | # MessageReceiveSample 2 | 3 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [MessageReceiveSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). 6 | 7 | -------------------------------------------------------------------------------- /iot-hub/Samples/device/MethodSample/readme.md: -------------------------------------------------------------------------------- 1 | # MethodSample 2 | 3 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [MethodSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). 6 | -------------------------------------------------------------------------------- /iot-hub/Samples/device/PnpDeviceSamples/readme.md: -------------------------------------------------------------------------------- 1 | # IoT Plug And Play device samples 2 | 3 | The samples that previously existed here have been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [PnpDeviceSamples](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /iot-hub/Samples/device/TwinSample/readme.md: -------------------------------------------------------------------------------- 1 | # Device Twins Sample 2 | 3 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [TwinSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). 6 | -------------------------------------------------------------------------------- /iot-hub/Samples/device/X509DeviceCertWithChainSample/readme.md: -------------------------------------------------------------------------------- 1 | # x509 device certificate with chain sample 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [X509Sample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). 5 | -------------------------------------------------------------------------------- /iot-hub/Samples/device/XamarinSample/readme.md: -------------------------------------------------------------------------------- 1 | # Microsoft Azure IoT device SDK Xamarin Samples for .NET 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [XamarinSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). 5 | -------------------------------------------------------------------------------- /iot-hub/Samples/module/ModuleSample/readme.md: -------------------------------------------------------------------------------- 1 | # Module Sample 2 | 3 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [ModuleSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). 6 | -------------------------------------------------------------------------------- /iot-hub/Samples/service/AutomaticDeviceManagementSample/readme.md: -------------------------------------------------------------------------------- 1 | # Azure IoT Hub AutomaticDeviceManagementSample 2 | 3 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [AutomaticDeviceManagementSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /iot-hub/Samples/service/AzureSasCredentialAuthenticationSample/readme.md: -------------------------------------------------------------------------------- 1 | # Azure IoT Hub AzureSasCredentialAuthenticationSample 2 | 3 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [AzureSasCredentialAuthenticationSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /iot-hub/Samples/service/CleanupDevicesSample/readme.md: -------------------------------------------------------------------------------- 1 | # Azure IoT Hub CleanupDevicesSample 2 | 3 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [CleanupDevicesSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /iot-hub/Samples/service/DigitalTwinClientSamples/readme.md: -------------------------------------------------------------------------------- 1 | # Digital Twin Client Samples for the Azure IoT Service SDK 2 | The samples that previously existed here have been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [DigialTwinsClientSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). 5 | -------------------------------------------------------------------------------- /iot-hub/Samples/service/EdgeDeploymentSample/readme.md: -------------------------------------------------------------------------------- 1 | # EdgeDeploymentSample 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [EdgeDeploymentSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /iot-hub/Samples/service/FileUploadNotificationReceiverSample/readme.md: -------------------------------------------------------------------------------- 1 | # FileUploadNotificationReceiverSample 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [FileUploadNotificationReceiverSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /iot-hub/Samples/service/ImportExportDevicesSample/readme.md: -------------------------------------------------------------------------------- 1 | # ImportExportDevicesSample 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [ImportExportDevicesSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /iot-hub/Samples/service/ImportExportDevicesWithManagedIdentitySample/readme.md: -------------------------------------------------------------------------------- 1 | # ImportExportDevicesWithManagedIdentitySample 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [ImportExportDevicesWithManagedIdentitySample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /iot-hub/Samples/service/JobsSample/readme.md: -------------------------------------------------------------------------------- 1 | # JobsSample 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [JobsSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /iot-hub/Samples/service/PnpServiceSamples/readme.md: -------------------------------------------------------------------------------- 1 | # IoT Plug And Play service samples 2 | The samples that previously existed here have been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [PnpServiceSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). 5 | -------------------------------------------------------------------------------- /iot-hub/Samples/service/RegistryManagerSample/readme.md: -------------------------------------------------------------------------------- 1 | # RegistryManagerSample 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [RegistryManagerSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /iot-hub/Samples/service/RoleBasedAuthenticationSample/readme.md: -------------------------------------------------------------------------------- 1 | # RoleBasedAuthenticationSample 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [RoleBasedAuthenticationSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /iot-hub/Samples/service/ServiceClientSample/readme.md: -------------------------------------------------------------------------------- 1 | # Service Client Sample 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [ServiceClientSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). 5 | -------------------------------------------------------------------------------- /iot-hub/Tutorials/Routing/IoT_SimulatedDevice.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2005 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimulatedDevice", "SimulatedDevice\SimulatedDevice.csproj", "{7A6973B3-9375-47E4-A593-B86A3514841A}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {7A6973B3-9375-47E4-A593-B86A3514841A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {7A6973B3-9375-47E4-A593-B86A3514841A}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {7A6973B3-9375-47E4-A593-B86A3514841A}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {7A6973B3-9375-47E4-A593-B86A3514841A}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {75D6C41B-4AA6-4E02-B353-34F9E0702263} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /iot-hub/Tutorials/Routing/SimulatedDevice/Parameters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CommandLine; 3 | 4 | namespace SimulatedDevice 5 | { 6 | /// 7 | /// Parameters for the application. 8 | /// 9 | internal class Parameters 10 | { 11 | [Option( 12 | 'u', 13 | "IoTHubUri", 14 | Required = true, 15 | HelpText = "The URI for the IoT hub.")] 16 | public string IotHubUri { get; set; } 17 | 18 | [Option( 19 | 'd', 20 | "DeviceId", 21 | Required = true, 22 | HelpText = "The device Id that you assigned when registering the device.")] 23 | public string DeviceId { get; set; } 24 | 25 | // This is the primary key for the device. This is in the portal. 26 | // Find your IoT hub in the portal > IoT devices > select your device > copy the key. 27 | [Option( 28 | 'k', 29 | "DeviceKey", 30 | Required = true, 31 | HelpText = "Find your IoT hub in the portal > IoT devices > select your device > copy the key.")] 32 | public string DeviceKey { get; set; } 33 | 34 | [Option( 35 | "ReadTheFile", 36 | Required = false, 37 | HelpText = "If this is false, it will submit messages to the IoT hub. If this is true, it will read one of the output files and convert it to ASCII.")] 38 | public bool ReadTheFile { get; set; } = false; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /iot-hub/Tutorials/Routing/SimulatedDevice/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | //This is the code that sends messages to the IoT Hub for testing the routing as defined 5 | // in this article: https://docs.microsoft.com/azure/iot-hub/tutorial-routing 6 | //The scripts for creating the resources are included in the resources folder in this 7 | // Visual Studio solution. 8 | // 9 | // This program encodes the message body so it can be queried against by the Iot hub. 10 | // 11 | // If you want to read an encoded message body, you can do this: 12 | // * route the message to storage, 13 | // * retrieve the message from the storage account by downloading the blob, 14 | // * use the ReadOneRowFromFile method at the bottom of this module to read the first row of the file. 15 | // * It will read the file, decode the first row in the file, and write it out to a new file 16 | // in ASCII so you can view it. 17 | 18 | using CommandLine; 19 | using Microsoft.Azure.Devices.Client; 20 | using Newtonsoft.Json; 21 | using Newtonsoft.Json.Linq; 22 | using System; 23 | using System.Text; 24 | using System.Threading; 25 | using System.Threading.Tasks; 26 | 27 | namespace SimulatedDevice 28 | { 29 | internal class Program 30 | { 31 | private static DeviceClient s_deviceClient; 32 | 33 | private static async Task Main(string[] args) 34 | { 35 | // Parse application parameters 36 | Parameters parameters = null; 37 | ParserResult result = Parser.Default.ParseArguments(args) 38 | .WithParsed(parsedParams => 39 | { 40 | parameters = parsedParams; 41 | }) 42 | .WithNotParsed(errors => 43 | { 44 | Environment.Exit(1); 45 | }); 46 | 47 | // If this is false, it will submit messages to the iot hub. 48 | // If this is true, it will read one of the output files and convert it to ASCII. 49 | if (parameters.ReadTheFile) 50 | { 51 | // If you want to decode an output file, put the path in ReadOneRowFromFile(), 52 | // uncomment the call here and the return command, then run this application. 53 | ReadOneRowFromFile(); 54 | } 55 | else 56 | { 57 | // Send messages to the simulated device. Each message will contain a randomly generated 58 | // Temperature and Humidity. 59 | // The "level" of each message is set randomly to "storage", "critical", or "normal". 60 | // The messages are routed to different endpoints depending on the level, temperature, and humidity. 61 | // This is set in the tutorial that goes with this sample: 62 | // http://docs.microsoft.com/azure/iot-hub/tutorial-routing 63 | 64 | Console.WriteLine("Routing Tutorial: Simulated device\n"); 65 | string myDeviceId = parameters.DeviceId; 66 | string deviceKey = parameters.DeviceKey; 67 | s_deviceClient = DeviceClient.Create( 68 | parameters.IotHubUri, 69 | new DeviceAuthenticationWithRegistrySymmetricKey(myDeviceId, deviceKey), 70 | TransportType.Mqtt); 71 | 72 | using var cts = new CancellationTokenSource(); 73 | Task messages = SendDeviceToCloudMessagesAsync(myDeviceId, cts.Token); 74 | Console.WriteLine("Press the Enter key to stop."); 75 | Console.ReadLine(); 76 | await s_deviceClient.CloseAsync(cts.Token); 77 | cts.Cancel(); 78 | await messages; 79 | 80 | } 81 | } 82 | 83 | /// 84 | /// Send message to the Iot hub. This generates the object to be sent to the hub in the message. 85 | /// 86 | private static async Task SendDeviceToCloudMessagesAsync(string myDeviceId, CancellationToken token) 87 | { 88 | double minTemperature = 20; 89 | double minHumidity = 60; 90 | var rand = new Random(); 91 | 92 | while (!token.IsCancellationRequested) 93 | { 94 | double currentTemperature = minTemperature + rand.NextDouble() * 15; 95 | double currentHumidity = minHumidity + rand.NextDouble() * 20; 96 | 97 | string infoString; 98 | string levelValue; 99 | 100 | if (rand.NextDouble() > 0.7) 101 | { 102 | if (rand.NextDouble() > 0.5) 103 | { 104 | levelValue = "critical"; 105 | infoString = "This is a critical message."; 106 | } 107 | else 108 | { 109 | levelValue = "storage"; 110 | infoString = "This is a storage message."; 111 | } 112 | } 113 | else 114 | { 115 | levelValue = "normal"; 116 | infoString = "This is a normal message."; 117 | } 118 | 119 | var telemetryDataPoint = new 120 | { 121 | deviceId = myDeviceId, 122 | temperature = currentTemperature, 123 | humidity = currentHumidity, 124 | pointInfo = infoString 125 | }; 126 | // serialize the telemetry data and convert it to JSON. 127 | string telemetryDataString = JsonConvert.SerializeObject(telemetryDataPoint); 128 | 129 | // Encode the serialized object using UTF-8 so it can be parsed by IoT Hub when 130 | // processing messaging rules. 131 | using var message = new Message(Encoding.UTF8.GetBytes(telemetryDataString)) 132 | { 133 | ContentEncoding = "utf-8", 134 | ContentType = "application/json", 135 | }; 136 | 137 | // Add one property to the message. 138 | message.Properties.Add("level", levelValue); 139 | 140 | // Submit the message to the hub. 141 | try 142 | { 143 | await s_deviceClient.SendEventAsync(message, token); 144 | } 145 | catch (OperationCanceledException) { } 146 | 147 | // Print out the message. 148 | Console.WriteLine("{0} > Sent message: {1}", DateTime.UtcNow, telemetryDataString); 149 | 150 | try 151 | { 152 | await Task.Delay(1000, token); 153 | } 154 | catch (OperationCanceledException) { } 155 | } 156 | } 157 | 158 | 159 | /// 160 | /// This method was written to enable you to decode one of the messages sent to the hub 161 | /// and view the body of the message. 162 | /// Route the messages to storage (they get written to blob storage). 163 | /// Send messages to the hub, by running this program with readthefile set to false. 164 | /// After some messages have been written to storage, download one of the files 165 | /// to somewhere you can find it, put the path in this method, and run the program 166 | /// with readthefile set to true. 167 | /// This method will read in the output file, then convert the first line to a message body object 168 | /// and write it back out to a new file that you can open and view. 169 | /// 170 | private static void ReadOneRowFromFile() 171 | { 172 | string filePathAndName = "C:\\Users\\username\\Desktop\\testfiles\\47_utf32.txt"; 173 | 174 | // Set the output file name. 175 | // Read in the file to an array of objects. These were encoded in Base64 when they were 176 | // written. 177 | string outputFilePathAndName = filePathAndName.Replace(".txt", "_new.txt"); 178 | string[] fileLines = System.IO.File.ReadAllLines(filePathAndName); 179 | 180 | // Parse the first line into a message object. Retrieve the body as a string. 181 | // This string was encoded as Base64 when it was written. 182 | var messageObject = JObject.Parse(fileLines[0]); 183 | string body = messageObject.Value("Body"); 184 | 185 | // Convert the body from Base64, then from UTF-32 to text, and write it out to the new file 186 | // so you can view the result. 187 | string outputResult = System.Text.Encoding.UTF32.GetString(System.Convert.FromBase64String(body)); 188 | 189 | System.IO.File.WriteAllText(outputFilePathAndName, outputResult); 190 | } 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /iot-hub/Tutorials/Routing/SimulatedDevice/SimulatedDevice.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | 9.0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /iot-hub/Tutorials/Routing/SimulatedDevice/resources/iothub_msgenrichment_cli.azcli: -------------------------------------------------------------------------------- 1 | # This command retrieves the subscription id of the current Azure account. 2 | # This field is used when setting up the routing queries. 3 | subscriptionID=$(az account show --query id -o tsv) 4 | 5 | # Concatenate this number onto the resources that have to be globally unique. 6 | # You can set this to "" or to a specific value if you don't want it to be random. 7 | # This retrieves a random value. 8 | randomValue=$RANDOM 9 | 10 | # This command installs the IOT Extension for Azure CLI. 11 | # You only need to install this the first time. 12 | # You need it to create the device identity. 13 | az extension add --name azure-cli-iot-ext 14 | 15 | # Set the values for the resource names that 16 | # don't have to be globally unique. 17 | location=westus2 18 | resourceGroup=ContosoResourcesMsgEn 19 | containerName1=original 20 | containerName2=enriched 21 | iotDeviceName=Contoso-Test-Device 22 | 23 | # Create the resource group to be used 24 | # for all the resources for this tutorial. 25 | az group create --name $resourceGroup \ 26 | --location $location 27 | 28 | # The IoT hub name must be globally unique, 29 | # so add a random value to the end. 30 | iotHubName=ContosoTestHubMsgEn$randomValue 31 | echo "IoT hub name = " $iotHubName 32 | 33 | # Create the IoT hub. 34 | az iot hub create --name $iotHubName \ 35 | --resource-group $resourceGroup \ 36 | --sku S1 --location $location 37 | 38 | # You need a storage account that will have two containers 39 | # -- one for the original messages and 40 | # one for the enriched messages. 41 | # The storage account name must be globally unique, 42 | # so add a random value to the end. 43 | storageAccountName=contosostorage$randomValue 44 | echo "Storage account name = " $storageAccountName 45 | 46 | # Create the storage account to be used as a routing destination. 47 | az storage account create --name $storageAccountName \ 48 | --resource-group $resourceGroup \ 49 | --location $location \ 50 | --sku Standard_LRS 51 | 52 | # Get the primary storage account key. 53 | # You need this to create the containers. 54 | storageAccountKey=$(az storage account keys list \ 55 | --resource-group $resourceGroup \ 56 | --account-name $storageAccountName \ 57 | --query "[0].value" | tr -d '"') 58 | 59 | # See the value of the storage account key. 60 | echo "storage account key = " $storageAccountKey 61 | 62 | # Create the containers in the storage account. 63 | az storage container create --name $containerName1 \ 64 | --account-name $storageAccountName \ 65 | --account-key $storageAccountKey \ 66 | --public-access off 67 | 68 | az storage container create --name $containerName2 \ 69 | --account-name $storageAccountName \ 70 | --account-key $storageAccountKey \ 71 | --public-access off 72 | 73 | # Create the IoT device identity to be used for testing. 74 | az iot hub device-identity create --device-id $iotDeviceName \ 75 | --hub-name $iotHubName 76 | 77 | # Retrieve the information about the device identity, then copy the primary key to 78 | # Notepad. You need this to run the device simulation during the testing phase. 79 | # If you are using Cloud Shell, you can scroll the window back up to retrieve this value. 80 | az iot hub device-identity show --device-id $iotDeviceName \ 81 | --hub-name $iotHubName 82 | 83 | ##### ROUTING FOR STORAGE ##### 84 | 85 | # You're going to have two routes and two endpoints. 86 | # One route points to the first container ("original") in the storage account 87 | # and includes the original messages. 88 | # The other points to the second container ("enriched") in the same storage account 89 | # and includes the enriched versions of the messages. 90 | 91 | endpointType="azurestoragecontainer" 92 | endpointName1="ContosoStorageEndpointOriginal" 93 | endpointName2="ContosoStorageEndpointEnriched" 94 | routeName1="ContosoStorageRouteOriginal" 95 | routeName2="ContosoStorageRouteEnriched" 96 | 97 | # for both endpoints, retrieve the messages going to storage 98 | condition='level="storage"' 99 | 100 | # Get the connection string for the storage account. 101 | # Adding the "-o tsv" makes it be returned without the default double quotes around it. 102 | storageConnectionString=$(az storage account show-connection-string \ 103 | --name $storageAccountName --query connectionString -o tsv) 104 | 105 | # Create the routing endpoints and routes. 106 | # Set the encoding format to either avro or json. 107 | 108 | # This is the endpoint for the first container, for endpoint messages that are not enriched. 109 | az iot hub routing-endpoint create \ 110 | --connection-string $storageConnectionString \ 111 | --endpoint-name $endpointName1 \ 112 | --endpoint-resource-group $resourceGroup \ 113 | --endpoint-subscription-id $subscriptionID \ 114 | --endpoint-type $endpointType \ 115 | --hub-name $iotHubName \ 116 | --container $containerName1 \ 117 | --resource-group $resourceGroup \ 118 | --encoding json 119 | 120 | # This is the endpoint for the second container, for endpoint messages that are enriched. 121 | az iot hub routing-endpoint create \ 122 | --connection-string $storageConnectionString \ 123 | --endpoint-name $endpointName2 \ 124 | --endpoint-resource-group $resourceGroup \ 125 | --endpoint-subscription-id $subscriptionID \ 126 | --endpoint-type $endpointType \ 127 | --hub-name $iotHubName \ 128 | --container $containerName2 \ 129 | --resource-group $resourceGroup \ 130 | --encoding json 131 | 132 | # This is the route for messages that are not enriched. 133 | # Create the route for the first storage endpoint. 134 | az iot hub route create \ 135 | --name $routeName1 \ 136 | --hub-name $iotHubName \ 137 | --source devicemessages \ 138 | --resource-group $resourceGroup \ 139 | --endpoint-name $endpointName1 \ 140 | --enabled \ 141 | --condition $condition 142 | 143 | # This is the route for messages that are enriched. 144 | # Create the route for the second storage endpoint. 145 | az iot hub route create \ 146 | --name $routeName2 \ 147 | --hub-name $iotHubName \ 148 | --source devicemessages \ 149 | --resource-group $resourceGroup \ 150 | --endpoint-name $endpointName2 \ 151 | --enabled \ 152 | --condition $condition 153 | -------------------------------------------------------------------------------- /iot-hub/Tutorials/Routing/SimulatedDevice/resources/iothub_routing_cli.azcli: -------------------------------------------------------------------------------- 1 | # This command retrieves the subscription id of the current Azure account. 2 | # This field is used when setting up the routing queries. 3 | subscriptionID=$(az account show --query id -o tsv) 4 | 5 | # Concatenate this number onto the resources that have to be globally unique. 6 | # You can set this to "" or to a specific value if you don't want it to be random. 7 | # This retrieves a random value. 8 | randomValue=$RANDOM 9 | 10 | # This command installs the IOT Extension for Azure CLI. 11 | # You only need to install this the first time. 12 | # You need it to create the device identity. 13 | az extension add --name azure-cli-iot-ext 14 | 15 | # Set the values for the resource names that 16 | # don't have to be globally unique. 17 | location=westus 18 | resourceGroup=ContosoResources 19 | iotHubConsumerGroup=ContosoConsumers 20 | containerName=contosoresults 21 | iotDeviceName=Contoso-Test-Device 22 | 23 | # Create the resource group to be used 24 | # for all the resources for this tutorial. 25 | az group create --name $resourceGroup \ 26 | --location $location 27 | 28 | # The IoT hub name must be globally unique, 29 | # so add a random value to the end. 30 | iotHubName=ContosoTestHub$randomValue 31 | echo "IoT hub name = " $iotHubName 32 | 33 | # Create the IoT hub. 34 | az iot hub create --name $iotHubName \ 35 | --resource-group $resourceGroup \ 36 | --sku S1 --location $location 37 | 38 | # Add a consumer group to the IoT hub for the 'events' endpoint. 39 | az iot hub consumer-group create --hub-name $iotHubName \ 40 | --name $iotHubConsumerGroup 41 | 42 | # The storage account name must be globally unique, 43 | # so add a random value to the end. 44 | storageAccountName=contosostorage$randomValue 45 | echo "Storage account name = " $storageAccountName 46 | 47 | # Create the storage account to be used as a routing destination. 48 | az storage account create --name $storageAccountName \ 49 | --resource-group $resourceGroup \ 50 | --location $location \ 51 | --sku Standard_LRS 52 | 53 | # Get the primary storage account key. 54 | # You need this to create the container. 55 | storageAccountKey=$(az storage account keys list \ 56 | --resource-group $resourceGroup \ 57 | --account-name $storageAccountName \ 58 | --query "[0].value" | tr -d '"') 59 | 60 | # See the value of the storage account key. 61 | echo "storage account key = " $storageAccountKey 62 | 63 | # Create the container in the storage account. 64 | az storage container create --name $containerName \ 65 | --account-name $storageAccountName \ 66 | --account-key $storageAccountKey \ 67 | --public-access off 68 | 69 | # The Service Bus namespace must be globally unique, 70 | # so add a random value to the end. 71 | sbNamespace=ContosoSBNamespace$randomValue 72 | echo "Service Bus namespace = " $sbNamespace 73 | 74 | # Create the Service Bus namespace. 75 | az servicebus namespace create --resource-group $resourceGroup \ 76 | --name $sbNamespace \ 77 | --location $location 78 | 79 | # The Service Bus queue name must be globally unique, 80 | # so add a random value to the end. 81 | sbQueueName=ContosoSBQueue$randomValue 82 | echo "Service Bus queue name = " $sbQueueName 83 | 84 | # Create the Service Bus queue to be used as a routing destination. 85 | az servicebus queue create --name $sbQueueName \ 86 | --namespace-name $sbNamespace \ 87 | --resource-group $resourceGroup 88 | 89 | # Create the IoT device identity to be used for testing. 90 | az iot hub device-identity create --device-id $iotDeviceName \ 91 | --hub-name $iotHubName 92 | 93 | # Retrieve the information about the device identity, then copy the primary key to 94 | # Notepad. You need this to run the device simulation during the testing phase. 95 | az iot hub device-identity show --device-id $iotDeviceName \ 96 | --hub-name $iotHubName 97 | 98 | ##### ROUTING FOR STORAGE ##### 99 | 100 | endpointName="ContosoStorageEndpoint" 101 | endpointType="azurestoragecontainer" 102 | routeName="ContosoStorageRoute" 103 | condition='level="storage"' 104 | 105 | # Get the connection string for the storage account. 106 | # Adding the "-o tsv" makes it be returned without the default double quotes around it. 107 | storageConnectionString=$(az storage account show-connection-string \ 108 | --name $storageAccountName --query connectionString -o tsv) 109 | 110 | # Create the routing endpoint for storage. 111 | # Set the encoding format to either avro or json. 112 | az iot hub routing-endpoint create \ 113 | --connection-string $storageConnectionString \ 114 | --endpoint-name $endpointName \ 115 | --endpoint-resource-group $resourceGroup \ 116 | --endpoint-subscription-id $subscriptionID \ 117 | --endpoint-type $endpointType \ 118 | --hub-name $iotHubName \ 119 | --container $containerName \ 120 | --resource-group $resourceGroup \ 121 | --encoding avro 122 | 123 | # Create the route for the storage endpoint. 124 | az iot hub route create \ 125 | --name $routeName \ 126 | --hub-name $iotHubName \ 127 | --source devicemessages \ 128 | --resource-group $resourceGroup \ 129 | --endpoint-name $endpointName \ 130 | --enabled \ 131 | --condition $condition 132 | 133 | ##### ROUTING FOR SERVICE BUS QUEUE ##### 134 | 135 | # Create the authorization rule for the Service Bus queue. 136 | az servicebus queue authorization-rule create \ 137 | --name "sbauthrule" \ 138 | --namespace-name $sbNamespace \ 139 | --queue-name $sbQueueName \ 140 | --resource-group $resourceGroup \ 141 | --rights Listen Manage Send \ 142 | --subscription $subscriptionID 143 | 144 | # Get the Service Bus queue connection string. 145 | # The "-o tsv" ensures it is returned without the default double-quotes. 146 | sbqConnectionString=$(az servicebus queue authorization-rule keys list \ 147 | --name "sbauthrule" \ 148 | --namespace-name $sbNamespace \ 149 | --queue-name $sbQueueName \ 150 | --resource-group $resourceGroup \ 151 | --subscription $subscriptionID \ 152 | --query primaryConnectionString -o tsv) 153 | 154 | # Show the Service Bus queue connection string. 155 | echo "service bus queue connection string = " $sbqConnectionString 156 | 157 | endpointName="ContosoSBQueueEndpoint" 158 | endpointType="ServiceBusQueue" 159 | routeName="ContosoSBQueueRoute" 160 | condition='level="critical"' 161 | 162 | # Set up the routing endpoint for the Service Bus queue. 163 | # This uses the Service Bus queue connection string. 164 | az iot hub routing-endpoint create \ 165 | --connection-string $sbqConnectionString \ 166 | --endpoint-name $endpointName \ 167 | --endpoint-resource-group $resourceGroup \ 168 | --endpoint-subscription-id $subscriptionID \ 169 | --endpoint-type $endpointType \ 170 | --hub-name $iotHubName \ 171 | --resource-group $resourceGroup 172 | 173 | # Set up the message route for the Service Bus queue endpoint. 174 | az iot hub route create --name $routeName \ 175 | --hub-name $iotHubName \ 176 | --source-type devicemessages \ 177 | --resource-group $resourceGroup \ 178 | --endpoint-name $endpointName \ 179 | --enabled \ 180 | --condition $condition -------------------------------------------------------------------------------- /iot-hub/Tutorials/Routing/SimulatedDevice/resources/iothub_routing_psh.ps1: -------------------------------------------------------------------------------- 1 | # This retrieves the subscription id of the current Azure account. 2 | # This field is used when setting up the routing queries. 3 | $subscriptionID = (Get-AzureRmContext).Subscription.Id 4 | 5 | # Concatenate this number onto the resources that have to be globally unique. 6 | # You can set this to "" or to a specific value if you don't want it to be random. 7 | # This retrieves the first 6 digits of a random value. 8 | $randomValue = "$(Get-Random)".Substring(0,6) 9 | 10 | # Set the values for the resource names that don't have to be globally unique. 11 | $location = "West US" 12 | $resourceGroup = "ContosoResources" 13 | $iotHubConsumerGroup = "ContosoConsumers" 14 | $containerName = "contosoresults" 15 | 16 | # Create the resource group to be used 17 | # for all resources for this tutorial 18 | New-AzResourceGroup -Name $resourceGroup -Location $location 19 | 20 | # The IoT hub name must be globally unique, 21 | # so add a random value to the end. 22 | $iotHubName = "ContosoTestHub" + $randomValue 23 | Write-Host "IoT hub name is " $iotHubName 24 | 25 | # Create the IoT hub. 26 | New-AzIotHub -ResourceGroupName $resourceGroup ` 27 | -Name $iotHubName ` 28 | -SkuName "S1" ` 29 | -Location $location ` 30 | -Units 1 31 | 32 | # Add a consumer group to the IoT hub. 33 | Add-AzIotHubEventHubConsumerGroup -ResourceGroupName $resourceGroup ` 34 | -Name $iotHubName ` 35 | -EventHubConsumerGroupName $iotHubConsumerGroup 36 | 37 | # The storage account name must be globally unique, 38 | # so add a random value to the end. 39 | $storageAccountName = "contosostorage" + $randomValue 40 | Write-Host "storage account name is " $storageAccountName 41 | 42 | # Create the storage account to be used as a routing destination. 43 | # Save the context for the storage account 44 | # to be used when creating a container. 45 | $storageAccount = New-AzStorageAccount -ResourceGroupName $resourceGroup ` 46 | -Name $storageAccountName ` 47 | -Location $location ` 48 | -SkuName Standard_LRS ` 49 | -Kind Storage 50 | # Retrieve the connection string from the context. 51 | $storageConnectionString = $storageAccount.Context.ConnectionString 52 | Write-Host "storage connection string = " $storageConnectionString 53 | 54 | # Create the container in the storage account. 55 | New-AzStorageContainer -Name $containerName ` 56 | -Context $storageAccount.Context 57 | 58 | # The Service Bus namespace must be globally unique, 59 | # so add a random value to the end. 60 | $serviceBusNamespace = "ContosoSBNamespace" + $randomValue 61 | Write-Host "Service Bus namespace is " $serviceBusNamespace 62 | 63 | # Create the Service Bus namespace. 64 | New-AzServiceBusNamespace -ResourceGroupName $resourceGroup ` 65 | -Location $location ` 66 | -Name $serviceBusNamespace 67 | 68 | # The Service Bus queue name must be globally unique, 69 | # so add a random value to the end. 70 | $serviceBusQueueName = "ContosoSBQueue" + $randomValue 71 | Write-Host "Service Bus queue name is " $serviceBusQueueName 72 | 73 | # Create the Service Bus queue to be used as a routing destination. 74 | New-AzServiceBusQueue -ResourceGroupName $resourceGroup ` 75 | -Namespace $serviceBusNamespace ` 76 | -Name $serviceBusQueueName ` 77 | -EnablePartitioning $False 78 | 79 | ##### ROUTING FOR STORAGE ##### 80 | 81 | $endpointName = "ContosoStorageEndpoint" 82 | $endpointType = "azurestoragecontainer" 83 | $routeName = "ContosoStorageRoute" 84 | $condition = 'level="storage"' 85 | 86 | # Create the routing endpoint for storage. 87 | # The encoding can be AVRO or JSON. 88 | Add-AzIotHubRoutingEndpoint ` 89 | -ResourceGroupName $resourceGroup ` 90 | -Name $iotHubName ` 91 | -EndpointName $endpointName ` 92 | -EndpointType $endpointType ` 93 | -EndpointResourceGroup $resourceGroup ` 94 | -EndpointSubscriptionId $subscriptionId ` 95 | -ConnectionString $storageConnectionString ` 96 | -ContainerName $containerName ` 97 | -Encoding JSON 98 | 99 | # Create the route for the storage endpoint. 100 | Add-AzIotHubRoute ` 101 | -ResourceGroupName $resourceGroup ` 102 | -Name $iotHubName ` 103 | -RouteName $routeName ` 104 | -Source DeviceMessages ` 105 | -EndpointName $endpointName ` 106 | -Condition $condition ` 107 | -Enabled 108 | 109 | ##### ROUTING FOR SERVICE BUS QUEUE ##### 110 | 111 | # Create the authorization rule for the Service Bus queue. 112 | New-AzServiceBusAuthorizationRule ` 113 | -ResourceGroupName $resourceGroup ` 114 | -NamespaceName $serviceBusNamespace ` 115 | -Queue $serviceBusQueueName ` 116 | -Name "sbauthrule" ` 117 | -Rights @("Manage","Listen","Send") 118 | 119 | # Get the Service Bus Queue key. 120 | $sbqkey = Get-AzServiceBusKey ` 121 | -ResourceGroupName $resourceGroup ` 122 | -NamespaceName $serviceBusNamespace ` 123 | -Queue $servicebusQueueName ` 124 | -Name "sbauthrule" 125 | 126 | $endpointName = "ContosoSBQueueEndpoint" 127 | $endpointType = "servicebusqueue" 128 | $routeName = "ContosoSBQueueRoute" 129 | $condition = 'level="critical"' 130 | 131 | # If you experience problems while running this command, 132 | # it might be because it didn't have time to finish before 133 | # running the next line. To fix this, include this pause for 90 134 | # seconds before continuing. This gives it enough time to finish. 135 | 136 | # The IoT Hub team could change this to make the prior command 137 | # loop and check to see if it's finished before it continues (like the create-iot-hub cmdlet does), 138 | # but in case they don't fix it, putting the Start-Sleep command in here makes sure it works. 139 | Start-Sleep -Seconds 90 140 | 141 | # This command is the one that sometimes doesn't work. It's as if it doesn't have time to 142 | # finish before it moves to the next line. 143 | # The error from Add-AzIotHubRoutingEndpoint is "Operation returned an invalid status code 'BadRequest'". 144 | 145 | # This command adds the routing endpoint, using the connection string property from the key. 146 | # This will definitely work if you do the Sleep command first. 147 | Add-AzIotHubRoutingEndpoint ` 148 | -ResourceGroupName $resourceGroup ` 149 | -Name $iotHubName ` 150 | -EndpointName $endpointName ` 151 | -EndpointType $endpointType ` 152 | -EndpointResourceGroup $resourceGroup ` 153 | -EndpointSubscriptionId $subscriptionId ` 154 | -ConnectionString $sbqkey.PrimaryConnectionString 155 | 156 | # Set up the message route for the Service Bus queue endpoint. 157 | Add-AzIotHubRoute ` 158 | -ResourceGroupName $resourceGroup ` 159 | -Name $iotHubName ` 160 | -RouteName $routeName ` 161 | -Source DeviceMessages ` 162 | -EndpointName $endpointName ` 163 | -Condition $condition ` 164 | -Enabled 165 | -------------------------------------------------------------------------------- /iot-hub/Tutorials/Routing/SimulatedDevice/resources/template_iothub.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "randomValue": { 6 | "defaultValue": "[substring(uniqueString(utcNow()),0,8)]", 7 | "type": "string", 8 | "metadata": { 9 | "description": "Random alphanumeric string to make the assets have a unique name." 10 | } 11 | }, 12 | "subscriptionId": { 13 | "type": "string", 14 | "defaultValue": "[subscription().subscriptionid]", 15 | "metadata": { 16 | "description": "The subscription ID of the Azure subscription to deploy into." 17 | } 18 | }, 19 | "IoTHubName_in": { 20 | "type": "string", 21 | "defaultValue": "ContosoTestHub", 22 | "metadata": { 23 | "description": "The name of the IoT Hub to create." 24 | } 25 | }, 26 | "location": { 27 | "type": "string", 28 | "defaultValue": "westus", 29 | "metadata": { 30 | "description": "The datacenter to use for the deployment." 31 | } 32 | }, 33 | "consumer_group":{ 34 | "type": "string", 35 | "defaultValue": "ContosoConsumers", 36 | "metadata": { 37 | "description": "The consumer group to assign to the messages for use in ASA." 38 | } 39 | }, 40 | "sku_name": { 41 | "type": "string", 42 | "defaultValue": "S1", 43 | "metadata": { 44 | "description": "The SKU to use for the IoT Hub." 45 | } 46 | }, 47 | "sku_units": { 48 | "type": "string", 49 | "defaultValue": "1", 50 | "metadata": { 51 | "description": "The number of IoT Hub units." 52 | } 53 | }, 54 | "d2c_partitions": { 55 | "type": "string", 56 | "metadata": { 57 | "description": "Partitions used for the event stream." 58 | } 59 | }, 60 | "storageAccountName_in": { 61 | "type": "string", 62 | "defaultValue": "contosostorage", 63 | "metadata": { 64 | "description": "Name of storage account to be created." 65 | } 66 | }, 67 | "storageContainerName": { 68 | "type": "string", 69 | "defaultValue": "contosoresults", 70 | "metadata": { 71 | "description": "Name of the container in which to place the routed data." 72 | } 73 | }, 74 | "storage_endpoint": { 75 | "type": "string", 76 | "defaultValue": "ContosoStorageEndpoint", 77 | "metadata": { 78 | "description": "Name of the endpoint for the storage account." 79 | } 80 | }, 81 | "service_bus_namespace_in": { 82 | "type": "string", 83 | "defaultValue": "ContosoSBNamespace", 84 | "metadata": { 85 | "description": "Namespace of the service bus that has the queue to which messages are routed." 86 | } 87 | }, 88 | "service_bus_queue_in": { 89 | "type": "string", 90 | "defaultValue": "ContosoSBQueue", 91 | "metadata": { 92 | "description": "Name of the service bus queue to which to route messages." 93 | } 94 | }, 95 | "service_bus_queue_endpoint": { 96 | "type": "string", 97 | "defaultValue": "ContosoSBQueueEndpoint", 98 | "metadata": { 99 | "description": "Endpoint to use for routing messages to the service bus queue." 100 | } 101 | }, 102 | "AuthRules_sb_queue": { 103 | "type": "string", 104 | "defaultValue": "AuthRules_sb_queue", 105 | "metadata": { 106 | "description": "Authorization rules for the service bus queue." 107 | } 108 | } 109 | }, 110 | "variables": { 111 | "queueAuthorizationRuleResourceId": "[resourceId('Microsoft.ServiceBus/namespaces/queues/authorizationRules', variables('service_bus_namespace'), variables('service_bus_queue'), parameters('AuthRules_sb_queue'))]", 112 | "iotHubName": "[concat(parameters('IotHubName_in'),parameters('randomValue'))]", 113 | "storageAccountName": "[concat(parameters('storageAccountName_in'),parameters('randomValue'))]", 114 | "service_bus_namespace": "[concat(parameters('service_bus_namespace_in'),parameters('randomValue'))]", 115 | "service_bus_queue": "[concat(parameters('service_bus_queue_in'),parameters('randomValue'))]", 116 | "sbVersion": "2017-04-01" 117 | }, 118 | "resources": [ 119 | { 120 | "type": "Microsoft.Storage/storageAccounts", 121 | "name": "[variables('storageAccountName')]", 122 | "apiVersion": "2018-07-01", 123 | "location": "[parameters('location')]", 124 | "sku": { 125 | "name": "Standard_LRS", 126 | "tier": "Standard" 127 | }, 128 | "kind": "Storage", 129 | "properties": {}, 130 | "resources": [ 131 | { 132 | "type": "blobServices/containers", 133 | "apiVersion": "2018-07-01", 134 | "name": "[concat('default/', parameters('storageContainerName'))]", 135 | "properties": { 136 | "publicAccess": "None" 137 | } , 138 | "dependsOn": [ 139 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]" 140 | ] 141 | } 142 | ] 143 | }, 144 | { 145 | "type": "Microsoft.ServiceBus/namespaces", 146 | "comments": "The Sku should be 'Standard' for this tutorial.", 147 | "sku": { 148 | "name": "Standard", 149 | "tier": "Standard" 150 | }, 151 | "name": "[variables('service_bus_namespace')]", 152 | "apiVersion": "[variables('sbVersion')]", 153 | "location": "[parameters('location')]", 154 | "properties": { 155 | "provisioningState": "Succeeded", 156 | "metricId": "[concat('a4295411-5eff-4f81-b77e-276ab1ccda12:', variables('service_bus_namespace'))]", 157 | "serviceBusEndpoint": "[concat('https://', variables('service_bus_namespace'),'.servicebus.windows.net:443/')]", 158 | "status": "Active" 159 | }, 160 | "dependsOn": [] 161 | }, 162 | { 163 | "type": "Microsoft.ServiceBus/namespaces/queues", 164 | "name": "[concat(variables('service_bus_namespace'), '/', variables('service_bus_queue'))]", 165 | "apiVersion": "[variables('sbVersion')]", 166 | "location": "[parameters('location')]", 167 | "scale": null, 168 | "properties": {}, 169 | "dependsOn": [ 170 | "[resourceId('Microsoft.ServiceBus/namespaces', variables('service_bus_namespace'))]" 171 | ] 172 | }, 173 | { 174 | "apiVersion": "2018-04-01", 175 | "type": "Microsoft.Devices/IotHubs", 176 | "name": "[variables('IoTHubName')]", 177 | "location": "[parameters('location')]", 178 | "dependsOn": [ 179 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]", 180 | "[resourceId('Microsoft.ServiceBus/namespaces', variables('service_bus_namespace'))]", 181 | "[resourceId('Microsoft.ServiceBus/namespaces/queues', variables('service_bus_namespace'), variables('service_bus_queue'))]" 182 | ], 183 | "properties": { 184 | "eventHubEndpoints": { 185 | "events": { 186 | "retentionTimeInDays": 1, 187 | "partitionCount": "[parameters('d2c_partitions')]" 188 | } 189 | }, 190 | "routing": { 191 | "endpoints": { 192 | "serviceBusQueues": [ 193 | { 194 | "connectionString": "[Concat('Endpoint=sb://',variables('service_bus_namespace'),'.servicebus.windows.net/;SharedAccessKeyName=',parameters('AuthRules_sb_queue'),';SharedAccessKey=',listkeys(variables('queueAuthorizationRuleResourceId'),variables('sbVersion')).primaryKey,';EntityPath=',variables('service_bus_queue'))]", 195 | "name": "[parameters('service_bus_queue_endpoint')]", 196 | "subscriptionId": "[parameters('subscriptionId')]", 197 | "resourceGroup": "[resourceGroup().Name]" 198 | } 199 | ], 200 | "serviceBusTopics": [], 201 | "eventHubs": [], 202 | "storageContainers": [ 203 | { 204 | "connectionString": 205 | "[Concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]", 206 | "containerName": "[parameters('storageContainerName')]", 207 | "fileNameFormat": "{iothub}/{partition}/{YYYY}/{MM}/{DD}/{HH}/{mm}", 208 | "batchFrequencyInSeconds": 100, 209 | "maxChunkSizeInBytes": 104857600, 210 | "encoding": "avro", 211 | "name": "[parameters('storage_endpoint')]", 212 | "subscriptionId": "[parameters('subscriptionId')]", 213 | "resourceGroup": "[resourceGroup().Name]" 214 | } 215 | ] 216 | }, 217 | "routes": [ 218 | { 219 | "name": "ContosoStorageRoute", 220 | "source": "DeviceMessages", 221 | "condition": "level=\"storage\"", 222 | "endpointNames": [ 223 | "[parameters('storage_endpoint')]" 224 | ], 225 | "isEnabled": true 226 | }, 227 | { 228 | "name": "ContosoSBQueueRoute", 229 | "source": "DeviceMessages", 230 | "condition": "level=\"critical\"", 231 | "endpointNames": [ 232 | "[parameters('service_bus_queue_endpoint')]" 233 | ], 234 | "isEnabled": true 235 | } 236 | 237 | ], 238 | "fallbackRoute": { 239 | "name": "$fallback", 240 | "source": "DeviceMessages", 241 | "condition": "true", 242 | "endpointNames": [ 243 | "events" 244 | ], 245 | "isEnabled": true 246 | } 247 | }, 248 | "storageEndpoints": { 249 | "$default": { 250 | "sasTtlAsIso8601": "PT1H", 251 | "connectionString": "", 252 | "containerName": "" 253 | } 254 | }, 255 | "messagingEndpoints": { 256 | "fileNotifications": { 257 | "lockDurationAsIso8601": "PT1M", 258 | "ttlAsIso8601": "PT1H", 259 | "maxDeliveryCount": 10 260 | } 261 | }, 262 | "enableFileUploadNotifications": false, 263 | "cloudToDevice": { 264 | "maxDeliveryCount": 10, 265 | "defaultTtlAsIso8601": "PT1H", 266 | "feedback": { 267 | "lockDurationAsIso8601": "PT1M", 268 | "ttlAsIso8601": "PT1H", 269 | "maxDeliveryCount": 10 270 | } 271 | } 272 | }, 273 | "sku": { 274 | "name": "[parameters('sku_name')]", 275 | "capacity": "[parameters('sku_units')]" 276 | } 277 | }, 278 | { 279 | "type": "Microsoft.ServiceBus/namespaces/queues/authorizationRules", 280 | "name": "[concat(variables('service_bus_namespace'), '/', variables('service_bus_queue'), '/', parameters('AuthRules_sb_queue'))]", 281 | "apiVersion": "[variables('sbVersion')]", 282 | "location": "[parameters('location')]", 283 | "scale": null, 284 | "properties": { 285 | "rights": [ 286 | "Send" 287 | ] 288 | }, 289 | "dependsOn": [ 290 | "[resourceId('Microsoft.ServiceBus/namespaces', variables('service_bus_namespace'))]", 291 | "[resourceId('Microsoft.ServiceBus/namespaces/queues', variables('service_bus_namespace'), variables('service_bus_queue'))]" 292 | ] 293 | }, 294 | { 295 | "type": "Microsoft.Devices/IotHubs/eventHubEndpoints/ConsumerGroups", 296 | "name": "[concat(variables('iotHubName'), '/events/',parameters('consumer_group'))]", 297 | "apiVersion": "2018-04-01", 298 | "dependsOn": [ 299 | "[concat('Microsoft.Devices/Iothubs/', variables('iotHubName'))]" 300 | ] 301 | } 302 | ], 303 | "outputs": { 304 | "sbq_connectionString": { 305 | "type": "string", 306 | "value": "[Concat('Endpoint=sb://',variables('service_bus_namespace'),'.servicebus.windows.net/;SharedAccessKeyName=',parameters('AuthRules_sb_queue'),';SharedAccessKey=',listkeys(variables('queueAuthorizationRuleResourceId'),variables('sbVersion')).primaryKey,';EntityPath=',variables('service_bus_queue'))]" 307 | } 308 | } 309 | } -------------------------------------------------------------------------------- /iot-hub/Tutorials/Routing/SimulatedDevice/resources/template_iothub_parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "IoTHubName_in": { 6 | "value": "ContosoTestHub" 7 | }, 8 | "location": { 9 | "value": "westus" 10 | }, 11 | "consumer_group":{ 12 | "value": "ContosoConsumers" 13 | }, 14 | "sku_name": { 15 | "value": "S1" 16 | }, 17 | "sku_units": { 18 | "value": "1" 19 | }, 20 | "d2c_partitions": { 21 | "value": "4" 22 | }, 23 | "storageAccountName_in": { 24 | "value": "contosostorage" 25 | }, 26 | "storageContainerName": { 27 | "value": "contosoresults" 28 | }, 29 | "storage_endpoint": { 30 | "value": "ContosoStorageEndpoint" 31 | }, 32 | "service_bus_namespace_in": { 33 | "value": "ContosoSBNamespace" 34 | }, 35 | "service_bus_queue_in": { 36 | "value": "ContosoSBQueue" 37 | }, 38 | "service_bus_queue_endpoint": { 39 | "value": "ContosoSBQueueEndpoint" 40 | }, 41 | "AuthRules_sb_queue": { 42 | "value": "AuthRules_sb_queue" 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /iot-hub/Tutorials/Routing/SimulatedDevice/resources/template_messageenrichments.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "randomValue": { 6 | "defaultValue": "[substring(uniqueString(utcNow()),0,8)]", 7 | "type": "string", 8 | "metadata": { 9 | "description": "Random alphanumeric string to make the assets have a unique name." 10 | } 11 | }, 12 | "subscriptionId": { 13 | "type": "string", 14 | "defaultValue": "[subscription().subscriptionid]", 15 | "metadata": { 16 | "description": "The subscription ID of the Azure subscription to deploy into." 17 | } 18 | }, 19 | "IoTHubName_in": { 20 | "type": "string", 21 | "defaultValue": "ContosoTestHubMsgEn", 22 | "metadata": { 23 | "description": "The name of the IoT Hub to create." 24 | } 25 | }, 26 | "location": { 27 | "type": "string", 28 | "defaultValue": "westus2", 29 | "metadata": { 30 | "description": "The datacenter to use for the deployment." 31 | } 32 | }, 33 | "sku_name": { 34 | "type": "string", 35 | "defaultValue": "S1", 36 | "metadata": { 37 | "description": "The SKU to use for the IoT Hub." 38 | } 39 | }, 40 | "sku_units": { 41 | "type": "string", 42 | "defaultValue": "1", 43 | "metadata": { 44 | "description": "The number of IoT Hub units." 45 | } 46 | }, 47 | "d2c_partitions": { 48 | "type": "string", 49 | "defaultValue": "4", 50 | "metadata": { 51 | "description": "Partitions used for the event stream." 52 | } 53 | }, 54 | "storageAccountName_in": { 55 | "type": "string", 56 | "defaultValue": "contosostorage", 57 | "metadata": { 58 | "description": "Name of storage account to be created." 59 | } 60 | }, 61 | "containerName1": { 62 | "type": "string", 63 | "defaultValue": "original", 64 | "metadata": { 65 | "description": "Name of the container in which to place the routed data." 66 | } 67 | }, 68 | "containerName2": { 69 | "type": "string", 70 | "defaultValue": "enriched", 71 | "metadata": { 72 | "description": "Name of the container in which to place the routed data." 73 | } 74 | }, 75 | "routeName1": { 76 | "type": "string", 77 | "defaultValue": "ContosoStorageRouteOriginal", 78 | "metadata": { 79 | "description": "Name of the endpoint for the storage account." 80 | } 81 | }, 82 | "routeName2": { 83 | "type": "string", 84 | "defaultValue": "ContosoStorageRouteEnriched", 85 | "metadata": { 86 | "description": "Name of the endpoint for the storage account." 87 | } 88 | }, 89 | "endpointName1": { 90 | "type": "string", 91 | "defaultValue": "ContosoStorageEndpointOriginal", 92 | "metadata": { 93 | "description": "Name of the endpoint for the storage account." 94 | } 95 | }, 96 | "endpointName2": { 97 | "type": "string", 98 | "defaultValue": "ContosoStorageEndpointEnriched", 99 | "metadata": { 100 | "description": "Name of the endpoint for the storage account." 101 | } 102 | } 103 | }, 104 | "variables": { 105 | "iotHubName": "[concat(parameters('IotHubName_in'),parameters('randomValue'))]", 106 | "storageAccountName": "[concat(parameters('storageAccountName_in'),parameters('randomValue'))]" 107 | }, 108 | "resources": [ 109 | { 110 | "type": "Microsoft.Storage/storageAccounts", 111 | "name": "[variables('storageAccountName')]", 112 | "apiVersion": "2018-07-01", 113 | "location": "[parameters('location')]", 114 | "sku": { 115 | "name": "Standard_LRS", 116 | "tier": "Standard" 117 | }, 118 | "kind": "Storage", 119 | "properties": {}, 120 | "resources": [ 121 | { 122 | "type": "blobServices/containers", 123 | "apiVersion": "2018-07-01", 124 | "name": "[concat('default/', parameters('containerName1'))]", 125 | "properties": { 126 | "publicAccess": "None" 127 | } , 128 | "dependsOn": [ 129 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]" 130 | ] 131 | }, 132 | { 133 | "type": "blobServices/containers", 134 | "apiVersion": "2018-07-01", 135 | "name": "[concat('default/', parameters('containerName2'))]", 136 | "properties": { 137 | "publicAccess": "None" 138 | } , 139 | "dependsOn": [ 140 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]" 141 | ] 142 | } 143 | ] 144 | }, 145 | { 146 | "apiVersion": "2019-11-04", 147 | "type": "Microsoft.Devices/IotHubs", 148 | "name": "[variables('IoTHubName')]", 149 | "location": "[parameters('location')]", 150 | "dependsOn": [ 151 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]" 152 | ], 153 | "properties": { 154 | "eventHubEndpoints": { 155 | "events": { 156 | "retentionTimeInDays": 1, 157 | "partitionCount": "[parameters('d2c_partitions')]" 158 | } 159 | }, 160 | "routing": { 161 | "enrichments": [ 162 | { 163 | "key": "myIoTHub", 164 | "value": "$iothubname", 165 | "endpointNames": ["ContosoStorageEndpointEnriched"] 166 | }, 167 | { 168 | "key": "DeviceLocation", 169 | "value": "$twin.tags.location", 170 | "endpointNames": ["ContosoStorageEndpointEnriched"] 171 | }, 172 | { 173 | "key": "customerID", 174 | "value": "6ce345b8-1e4a-411e-9398-d34587459a3a", 175 | "endpointNames": ["ContosoStorageEndpointEnriched"] 176 | } 177 | ], 178 | "endpoints": { 179 | "serviceBusQueues": [], 180 | "serviceBusTopics": [], 181 | "eventHubs": [], 182 | "storageContainers": [ 183 | { 184 | "connectionString": 185 | "[Concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]", 186 | "containerName": "[parameters('containerName1')]", 187 | "fileNameFormat": "{iothub}/{partition}/{YYYY}/{MM}/{DD}/{HH}/{mm}", 188 | "batchFrequencyInSeconds": 100, 189 | "maxChunkSizeInBytes": 104857600, 190 | "encoding": "json", 191 | "name": "[parameters('endpointName1')]", 192 | "subscriptionId": "[parameters('subscriptionId')]", 193 | "resourceGroup": "[resourceGroup().Name]" 194 | }, 195 | { 196 | "connectionString": 197 | "[Concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]", 198 | "containerName": "[parameters('containerName2')]", 199 | "fileNameFormat": "{iothub}/{partition}/{YYYY}/{MM}/{DD}/{HH}/{mm}", 200 | "batchFrequencyInSeconds": 100, 201 | "maxChunkSizeInBytes": 104857600, 202 | "encoding": "json", 203 | "name": "[parameters('endpointName2')]", 204 | "subscriptionId": "[parameters('subscriptionId')]", 205 | "resourceGroup": "[resourceGroup().Name]" 206 | } 207 | ] 208 | }, 209 | "routes": [ 210 | { 211 | "name": "[parameters('routeName1')]", 212 | "source": "DeviceMessages", 213 | "condition": "level=\"storage\"", 214 | "endpointNames": [ 215 | "[parameters('endpointName1')]" 216 | ], 217 | "isEnabled": true 218 | }, 219 | { 220 | "name": "[parameters('routeName2')]", 221 | "source": "DeviceMessages", 222 | "condition": "level=\"storage\"", 223 | "endpointNames": [ 224 | "[parameters('endpointName2')]" 225 | ], 226 | "isEnabled": true 227 | } 228 | ], 229 | "fallbackRoute": { 230 | "name": "$fallback", 231 | "source": "DeviceMessages", 232 | "condition": "true", 233 | "endpointNames": [ 234 | "events" 235 | ], 236 | "isEnabled": true 237 | } 238 | }, 239 | "storageEndpoints": { 240 | "$default": { 241 | "sasTtlAsIso8601": "PT1H", 242 | "connectionString": "", 243 | "containerName": "" 244 | } 245 | }, 246 | "messagingEndpoints": { 247 | "fileNotifications": { 248 | "lockDurationAsIso8601": "PT1M", 249 | "ttlAsIso8601": "PT1H", 250 | "maxDeliveryCount": 10 251 | } 252 | }, 253 | "enableFileUploadNotifications": false, 254 | "cloudToDevice": { 255 | "maxDeliveryCount": 10, 256 | "defaultTtlAsIso8601": "PT1H", 257 | "feedback": { 258 | "lockDurationAsIso8601": "PT1M", 259 | "ttlAsIso8601": "PT1H", 260 | "maxDeliveryCount": 10 261 | } 262 | } 263 | }, 264 | "sku": { 265 | "name": "[parameters('sku_name')]", 266 | "capacity": "[parameters('sku_units')]" 267 | } 268 | } 269 | ] 270 | } -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /provisioning/Samples/device/ComputeDerivedSymmetricKeySample/readme.md: -------------------------------------------------------------------------------- 1 | # ComputeDerivedSymmetricKeySample 2 | 3 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [ComputeDerviedSymmetricKeySample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /provisioning/Samples/device/SymmetricKeySample/readme.md: -------------------------------------------------------------------------------- 1 | # SymmetricKeySample 2 | 3 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [SymmetricKeySample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /provisioning/Samples/device/TpmSample/readme.md: -------------------------------------------------------------------------------- 1 | # Provisioning Device Client Sample - TPM Attestation 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [TpmSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). 5 | -------------------------------------------------------------------------------- /provisioning/Samples/device/X509Sample/readme.md: -------------------------------------------------------------------------------- 1 | # Provisioning Device Client Sample - X.509 Attestation 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [X509Sample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). 5 | -------------------------------------------------------------------------------- /provisioning/Samples/device/readme.md: -------------------------------------------------------------------------------- 1 | # Provisioning Device Client Sample - Microsoft Azure IoT SDK for .NET 2 | 3 | The DPS samples that previously existed here have been removed since this sample repository will be retired and archived. 4 | 5 | Please see here for the up to date [ProvisioningSamples](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). 6 | -------------------------------------------------------------------------------- /provisioning/Samples/service/BulkOperationSample/readme.md: -------------------------------------------------------------------------------- 1 | # BulkOperationSample 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [BulkOperationSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /provisioning/Samples/service/CleanupEnrollmentsSample/readme.md: -------------------------------------------------------------------------------- 1 | # CleanupEnrollmentsSample 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [CleanupEnrollmentsSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /provisioning/Samples/service/EnrollmentGroupSample/readme.md: -------------------------------------------------------------------------------- 1 | # EnrollmentGroupSample 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [EnrollmentGroupSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /provisioning/Samples/service/EnrollmentSample/readme.md: -------------------------------------------------------------------------------- 1 | # EnrollmentSample 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [EnrollmentSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /provisioning/Samples/service/GroupCertificateVerificationSample/readme.md: -------------------------------------------------------------------------------- 1 | # GroupCertificateVerificationSample 2 | The sample that previously existed here has been removed since this sample repository will be retired and archived. 3 | 4 | Please see here for the up to date [GroupCertificateVerificationSample](https://github.com/Azure/azure-iot-sdk-csharp/blob/main/readme.md#samples). -------------------------------------------------------------------------------- /vsts/CredScanSuppressions.json: -------------------------------------------------------------------------------- 1 | { 2 | "tool": "Credential Scanner", 3 | "suppressions": [ 4 | { 5 | "placeholder": "dGVzdFN0cmluZzE=", 6 | "_justification": "Dummy secret used in unit tests, it is fake" 7 | }, 8 | { 9 | "placeholder": "dGVzdFN0cmluZzI=", 10 | "_justification": "Dummy secret used in unit tests, it is fake" 11 | }, 12 | { 13 | "placeholder": "dGVzdFN0cmluZzM=", 14 | "_justification": "Dummy secret used in unit tests, it is fake" 15 | }, 16 | { 17 | "placeholder": "dGVzdFN0cmluZzQ=", 18 | "_justification": "Dummy secret used in unit tests, it is fake" 19 | }, 20 | { 21 | "placeholder": "dGVzdFN0cmluZzU=", 22 | "_justification": "Dummy secret used in unit tests, it is fake" 23 | }, 24 | { 25 | "placeholder": "dGVzdFN0cmluZzY=", 26 | "_justification": "Dummy secret used in unit tests, it is fake" 27 | }, 28 | { 29 | "placeholder": "notsafe", 30 | "_justification": "Dummy secret used in unit tests, it is fake" 31 | } 32 | ] 33 | } -------------------------------------------------------------------------------- /vsts/vsts.yaml: -------------------------------------------------------------------------------- 1 | name: $(BuildID)_$(BuildDefinitionName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r) 2 | 3 | # https://docs.microsoft.com/azure/devops/pipelines/process/runtime-parameters 4 | parameters: 5 | - name: jobTimeoutInMinutes 6 | displayName: Timeout for each job 7 | type: number 8 | default: 75 9 | - name: tests 10 | displayName: Run all tests, include clearing (if unchecked, clear service resources only). 11 | type: boolean 12 | default: true 13 | 14 | variables: 15 | ${{ if parameters.tests }}: 16 | testConfig: "-run" 17 | ${{ else }}: 18 | testConfig: "-clear" 19 | 20 | resources: 21 | - repo: self 22 | clean: true 23 | 24 | jobs: 25 | ### Linux build ### 26 | - job: LINUX 27 | displayName: Linux (timeout=${{ parameters.jobTimeoutInMinutes }}mins) 28 | condition: succeeded() 29 | pool: 30 | vmImage: 'ubuntu-latest' 31 | timeoutInMinutes: ${{ parameters.jobTimeoutInMinutes }} 32 | steps: 33 | - task: UseDotNet@2 34 | displayName: 'Use .NET 6.0 SDK' 35 | inputs: 36 | version: 6.0.x 37 | performMultiLevelLookup: true 38 | installationPath: $(Agent.ToolsDirectory)/dotnet 39 | - task: UseDotNet@2 40 | displayName: 'Use .NET 5.0 SDK' 41 | inputs: 42 | version: 5.0.x 43 | performMultiLevelLookup: true 44 | installationPath: $(Agent.ToolsDirectory)/dotnet 45 | - task: UseDotNet@2 46 | displayName: 'Use .NET Core 3.1 SDK' 47 | inputs: 48 | version: 3.1.x 49 | performMultiLevelLookup: true 50 | installationPath: $(Agent.ToolsDirectory)/dotnet 51 | - task: UseDotNet@2 52 | displayName: 'Use .NET Core 2.1 SDK' 53 | inputs: 54 | version: 2.1.x 55 | performMultiLevelLookup: true 56 | installationPath: $(Agent.ToolsDirectory)/dotnet 57 | 58 | - powershell: ./build.ps1 -clean -configuration Release -build $(testConfig) 59 | displayName: build and run 60 | env: 61 | # Environment variables for IoT hub device samples 62 | IOTHUB_DEVICE_CONN_STRING: $(IOTHUB-DEVICE-CONN-STRING) 63 | IOTHUB_MODULE_CONN_STRING: $(IOTHUB-MODULE-CONN-STRING) 64 | PNP_TC_DEVICE_CONN_STRING: $(PNP-TC-DEVICE-CONN-STRING) 65 | PNP_THERMOSTAT_DEVICE_CONN_STRING: $(PNP-THERMOSTAT-DEVICE-CONN-STRING) 66 | 67 | # Environment variables for IoT hub service samples 68 | IOTHUB_CONNECTION_STRING: $(IOTHUB-CONNECTION-STRING) 69 | IOTHUB_X509_DEVICE_PFX_THUMBPRINT: $(IOTHUB-X509-DEVICE-PFX-THUMBPRINT) 70 | STORAGE_ACCOUNT_CONNECTION_STRING: $(STORAGE-ACCOUNT-CONNECTION-STRING) 71 | FAR_AWAY_IOTHUB_CONNECTION_STRING: $(FAR-AWAY-IOTHUB-CONNECTION-STRING) 72 | MSFT_TENANT_ID: $(MSFT-TENANT-ID) 73 | E2E_TEST_AAD_APP_CLIENT_ID: $(E2E-TEST-AAD-APP-CLIENT-ID) 74 | E2E_TEST_AAD_APP_CLIENT_SECRET: $(E2E-TEST-AAD-APP-CLIENT-SECRET) 75 | IOT_HUB_SAS_KEY: $(IOTHUB-SAS-KEY) 76 | IOT_HUB_SAS_KEY_NAME: $(IOTHUB-SAS-KEY-NAME) 77 | 78 | # PATH-TO-DEVICE-PREFIX-FOR-DELETION-FILE is a variable configured on the pipeline. The possible values are: csharp_devices_list.csv, csharp_samples_devices_list.csv. 79 | # The value of this variable determines whether to delete devices created by the sample or e2e tests. 80 | # csharp_devices_list.csv contains the prefixes of devices created by e2e tests. 81 | # csharp_samples_devices_list.csv contains the prefixes of devices created by samples. 82 | PATH_TO_DEVICE_PREFIX_FOR_DELETION_FILE: $(PATH-TO-DEVICE-PREFIX-FOR-DELETION-FILE) 83 | 84 | # Environment variables for DPS device samples 85 | DPS_IDSCOPE: $(DPS-IDSCOPE) 86 | DPS_SYMMETRIC_KEY_INDIVIDUAL_ENROLLMENT_REGISTRATION_ID : $(DPS-SYMMETRIC-KEY-INDIVIDUAL-ENROLLMENT-REGISTRATION-ID) 87 | DPS_SYMMETRIC_KEY_INDIVIDUAL_ENROLLEMNT_PRIMARY_KEY : $(DPS-SYMMETRIC-KEY-INDIVIDUAL-ENROLLEMNT-PRIMARY-KEY) 88 | 89 | # Environment variables for DPS service samples 90 | PROVISIONING_CONNECTION_STRING: $(PROVISIONING-CONNECTION-STRING) 91 | 92 | - task: ComponentGovernanceComponentDetection@0 93 | displayName: Component Governance Detection 94 | inputs: 95 | scanType: 'Register' 96 | verbosity: 'Verbose' 97 | alertWarningLevel: 'Low' # The task will present a warning, but will not cause the build to fail 98 | condition: always() 99 | 100 | ### Windows build ### 101 | - job: WINDOWS 102 | displayName: Windows (timeout=${{ parameters.jobTimeoutInMinutes }}mins) 103 | # Since the samples run against the same Azure resources, CRUD operations will fight for the same resources. 104 | # So, the builds have been serialized. Comment out the line below to run them in parallel. 105 | dependsOn: LINUX 106 | condition: succeeded() 107 | pool: 108 | vmImage: 'windows-latest' 109 | timeoutInMinutes: ${{ parameters.jobTimeoutInMinutes }} 110 | steps: 111 | - task: UseDotNet@2 112 | displayName: 'Use .NET 6.0 SDK' 113 | inputs: 114 | version: 6.0.x 115 | performMultiLevelLookup: true 116 | installationPath: $(Agent.ToolsDirectory)/dotnet 117 | - task: UseDotNet@2 118 | displayName: 'Use .NET 5.0 SDK' 119 | inputs: 120 | version: 5.0.x 121 | performMultiLevelLookup: true 122 | installationPath: $(Agent.ToolsDirectory)/dotnet 123 | - task: UseDotNet@2 124 | displayName: 'Use .NET Core 3.1 SDK' 125 | inputs: 126 | version: 3.1.x 127 | performMultiLevelLookup: true 128 | installationPath: $(Agent.ToolsDirectory)/dotnet 129 | - task: UseDotNet@2 130 | displayName: 'Use .NET Core 2.1 SDK' 131 | inputs: 132 | version: 2.1.x 133 | performMultiLevelLookup: true 134 | installationPath: $(Agent.ToolsDirectory)/dotnet 135 | 136 | - powershell: ./build.ps1 -clean -configuration Release -build $(testConfig) 137 | displayName: build and run 138 | env: 139 | # Environment variables for IoT hub device samples 140 | IOTHUB_DEVICE_CONN_STRING: $(IOTHUB-DEVICE-CONN-STRING) 141 | IOTHUB_MODULE_CONN_STRING: $(IOTHUB-MODULE-CONN-STRING) 142 | PNP_TC_DEVICE_CONN_STRING: $(PNP-TC-DEVICE-CONN-STRING) 143 | PNP_THERMOSTAT_DEVICE_CONN_STRING: $(PNP-THERMOSTAT-DEVICE-CONN-STRING) 144 | 145 | # Environment variables for IoT hub service samples 146 | IOTHUB_CONNECTION_STRING: $(IOTHUB-CONNECTION-STRING) 147 | IOTHUB_X509_DEVICE_PFX_THUMBPRINT: $(IOTHUB-X509-DEVICE-PFX-THUMBPRINT) 148 | STORAGE_ACCOUNT_CONNECTION_STRING: $(STORAGE-ACCOUNT-CONNECTION-STRING) 149 | FAR_AWAY_IOTHUB_CONNECTION_STRING: $(FAR-AWAY-IOTHUB-CONNECTION-STRING) 150 | MSFT_TENANT_ID: $(MSFT-TENANT-ID) 151 | E2E_TEST_AAD_APP_CLIENT_ID: $(E2E-TEST-AAD-APP-CLIENT-ID) 152 | E2E_TEST_AAD_APP_CLIENT_SECRET: $(E2E-TEST-AAD-APP-CLIENT-SECRET) 153 | IOT_HUB_SAS_KEY: $(IOTHUB-SAS-KEY) 154 | IOT_HUB_SAS_KEY_NAME: $(IOTHUB-SAS-KEY-NAME) 155 | 156 | # PATH-TO-DEVICE-PREFIX-FOR-DELETION-FILE is a variable configured on the pipeline. The possible values are: csharp_devices_list.csv, csharp_samples_devices_list.csv. 157 | # The value of this variable determines whether to delete devices created by the sample or e2e tests. 158 | # csharp_devices_list.csv contains the prefixes of devices created by e2e tests. 159 | # csharp_samples_devices_list.csv contains the prefixes of devices created by samples. 160 | PATH_TO_DEVICE_PREFIX_FOR_DELETION_FILE: $(PATH-TO-DEVICE-PREFIX-FOR-DELETION-FILE) 161 | 162 | # Environment variables for DPS device samples 163 | DPS_IDSCOPE: $(DPS-IDSCOPE) 164 | DPS_SYMMETRIC_KEY_INDIVIDUAL_ENROLLMENT_REGISTRATION_ID : $(DPS-SYMMETRIC-KEY-INDIVIDUAL-ENROLLMENT-REGISTRATION-ID) 165 | DPS_SYMMETRIC_KEY_INDIVIDUAL_ENROLLEMNT_PRIMARY_KEY : $(DPS-SYMMETRIC-KEY-INDIVIDUAL-ENROLLEMNT-PRIMARY-KEY) 166 | 167 | # Environment variables for DPS service samples 168 | PROVISIONING_CONNECTION_STRING: $(PROVISIONING-CONNECTION-STRING) 169 | 170 | - task: ComponentGovernanceComponentDetection@0 171 | displayName: Component Governance Detection 172 | inputs: 173 | scanType: 'Register' 174 | verbosity: 'Verbose' 175 | alertWarningLevel: 'Low' # The task will present a warning, but will not cause the build to fail 176 | condition: always() 177 | --------------------------------------------------------------------------------