Skip to content

Commit edc8728

Browse files
authored
Add cmdlet to invoke device method (#11472)
1 parent d9dd75c commit edc8728

File tree

11 files changed

+1147
-517
lines changed

11 files changed

+1147
-517
lines changed

src/IotHub/IotHub.Test/ScenarioTests/IotHubDPDeviceTests.ps1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ function Test-AzureRmIotHubDeviceLifecycle
8787
Assert-True { $updateddevice1twin3.DeviceId -eq $device1}
8888
Assert-True { $updateddevice1twin3.tags.Count -eq 1}
8989

90+
# Invoke direct method on device
91+
$errorMessage = 'Timed out waiting for device to connect.'
92+
Assert-ThrowsContains { Invoke-AzIotHubDeviceMethod -ResourceGroupName $ResourceGroupName -IotHubName $IotHubName -DeviceId $device1 -Name "SetTelemetryInterval" } $errorMessage
93+
9094
# Get all devices
9195
$devices = Get-AzIotHubDevice -ResourceGroupName $ResourceGroupName -IotHubName $IotHubName
9296
Assert-True { $devices.Count -eq 3}

src/IotHub/IotHub.Test/SessionRecords/Microsoft.Azure.Commands.IotHub.Test.ScenarioTests.IotHubDPDeviceTests/TestAzureIotHubDeviceLifecycle.json

Lines changed: 699 additions & 516 deletions
Large diffs are not rendered by default.

src/IotHub/IotHub/Az.IotHub.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ CmdletsToExport = 'Add-AzIotHubKey', 'Get-AzIotHubEventHubConsumerGroup',
101101
'Set-AzIotHubDeviceParent', 'Add-AzIotHubDeviceChildren',
102102
'Remove-AzIotHubDeviceChildren', 'Get-AzIotHubDeviceChildren',
103103
'Get-AzIotHubDistributedTracing', 'Set-AzIotHubDistributedTracing',
104-
'Get-AzIotHubDeviceTwin', 'Update-AzIotHubDeviceTwin'
104+
'Get-AzIotHubDeviceTwin', 'Update-AzIotHubDeviceTwin', 'Invoke-AzIotHubDeviceMethod'
105105
# Variables to export from this module
106106
# VariablesToExport = @()
107107

src/IotHub/IotHub/ChangeLog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
* Manage IoT device twin configuration, New cmdlets are:
2222
- `Get-AzIotHubDeviceTwin`
2323
- `Update-AzIotHubDeviceTwin`
24+
* Added cmdlet to invoke direct method on a device in an Iot Hub.
2425

2526
## Version 2.3.0
2627
* Added support to manage distributed settings per-device. New Cmdlets are:

src/IotHub/IotHub/IotHub.format.ps1xml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,5 +965,27 @@
965965
</ListEntries>
966966
</ListControl>
967967
</View>
968+
<View>
969+
<Name>
970+
Microsoft.Azure.Commands.Management.IotHub.Models.PSCloudToDeviceMethodResult
971+
</Name>
972+
<ViewSelectedBy>
973+
<TypeName>Microsoft.Azure.Commands.Management.IotHub.Models.PSCloudToDeviceMethodResult</TypeName>
974+
</ViewSelectedBy>
975+
<ListControl>
976+
<ListEntries>
977+
<ListEntry>
978+
<ListItems>
979+
<ListItem>
980+
<PropertyName>Status</PropertyName>
981+
</ListItem>
982+
<ListItem>
983+
<PropertyName>Payload</PropertyName>
984+
</ListItem>
985+
</ListItems>
986+
</ListEntry>
987+
</ListEntries>
988+
</ListControl>
989+
</View>
968990
</ViewDefinitions>
969991
</Configuration>
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
namespace Microsoft.Azure.Commands.Management.IotHub
16+
{
17+
using System;
18+
using System.Collections.Generic;
19+
using System.Management.Automation;
20+
using Microsoft.Azure.Commands.Management.IotHub.Common;
21+
using Microsoft.Azure.Commands.Management.IotHub.Models;
22+
using Microsoft.Azure.Devices;
23+
using Microsoft.Azure.Management.IotHub;
24+
using Microsoft.Azure.Management.IotHub.Models;
25+
using Microsoft.WindowsAzure.Commands.Utilities.Common;
26+
using ResourceManager.Common.ArgumentCompleters;
27+
28+
[Cmdlet("Invoke", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "IotHubDeviceMethod", DefaultParameterSetName = ResourceParameterSet, SupportsShouldProcess = true)]
29+
[OutputType(typeof(PSCloudToDeviceMethodResult))]
30+
public class InvokeAzIotHubDeviceMethod : IotHubBaseCmdlet
31+
{
32+
private const string ResourceIdParameterSet = "ResourceIdSet";
33+
private const string ResourceParameterSet = "ResourceSet";
34+
private const string InputObjectParameterSet = "InputObjectSet";
35+
36+
[Parameter(Position = 0, Mandatory = true, ParameterSetName = InputObjectParameterSet, ValueFromPipeline = true, HelpMessage = "IotHub object")]
37+
[ValidateNotNullOrEmpty]
38+
public PSIotHub InputObject { get; set; }
39+
40+
[Parameter(Position = 0, Mandatory = true, ParameterSetName = ResourceIdParameterSet, ValueFromPipelineByPropertyName = true, HelpMessage = "IotHub Resource Id")]
41+
[ValidateNotNullOrEmpty]
42+
[ResourceIdCompleter("Microsoft.Devices/IotHubs")]
43+
public string ResourceId { get; set; }
44+
45+
[Parameter(Position = 0, Mandatory = true, ParameterSetName = ResourceParameterSet, HelpMessage = "Name of the Resource Group")]
46+
[ValidateNotNullOrEmpty]
47+
[ResourceGroupCompleter]
48+
public string ResourceGroupName { get; set; }
49+
50+
[Parameter(Position = 1, Mandatory = true, ParameterSetName = ResourceParameterSet, HelpMessage = "Name of the Iot Hub")]
51+
[ValidateNotNullOrEmpty]
52+
public string IotHubName { get; set; }
53+
54+
[Parameter(Position = 1, Mandatory = true, ParameterSetName = InputObjectParameterSet, HelpMessage = "Target Device Id.")]
55+
[Parameter(Position = 1, Mandatory = true, ParameterSetName = ResourceIdParameterSet, HelpMessage = "Target Device Id.")]
56+
[Parameter(Position = 2, Mandatory = true, ParameterSetName = ResourceParameterSet, HelpMessage = "Target Device Id.")]
57+
[ValidateNotNullOrEmpty]
58+
public string DeviceId { get; set; }
59+
60+
[Parameter(Mandatory = true, HelpMessage = "The name of the method to invoke on this device.")]
61+
public string Name { get; set; }
62+
63+
[Parameter(Mandatory = false, HelpMessage = "The payload for the method to invoke on this device.")]
64+
public string Payload { get; set; }
65+
66+
[Parameter(Mandatory = false, HelpMessage = "Number of seconds to wait until a result is received from the direct method. Default is 10.")]
67+
public int ResponseTimeOut { get; set; }
68+
69+
[Parameter(Mandatory = false, HelpMessage = "Number of seconds to wait until a connection is successfully made. Default is 10.")]
70+
[ValidateRange(10, 300)]
71+
public int ConnectionTimeOut { get; set; }
72+
73+
public override void ExecuteCmdlet()
74+
{
75+
if (ShouldProcess(this.IotHubName, Properties.Resources.InvokeIotHubDeviceMethod))
76+
{
77+
IotHubDescription iotHubDescription;
78+
if (ParameterSetName.Equals(InputObjectParameterSet))
79+
{
80+
this.ResourceGroupName = this.InputObject.Resourcegroup;
81+
this.IotHubName = this.InputObject.Name;
82+
iotHubDescription = IotHubUtils.ConvertObject<PSIotHub, IotHubDescription>(this.InputObject);
83+
}
84+
else
85+
{
86+
if (ParameterSetName.Equals(ResourceIdParameterSet))
87+
{
88+
this.ResourceGroupName = IotHubUtils.GetResourceGroupName(this.ResourceId);
89+
this.IotHubName = IotHubUtils.GetIotHubName(this.ResourceId);
90+
}
91+
92+
iotHubDescription = this.IotHubClient.IotHubResource.Get(this.ResourceGroupName, this.IotHubName);
93+
}
94+
95+
IEnumerable<SharedAccessSignatureAuthorizationRule> authPolicies = this.IotHubClient.IotHubResource.ListKeys(this.ResourceGroupName, this.IotHubName);
96+
SharedAccessSignatureAuthorizationRule policy = IotHubUtils.GetPolicy(authPolicies, PSAccessRights.ServiceConnect);
97+
PSIotHubConnectionString psIotHubConnectionString = IotHubUtils.ToPSIotHubConnectionString(policy, iotHubDescription.Properties.HostName);
98+
ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(psIotHubConnectionString.PrimaryConnectionString);
99+
100+
if (!this.IsParameterBound(c => c.ResponseTimeOut))
101+
{
102+
this.ResponseTimeOut = 10;
103+
}
104+
105+
if (!this.IsParameterBound(c => c.ConnectionTimeOut))
106+
{
107+
this.ConnectionTimeOut = 10;
108+
}
109+
110+
CloudToDeviceMethod method = new CloudToDeviceMethod(this.Name, new TimeSpan(0, 0, this.ResponseTimeOut), new TimeSpan(0, 0, this.ConnectionTimeOut));
111+
if (this.IsParameterBound(c => c.Payload))
112+
{
113+
method = method.SetPayloadJson(this.Payload);
114+
}
115+
116+
CloudToDeviceMethodResult result = serviceClient.InvokeDeviceMethodAsync(this.DeviceId, method).GetAwaiter().GetResult();
117+
PSCloudToDeviceMethodResult psCloudToDeviceMethodResult = new PSCloudToDeviceMethodResult()
118+
{
119+
Status = result.Status,
120+
Payload = result.GetPayloadAsJson()
121+
};
122+
this.WriteObject(psCloudToDeviceMethodResult);
123+
}
124+
}
125+
}
126+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright Microsoft Corporation
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
// http://www.apache.org/licenses/LICENSE-2.0
6+
// Unless required by applicable law or agreed to in writing, software
7+
// distributed under the License is distributed on an "AS IS" BASIS,
8+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
// See the License for the specific language governing permissions and
10+
// limitations under the License.
11+
// ----------------------------------------------------------------------------------
12+
13+
namespace Microsoft.Azure.Commands.Management.IotHub.Models
14+
{
15+
/// <summary>
16+
/// Represents the Device Method Invocation Results.
17+
/// </summary>
18+
19+
public class PSCloudToDeviceMethodResult
20+
{
21+
/// <summary>
22+
/// Gets or sets the status of device method invocation.
23+
/// </summary>
24+
public int Status { get; set; }
25+
26+
/// <summary>
27+
/// Gets or sets the result payload of device method invocation.
28+
/// </summary>
29+
public string Payload { get; set; }
30+
}
31+
}

src/IotHub/IotHub/Properties/Resources.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/IotHub/IotHub/Properties/Resources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,4 +222,7 @@
222222
<data name="UpdateIotHubDeviceTwin" xml:space="preserve">
223223
<value>Update Device Twin</value>
224224
</data>
225+
<data name="InvokeIotHubDeviceMethod" xml:space="preserve">
226+
<value>Invoke Direct Method on a device</value>
227+
</data>
225228
</root>

src/IotHub/IotHub/help/Az.IotHub.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ Get information on all the endpoints for your IoT Hub
101101
### [Get-AzIotHubValidSku](Get-AzIotHubValidSku.md)
102102
Gets all valid skus that this IotHub can transition to.
103103

104+
### [Invoke-AzIotHubDeviceMethod](Invoke-AzIotHubDeviceMethod.md)
105+
Invoke a direct method on a device.
106+
104107
### [Invoke-AzIotHubManualFailover](Invoke-AzIotHubManualFailover.md)
105108
Invoke failover process for the IoT Hub to the geo-paired disaster recovery region.
106109

0 commit comments

Comments
 (0)