0

我想向 IoTHub 中已知的设备发送云到设备消息 (C2D)。我在代码中使用 SERVICE 策略。发送从控制台应用程序(现在)或以后的 WebApi 发生。所以代码不会在设备上运行!

我想使用 SAS 令牌连接到期,而不是连接设备的对称密钥。我创建了以下代码:

一个助手类:

..
using Microsoft.Azure.Devices;
using Microsoft.Azure.Devices.Common.Security;
..

public static class ServiceClientSasConnectionHelper
{
    public static string GetSasConnectionString(SasTokenModel sasTokenModel)
    {
        var sasToken = GetSasToken(sasTokenModel);
        var connectionString = string.Empty;
        if (!string.IsNullOrEmpty(sasTokenModel.PolicyName))
            connectionString = IotHubConnectionStringBuilder.Create(sasTokenModel.HostName, AuthenticationMethodFactory.CreateAuthenticationWithSharedAccessPolicyToken(sasTokenModel.PolicyName, sasToken)).ToString();
        else
            connectionString = $"HostName={sasTokenModel.HostName};DeviceId={sasTokenModel.DeviceId};SharedAccessSignature={sasToken}";
        return connectionString;
    }

    private static string GetSasToken(SasTokenModel sasTokenModel)
    {
        var sasBuilder = new SharedAccessSignatureBuilder
        {
            Key = sasTokenModel.SigninKey,
            Target = $"{sasTokenModel.HostName}/devices/{sasTokenModel.DeviceId}",
            TimeToLive = TimeSpan.FromMinutes(sasTokenModel.TokenLifeTimeInMinutes)
        };

        var sasToken = sasBuilder.ToSignature();

        if (!string.IsNullOrEmpty(sasTokenModel.PolicyName))
            sasToken += $"&skn={sasTokenModel.PolicyName}";

        return sasToken;
    }
}

它是从 PROGRAM.CS 调用的:

var policyName = string.Empty;
policyName = ConfigHelper.GetPolicyName();  //service
var hostName = ConfigHelper.GetIotUri(); //companyname-Tenant2Display.azure-devices.net
var policyKey = ConfigHelper.GetPolicyKey(); // primarary key from Portal

var sasTokenModel = new SasTokenModel
{
    DeviceId = WebUtility.UrlEncode(deviceKeyPair.Id), //DeviceId
    SigninKey = string.IsNullOrEmpty(policyName) ? deviceKeyPair.Key : policyKey,
    HostName = hostName,
    PolicyName = policyName,
    TokenLifeTimeInMinutes = 5
};
var connString = ServiceClientSasConnectionHelper.GetSasConnectionString(sasTokenModel);
var serviceClient = ServiceClient.CreateFromConnectionString(connString);
await serviceClient.SendAsync(deviceId, commandMessage);

调用 SendAsync 时,我收到一个错误,并显示以下消息:

\r\n跟踪 ID:fee6f860bdff42faa7cad8f81095223e-G:10-TimeStamp:04/19/2017 21:09:32

在属性 Code 的异常中,值为:Microsoft.Azure.Devices.Common.Exceptions.ErrorCode.InvalidErrorCode

堆栈跟踪:

在 Microsoft.Azure.Devices.AmqpServiceClient.d__28.MoveNext() --- 从先前引发异常的位置结束堆栈跟踪--- 在 System.Runtime 的 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)。 CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at TelemetrySender.Service.Sender.d__1.MoveNext() in C:\repo\TelemetrySender.cs:line 34

我在 de service 部分查看了 Github 存储库“azure-iot-sdk-csharp”,但找不到此错误的原因。我确实看到了错误消息的设置位置,但我不明白为什么。

谁能帮助我?

4

1 回答 1

0

我想将云到设备消息 (C2D) 发送到设备...我想使用 SAS 令牌连接到期,而不是连接设备的对称密钥

您无法使用设备级凭据发送云到设备消息。您需要使用 IoT 中心级别的凭据。

因此,您需要删除/devices/{sasTokenModel.DeviceId}. 最终的SAS 令牌将具有以下格式TargetGetSasToken()

SharedAccessSignature sig={signature-string}&se={expiry}&skn={policyName}&sr={URL-encoded-resourceURI}

我无法重现您的问题。我在台式机上测试,操作系统版本是 10.0.14393。

但是我可以使用您的不完整代码和正确的 SAS 令牌格式(前面提到)成功发送 Cloud-To-Device 消息。你可以参考一下。

于 2017-04-20T08:32:20.923 回答