Jak na SAS klíč pro Event Hub REST API


Dnes se podíváme na první ze série článku o IoT. V prvním díle si ukážeme typické použití Azure jako integrační platformy pro IoT a to konkrétně pro sběr a následné zpracování senzorových dat.

Celý expediment, který budu popisovat v sérii článků řeší problém s řízením vytápění v rodinném domě. V mém konkrétním případě jsem potřeboval sbírat data z několika teplotních čidel a zareagovat v případě, že se teplota skokově změnila, dostala se mimo stanovený rozsah, nebo se změna projevila jen na některých čidlech. Cílem bylo monitorovat teplotu v domě a následně regulovat jednotlivé pokoje i v případě například otevřených oken a pod. Jelikož řešení musí běžet 24/7, rozhodl jsem se, kvůli spotřebě, realizovat jednotlivá čidla pomocí Arduina a hodnoty přenášet po I2C sběrnici. Data jsou pak následně agregovaná pomocí Rasppery Pi a z něj posílána do Azure Event Hubu a z něj následně zpracovaná pomocí služby Stream Analytics.

Shrnutí:

  • Měření dat – Arduino
  • Sběr dat – Raspberry Pi pomocí i2C
  • Uložení dat – Azure Event Hub
  • Zpracování dat – Azure Stream Analytics

První problém nastal, když jsem chtěl data o teplotě odesílat do azure. První verze programu vypadala následovně:

MessagingFactory factory = MessagingFactory.CreateFromConnectionString(ConnectionString);
EventHubClient client = factory.CreateEventHubClient("arduino");

string serializedString = JsonConvert.SerializeObject(temperature);
MemoryStream stream = new MemoryStream();
byte[] buffer;
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(serializedString);
writer.Flush();
stream.Seek(0, SeekOrigin.Begin);
buffer = stream.ToArray();
}
EventData eventData = new EventData(buffer);
eventData.Properties.Add("Type", "Temperature");
client.Send(eventData);

 

Při testování vše fungovalo jak mělo, ale při přenosu na Raspberry Pi byla výsledkem chyba

“Missing method System.Net.NetworkCredential::.ctor(string,SecureString,string) in assembly /usr/lib/mono/gac/System/4.0.0.0__b77a5c561934e089/System.dll, referenced in assembly /home/pospa/dev/Microsoft.ServiceBus.dll”

Mono dokáže hodně, ale někde člověk prostě narazí. Nu což, alternativní variantou je použít REST API. Teorie zde:

https://msdn.microsoft.com/en-us/library/azure/dn790674.aspx

Zdánlivě jednoduchý úkol na pár řádek kódu… No a o několik hodin a verzí později jsem to měl. Bohužel, nebo spíš bohudík, je REST API nekompromisní a parametry je nutné dodržet do sebemenšího detailu. Výsledný funkční kód je:

HttpWebRequest request = (HttpWebRequest) WebRequest.Create(GetServiceUri(eventHubName, publisher));
request.Method = "POST";
request.Headers.Add("Authorization", GetSAS(eventHubName, publisher, keyName, keyValue));
request.ContentType = "application/atom+xml;type=entry;charset=utf-8";

request.Headers.Add("Type", "Temperature");

string serializedString = JsonConvert.SerializeObject(temperature);
using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(serializedString);
}

using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
Console.WriteLine("> Http Response: {0}", response.StatusCode);
}

Jednotlivé metody pak:

private static Uri GetServiceUri(string eventHub, string publisher)
{
Uri uri = ServiceBusEnvironment.CreateServiceUri("https", SbNamespace,
String.Format("{0}/publishers/{1}/messages", eventHub, publisher));
return uri;
}

private static Uri GetMethodUri()
{
Uri uri = ServiceBusEnvironment.CreateServiceUri("https", SbNamespace, string.Empty);
return uri;
}

private static readonly object lockObject = new object();
private static readonly Dictionary<string, string> _sas = new Dictionary<string, string>();

private static string GetSAS(string eventHubName, string publisher, string keyName, string keyValue)
{
string key = string.Concat(eventHubName, '/', publisher, '/', keyName);
if (!_sas.ContainsKey(key))
{
lock (lockObject)
{
if (!_sas.ContainsKey(key))
{
_sas.Add(key, SharedAccessSignatureTokenProvider.GetPublisherSharedAccessSignature(GetMethodUri(), eventHubName, publisher, keyName, keyValue, TimeSpan.FromMinutes(Ttl)));
}
}
}
return _sas[key];
}

Doufám, že vám návod ušetří martyrium hledáni a testování. Komentáře parametrů jsou:

  • eventHub – jméno Event Hubu z management portálu
  • publisher – alfanumerické jméno systému odesílajícího data, zvolíte si samy
  • SbNamespace – Service Bus namespace z management portálu
  • keyName – jméno klíče z management portálu
  • keyValue – Hodnota vygenerovaného klíče z management portálu
  • Ttl – Time To Live, platnost vygenerovaného SAS tokenu v minutách

 


Pokud budete mít s REST API jakýkoliv problém, komentáře jsou tím správným místem pro dotaz. Případně se můžete obrátit na můj twitter, kde budou i nadále odkazy na veškeré mé technické články. Děkuji

 

-<{Pospa}>-

Comments (0)

Skip to main content