从 Azure IoT 中心到 ESP8266 的云到设备 (C2D) 消息 - 通过 Azure CLI 工作但不通过 HTTP 请求

问题描述

Azure Web CLI (bash) 中的 C2D 消息传递

az iot device c2d-message send -d MY-DEVICE-NAME -n MY-IOT-HUB-NAME --data "It works"

这是有效的 - C2D 消息被发送到设备。该消息通过串行方式打印出来,并显示在 TFT 上。

当我提交 HTTP 请求时,目标设备上没有收到任何消息。我会在最底部包含相关的设备代码

使用 az iot device c2d-message send 的 C2D 消息和使用下面的 HTTP 请求有区别吗?

HTTP 请求

curl -i https://MY-IOT-HUB-NAME.azure-devices.net/devices/MY-DEVICE-NAME/messages/events?api-version=2016-11-14 -H "Authorization: SharedAccessSignature sr=MY-IOT-HUB-NAME.azure-devices.net&sig=MY-SAS-SIG&se=1613476202&skn=MY-SKN" -H "Content-Type: application/json" -d'{"deviceid":"MY-DEVICE-NAME","temperature":70}'

这个 HTTP 请求正在工作,我得到一个 204,这表明 HTTP 请求格式正确并且授权正在工作。回复如下。

回复

HTTP/1.1 204 No Content
Content-Length: 0
Server: Microsoft-HTTPAPI/2.0
x-ms-request-id: 7d78e812-9659-4b70-aed2-becd81410192
Date: Tue,16 Feb 2021 11:20:43 GMT

设备代码

为我草率的代码道歉,我是 C++ 新手。

#include <AzureIoTHub.h>
#include "AzureIoTProtocol_MQTT.h"
#include "Esp.h"
#include "Free_Fonts.h"
#include <iothub_client_ll.h>
#include "iot_configs.h"
#include "iothubtransportmqtt.h"
#include "sample_init.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "SPI.h"
#include "TFT_eSPI.h"
#include <Wire.h>

static const char ssid[] = IOT_CONfig_WIFI_SSID;
static const char pass[] = IOT_CONfig_WIFI_PASSWORD;
static const char* connectionString = DEVICE_CONNECTION_STRING;
static bool g_continueRunning = true;
static size_t g_message_count_send_confirmations = 0;
IOTHUB_MESSAGE_HANDLE message_handle;
IOTHUB_CLIENT_STATUS status;
size_t messages_sent = 0;
int message_frequency = 10000;
TFT_eSPI tft = TFT_eSPI();
unsigned long drawTime = 0;
int row = 0;
int rows = 15;
int linespace = 16;
int padding = 2;
int counter = 0;
int chars = 29;
int result = 0;
IOTHUB_DEVICE_CLIENT_LL_HANDLE device_ll_handle;
static int callbackCounter;
int receiveContext = 0;

void setup() {
  Serial.begin(115200);
  tft.begin();
  tft.setRotation(1);
  tft.fillScreen(TFT_BLACK);

  logger("Connecting to WiFi...","ALERT",true,true);
  logger(IOT_CONfig_WIFI_SSID,true);
  sample_init(ssid,pass);
  logger("Connected to WiFi",true);
  IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol = MQTT_Protocol;
  logger("Connecting to IoT Hub...",true);
  (void)IoTHub_Init();
  logger("Connected to IoT Hub",true);
  device_ll_handle = IoTHubDeviceClient_LL_CreateFromConnectionString(connectionString,protocol);
  logger("Creating device handle...",true);
  IoTHubClient_LL_SetMessageCallback(device_ll_handle,ReceiveMessageCallback,NULL);
  logger("Created device handle",true);
  logger("Ready to receive C2D msgs",true);
  logger("",true);
  do
  {
    IoTHubClient_LL_DoWork(device_ll_handle);
    ThreadAPI_Sleep(1);
  } while (1);

  IoTHubClient_LL_Destroy(device_ll_handle);
  IoTHub_Deinit();
}

static IOTHUBMESSAGE_disPOSITION_RESULT ReceiveMessageCallback(IOTHUB_MESSAGE_HANDLE message,void* userContextCallback)
{

  const unsigned char* buffer = NULL;
  size_t size = 0;
  char m_buffer[1000]; // need to work out my max buffer size and deal with this - if I send a longer message it will break!
  int m = sprintf(m_buffer,"msg: %d",counter);

  char niceBuffer[30] = {
    0
  };

  (void)userContextCallback;
  IoTHubMessage_GetByteArray(message,&buffer,&size);
  printf("Received Message: %.*s & Size=%d\r\n",(int)size,buffer,(int)size);

  if (size > chars) {
    size = chars;
  }

  for (int i = 0; i < size; i++) {
    niceBuffer[i] = buffer[i];
  }

  niceBuffer[chars] = '\0';
  logger(niceBuffer,true);
  delay(1000);
  counter++;

  return IOTHUBMESSAGE_ACCEPTED;
}

void logger(const char * message,const char * type,bool print_to_serial,bool print_to_display) { 

  if (print_to_serial) {
    Serial.println(message);
  } else {

  }

  if (print_to_display) { 
    // Todo 2D data for the screen
    if (row == rows) {
      tft.fillScreen(TFT_BLACK);
      row = 0;
    }
    tft.setTextDatum(TL_DATUM);
    tft.setTextColor(TFT_WHITE,TFT_BLACK);
    tft.setFreeFont(FF1);
    tft.drawString(message,padding,(padding + (linespace * row)),GFXFF);
    row++;
  } else {

  }

}

void loop() {
  //loop
}

#ifndef LOAD_GLCD
//ERROR_Please_enable_LOAD_GLCD_in_User_Setup
#endif

#ifndef LOAD_GFXFF
ERROR_Please_enable_LOAD_GFXFF_in_User_Setup!
#endif

解决方法

无法通过 HTTP 将 C2D 发送到设备。此功能需要使用 AMQP 启动,这是 Azure CLI 应用程序使用的。我不知道为什么你的 curl 请求返回 204 而不是更有意义的东西。