InvalidErrorCode при отправке сообщения C2D через Центр Интернета вещей с токеном SAS

Я хочу отправить сообщение «облако на устройство» (C2D) на устройство, известное в IoTHub. Я использую политику 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Идентификатор отслеживания:fee6f860bdff42faa7cad8f81095223e-G:10-TimeStamp:19/04/2017 21:09:32

В исключении для свойства Code значение: Microsoft.Azure.Devices.Common.Exceptions.ErrorCode.InvalidErrorCode.

Трассировки стека:

в Microsoft.Azure.Devices.AmqpServiceClient.d__28.MoveNext() --- Конец трассировки стека из предыдущего места, где было выдано исключение --- в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(задача задачи) в System.Runtime. CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (задача задачи) в System.Runtime.CompilerServices.TaskAwaiter.GetResult() в TelemetrySender.Service.Sender.d__1.MoveNext() в C:\repo\TelemetrySender.cs:строка 34

Я заглянул в репозиторий Github "azure-iot-sdk-csharp" в разделе службы, но не могу найти причину этой ошибки. Я вижу, где установлено сообщение об ошибке, но я не понимаю, почему.

Любой, кто может мне помочь?


person Sven    schedule 19.04.2017    source источник
comment
Какая платформа и версия ОС?   -  person Rita Han    schedule 20.04.2017
comment
Мой пример используется в Windows 10 с Visual Studio 2017.   -  person Sven    schedule 24.04.2017


Ответы (1)


Я хочу отправить сообщение из облака на устройство (C2D) на устройство... Я хочу использовать SAS-токен для подключения с истечением срока действия вместо подключения с помощью симметричного ключа устройства

Вы не можете отправить сообщение Cloud-To-Device, используя учетные данные на уровне устройства. Вам необходимо использовать учетные данные уровня центра Интернета вещей.

Итак, вам нужно удалить /devices/{sasTokenModel.DeviceId} в Target из GetSasToken(). Окончательный SAS-токен будет иметь следующий формат:

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

Я не могу воспроизвести вашу проблему. Я тестирую на рабочем столе, и версия ОС 10.0.14393.

Но я могу успешно отправить сообщение Cloud-To-Device, используя ваш незавершенный код и корректирующий формат токена SAS (упомянутый ранее). У вас может быть справка.

person Rita Han    schedule 20.04.2017
comment
Спасибо. Я знал, что где-то думал не так :) - person Sven; 24.04.2017
comment
Параграф в Использование токенов безопасности из компонентов службы немного сбивает с толку. В нем говорится: {имя хоста iot hub}/devicebound --› Отправлять сообщения из облака на устройство. при использовании /devicebounds за uri при отправке сообщений телеметрии я получаю UnknownErrorCode. При использовании этого при отправке прямых методов это происходит без проблем. Для отправки сообщения телеметрии будет работать только uri. - person Sven; 24.04.2017