繁体   English   中英

使用 azure-iot-sdk-c SDK 在 Azure IoT Edge 模块中实现直接模块方法时遇到问题

[英]Trouble with implementing a Direct Module Method in Azure IoT Edge Module using azure-iot-sdk-c SDK

完全公开,我在 Azure IoT SDK C github 项目上问过这个问题,但由于他们建议查看 StackOverflow,我决定也在这里发布。

我在基于 azure-iot-sdk-c 的 IoT Edge 模块中实现直接模块方法处理程序时遇到问题。 我找不到带有示例实现的文档页面,所以我从各种 SDK 文档页面和单元测试“示例”中组装了我的实现。

为了对此进行测试,我有一台运行 iotedge 1.0.8-2 的基于 Linux 的专用 PC (Ubuntu 18.04)。 我可以看到我的模块正在启动并打印其版本并触发连接状态回调消息。 当我在门户中手动编辑设备的模块标识孪生时,我什至看到 ModuleTwin 回调正在触发并打印有效负载。

但是,当我尝试在门户中的设备中手动调用模块上的直接方法时,我看不到任何打印内容,并且在门户中收到以下错误:

{"message":"GatewayTimeout:{\r\n  \"Message\": \"{\\\"errorCode\\\":504101,\\\"trackingId\\\":\\\"8215e001484d41a19245639844f44f78-G:9-TimeStamp:01/14/2020 21:20:42-G:0-TimeStamp:01/14/2020 21:20:42\\\",\\\"message\\\":\\\"Timed out waiting for the response from device.\\\",\\\"info\\\":{},\\\"timestampUtc\\\":\\\"2020-01-14T21:20:42.0556758Z\\\"}\",\r\n  \"ExceptionMessage\": \"\"\r\n}"}

相关代码如下。 我查看了 StackOverflow,但没有基于 C SDK 的示例。 直接模块方法我哪里出错了? 谢谢!

更新:一个有趣的观察是,如果我更改此代码以使用来自 AMQP 的 MQTT,则一切正常。 直接模块方法不支持 AMQP 吗?

#include <iothub_module_client_ll.h>
#include <iothub_client_options.h>
#include <iothub_message.h>
#include <azure_c_shared_utility/threadapi.h>
#include <azure_c_shared_utility/crt_abstractions.h>
#include <azure_c_shared_utility/platform.h>
#include <azure_c_shared_utility/shared_util_options.h>
#include <iothubtransportamqp.h>
#include <iothub.h>
#include <time.h>

#include <stdio.h>
#include <stdlib.h>

// Linker defined build information (see Makefile)
extern char   __BUILD_DATE;
extern char   __BUILD_NUMBER;

// Set the default value for module communication (e.g. AMQP) log tracing, yet
// allow compile time overrides.
#ifndef LOG_TRACE_ENABLED
  #define LOG_TRACE_ENABLED 0
#endif

static void moduleTwinCallback(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad, size_t size, void* /*userContextCallback*/)
{
    EPRINT("DEBUG: Module Twin callback called with (state=%s)", MU_ENUM_TO_STRING(DEVICE_TWIN_UPDATE_STATE, update_state));
    EPRINT("DEBUG: payload=%.*s", (int)size, (const char *)payLoad);
    fflush(NULL);

    //JSON_Value *root_value = json_parse_string(payLoad);
    //JSON_Object *root_object = json_value_get_object(root_value);
    //if (json_object_dotget_value(root_object, "desired.TemperatureThreshold") != NULL) {
    //    temperatureThreshold = json_object_dotget_number(root_object, "desired.TemperatureThreshold");
    //}
    //if (json_object_get_value(root_object, "TemperatureThreshold") != NULL) {
    //    temperatureThreshold = json_object_get_number(root_object, "TemperatureThreshold");
    //}
}

