使用nodemcu将消息发送到Azure事件中心

时间:2020-02-24 11:16:19

标签: azure arduino esp8266 azure-eventhub nodemcu

我正在尝试使用nodemcu(ESP8266)将消息发送到Azure事件中心。 我正在使用Azure事件中心的REST API。 我遵循了this的说明,但是我没有为我工作。

当前,我正在响应:401 SubCode = 40103:无效的授权令牌签名

我提供了用于连接HTTPS的指纹。 (在教程中没有必要,所以我有些困惑。)

我对SAS表示怀疑,但是我一次又一次地检查。

作为替代方案,我也打算使用AMQP,但找不到支持它的库。

是否有其他方法可以将消息发送到事件中心。

#include <WiFiClientSecure.h>
#include <String.h>
#include "sha256.h"
#include "Base64.h"

// START: Azure Evet Hub settings
const char* KEY = "<key>";    // event hub access key 
const char* KEY_NAME = "<key-name>";                 // event hub key name  ( policy name) 
const char* HOST = "<event-hub-namespace>.servicebus.windows.net";              // event hub name (name of service bus)
const char* END_POINT = "/<event-hub>/messages";                 // name of the evnthub which we create inside eventhub namespace
// END: Azure Evet Hub settings 

// START: WiFi settings
const char* SSID = "<ssid>";
const char* PASSWORD = "<password>";
// END: WiFi settings

String request;
String data;
String fullSas;
WiFiClientSecure client;

// Use web browser to view and copy
// SHA1 fingerprint of the certificate
const char fingerprint[] PROGMEM = "<fingerprint>";
void setup() {
  Serial.begin(115200);

  // START: Naive URL Encode
  String url = "https://" + (String)HOST + (String)END_POINT;
  url.replace(":", "%3A");
  url.replace("/", "%2F");
  Serial.println(url);
  // END: Naive URL Encode

  // START: Create SAS
  // https://azure.microsoft.com/en-us/documentation/articles/service-bus-sas-overview/
  // Where to get secods since the epoch: local service, SNTP, RTC
  int expire = 1609459200;
  String stringToSign = url + "\n" + expire;

  // START: Create signature
  Sha256.initHmac((const uint8_t*)KEY, 44);
  Sha256.print(stringToSign);
  char* sign = (char*) Sha256.resultHmac();
  int signLen = 32;
  // END: Create signature

  // START: Get base64 of signature
  int encodedSignLen = base64_enc_len(signLen);
  char encodedSign[encodedSignLen];
  base64_encode(encodedSign, sign, signLen); 
  String encodedSas = (String) encodedSign;
  // Naive URL encode
  encodedSas.replace("=", "%3D");
  //Serial.println(encodedSas);
  // END: Get base64 of signature

  // SharedAccessSignature
   fullSas = "sr=" + url + "&sig="+ encodedSas + "&se=" + expire +"&skn=" + KEY_NAME;
  // END: create SAS
//Serial.println("SAS below");
//Serial.println(fullSas);
//Serial.println();
  // START: Wifi connection
  Serial.print("connecting to ");
  Serial.println(SSID);

  WiFi.begin(SSID, PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  // END: Wifi connection

}

void loop() {
  //delay(100);
  WiFiClientSecure client;

  Serial.printf("Using fingerprint '%s'\n", fingerprint);
  client.setFingerprint(fingerprint);

  if (!client.connect(HOST, 443)) {
    Serial.println("connection failed");
    return;
  }

   data = "{'Temperature':25.25 , 'Deviceid':'esp3'}";
   request = String("POST ") + END_POINT + " HTTP/1.1\r\n" +
               "Host: " + HOST + "\r\n" +
               "Authorization: SharedAccessSignature " + fullSas + "\r\n" +                
               "Content-Type: application/atom+xml;type=entry;charset=utf-8\r\n" + 
               "Content-Length: " + data.length() + "\r\n\r\n" +
               data;
    Serial.println(request);
  client.print(request);
 delay(100);  
}

2 个答案:

答案 0 :(得分:0)

请看一下this post,它使用nodemcu和Azure Event Hub提供了POC。但是,基本上,从IoT设备到事件中心的每个请求都必须经过身份验证,在这种情况下,您应该使用共享访问签名(SAS)令牌并强制执行HTTPS。

答案 1 :(得分:0)

很显然,SAS创建部件无法正常工作。当我使用python脚本(提供here)创建SAS时,它起作用了。我不知道为什么4年后它就坏了。