1

C2D messaging in Azure Web CLI (bash)

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

This works - a C2D message is sent to the device. The message is printed out over serial, and is displayed on a TFT.

When I submit an HTTP request no message is received on the target device. I'll include the relevant device code at the very bottom.

Is there a difference between a C2D message using az iot device c2d-message send and using the HTTP request below?

HTTP request

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}'

This HTTP request is working, and I'm getting a 204, which indicates that that the HTTP request is properly formed and the authorisation is working. The response is below.

Response

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

Device code

Apologies for my sloppy code, I'm new to 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, "ALERT", true, true);
  sample_init(ssid, pass);
  logger("Connected to WiFi", "ALERT", true, true);
  IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol = MQTT_Protocol;
  logger("Connecting to IoT Hub...", "ALERT", true, true);
  (void)IoTHub_Init();
  logger("Connected to IoT Hub", "ALERT", true, true);
  device_ll_handle = IoTHubDeviceClient_LL_CreateFromConnectionString(connectionString, protocol);
  logger("Creating device handle...", "ALERT", true, true);
  IoTHubClient_LL_SetMessageCallback(device_ll_handle, ReceiveMessageCallback, NULL);
  logger("Created device handle", "ALERT", true, true);
  logger("Ready to receive C2D msgs", "ALERT", true, true);
  logger("", "ALERT", true, 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, "ALERT", true, 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
vorkuta
  • 11
  • 1
  • have a look at the document https://learn.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-endpoints, see details about the Service endpoints. – Roman Kiss Feb 16 '21 at 13:16

1 Answers1

0

There is no way to send C2D to a device over HTTP. This functionality needs to be initiated using AMQP, which is what the Azure CLI app uses. I'm not sure why your curl request returned 204 instead of something more meaningful.