static int DirectMethodCb(const char* method_name, const unsigned char* payload, size_t size, unsigned char** response, size_t* resp_size, void* /*userContextCallback*/)
{
  const char *METHOD_NAME = "TestMethod";
  const int METHOD_RESPONSE_SUCCESS = 200;
  const int METHOD_RESPONSE_ERROR = 401;

  int responseCode;

  EPRINT("DEBUG: Method name:    %s", method_name);
  EPRINT("DEBUG: Method payload: %.*s", (int)size, (const char*)payload);

  if (strcmp(METHOD_NAME, method_name))
  {
    EPRINT("Method name incorrect - expected %s but got %s", METHOD_NAME, method_name);
    responseCode = METHOD_RESPONSE_ERROR;
  }
  /*
  else if (size != strlen(expectedMethodPayload))
  {
    LogError("payload size incorect - expected %zu but got %zu", strlen(expectedMethodPayload), size);
    responseCode = METHOD_RESPONSE_ERROR;
  }
  else if (memcmp(payload, expectedMethodPayload, size))
  {
    LogError("Payload strings do not match");
    responseCode = METHOD_RESPONSE_ERROR;
  }
  */
  else
  {
    *resp_size = size;
    if (size == 0)
    {
      *response = NULL;
      EPRINT("DEBUG: Empty, but good response");
      responseCode = METHOD_RESPONSE_SUCCESS;
    }
    else
    {
      if ((*response = (unsigned char*)malloc(*resp_size)) == NULL)
      {
        EPRINT("allocation failure");
        responseCode = METHOD_RESPONSE_ERROR;
      }
      else
      {
        (void)memcpy(*response, payload, *resp_size);
        EPRINT("DEBUG: All good - echoing back the payload");
        responseCode = METHOD_RESPONSE_SUCCESS;
      }
    }
  }

  EPRINT("DEBUG: completing with return code %d", responseCode);
  fflush(NULL);
  return responseCode;
}

static void ConnectionStatusCb(IOTHUB_CLIENT_CONNECTION_STATUS result, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason, void* /*userContextCallback*/)
{
  EPRINT("DEBUG: ConnectionStatusCb(status=%d %s, reason=%d %s",
      result, MU_ENUM_TO_STRING(IOTHUB_CLIENT_CONNECTION_STATUS, result),
      reason, MU_ENUM_TO_STRING(IOTHUB_CLIENT_CONNECTION_STATUS_REASON, reason)
      );
  fflush(NULL);
}

int main(void)
{
  IOTHUB_MODULE_CLIENT_LL_HANDLE iotHubModuleClientHandle = nullptr;
  int retval = 1;

  do
  {
    printf("\n\n=======================\n");
    printf("Build date  : %lu\n", (unsigned long) &__BUILD_DATE);
    printf("Build number: %lu\n", (unsigned long) &__BUILD_NUMBER);
    fflush(NULL);

    srand((unsigned int)time(NULL));

    if (0 != IoTHub_Init())
    {
      EPRINT("Failed to initialize the platform.");
      break;
    }

    iotHubModuleClientHandle = IoTHubModuleClient_LL_CreateFromEnvironment(AMQP_Protocol);
    if (nullptr == iotHubModuleClientHandle)
    {
      EPRINT("IoTHubModuleClient_LL_CreateFromEnvironment failed");
      break;
    }

    IOTHUB_CLIENT_RESULT result = IoTHubModuleClient_LL_SetModuleMethodCallback(iotHubModuleClientHandle, DirectMethodCb, iotHubModuleClientHandle);
    if (IOTHUB_CLIENT_OK != result)
    {
      EPRINT("IoTHubModuleClient_SetModuleMethodCallback failed: %d", result);
      break;
    }

    result = IoTHubModuleClient_LL_SetConnectionStatusCallback(iotHubModuleClientHandle, ConnectionStatusCb, iotHubModuleClientHandle);
    if (IOTHUB_CLIENT_OK != result)
    {
      EPRINT("IoTHubDeviceClient_SetConnectionStatusCallback failed: %d", result);
      break;
    }

#if LOG_TRACE_ENABLED
    bool traceOn = true;
    IoTHubModuleClient_LL_SetOption(iotHubModuleClientHandle, OPTION_LOG_TRACE, &traceOn);
#endif // LOG_TRACE_ENABLED

    result = IoTHubModuleClient_LL_SetModuleTwinCallback(iotHubModuleClientHandle, moduleTwinCallback, iotHubModuleClientHandle);
    if (IOTHUB_CLIENT_OK != result)
    {
      EPRINT("IoTHubModuleClient_LL_SetModuleTwinCallback failed: %d", result);
      break;
    }

    while (true)
    {
      IoTHubModuleClient_LL_DoWork(iotHubModuleClientHandle);
      ThreadAPI_Sleep(100);
    }
  } while(false);

  if (nullptr != iotHubModuleClientHandle)
  {
    IoTHubModuleClient_LL_Destroy(iotHubModuleClientHandle);
  }
  IoTHub_Deinit();

  return retval;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM