かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

UWPでAzureのイベントハブにデータを突っ込む

抱かれたい男No1様にとてもお世話になりました。

Windows 10 IoT Core(UWP)でSASトークンを生成buchizo.wordpress.com

ServiceBusの名前空間をokazukihub-nsで作成して、イベントハブ名をokazukihubで作成して、送信の権限を持った口をInputという名前で作りました。ここに、データを突っ込むコードは以下のようになりました。

private async void button_Click(object sender, RoutedEventArgs e)
{
    var client = new HttpClient();
    var content = new ObjectContent<DeviceInfo>(new DeviceInfo
        {
            Id = 0,
            Value = 100,
        },
        new JsonMediaTypeFormatter());

    var sas = this.CreateToken("https://okazukihub-ns.servicebus.windows.net/okazukihub/messages", "Input", "p6U8m6dqSEsCb+3McnCOwsb8L7mcIm0tWmhVIL0u8vg=");
    client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", sas);
    content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/atom+xml")
    {
        CharSet = "utf-8",
    };
    content.Headers.ContentType.Parameters.Add(new System.Net.Http.Headers.NameValueHeaderValue("type", "entry"));
    var result = await client.PostAsync("https://okazukihub-ns.servicebus.windows.net/okazukihub/messages", content);
}

private string CreateToken(string resourceUri, string keyName, string key)
{
    TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
    var expiry = Convert.ToString((int)sinceEpoch.TotalSeconds + 3600); //EXPIRES in 1h 
    string stringToSign = WebUtility.UrlEncode(resourceUri) + "\n" + expiry;
    var signature = ComputeSignature(stringToSign, key);
    var sasToken = String.Format(CultureInfo.InvariantCulture,
        "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
        WebUtility.UrlEncode(resourceUri), WebUtility.UrlEncode(signature), expiry, keyName);

    return sasToken;
}

public string ComputeSignature(string content, string key, BinaryStringEncoding encoding = BinaryStringEncoding.Utf8)
{
    var algorithmProvider = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha256);
    var contentBuffer = CryptographicBuffer.ConvertStringToBinary(content, encoding);
    var keyBuffer = CryptographicBuffer.ConvertStringToBinary(key, encoding);
    var signatureKey = algorithmProvider.CreateKey(keyBuffer);
    var signedBuffer = CryptographicEngine.Sign(signatureKey, contentBuffer);
    return CryptographicBuffer.EncodeToBase64String(signedBuffer);
}

下の2メソッドは抱かれたい男No1様のページのコードになります。ボタンクリックで各種データを作ってサーバーに投げています。DeviceInfoクラスは、自作のIdとValueだけもったクラスになります。

ちょっとはまったのがAuthorizationヘッダーの設定がなかなかうまくいかなかった点です。HttpContent(ObjectContent)のHeadersに追加するとうまく追加できなくて、HttpCLientのDefaultRequestHeadersに追加するとうまくいきました。謎い。

client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", sas);

これで次のステップに進める…。