进程间通信 (IPC) 客户端 APIs - 的托管集成 AWS IoT Device Management

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

进程间通信 (IPC) 客户端 APIs

托管集成中心上的外部组件可以使用托管集成 Hub SDK 的代理组件和进程间通信 (IPC) 与托管集成 Hub SDK 通信。集线器上的一个外部组件示例是管理本地例程的守护程序(一个持续运行的后台进程)。在通信过程中,IPC 客户端是发布命令或其他请求以及订阅事件的外部组件。IPC 服务器是托管集成中心 SDK 中的代理组件。有关更多信息,请参阅设置 IPC 客户端

为了构建 IPC 客户端,我们提供了 IPC 客户端库IotmiLocalControllerClient。此库提供客户端, APIs 用于在 Agent 中与 IPC 服务器进行通信,包括发送命令请求、查询设备状态、订阅事件(如设备状态事件)以及处理基于事件的交互。

设置 IPC 客户端

IotmiLocalControllerClient库是基本 IPC 的包装 APIs,它简化和简化了在应用程序中实现 IPC 的过程。以下各节描述了 APIs 它所提供的。

注意

本主题专门针对作为 IPC 客户端的外部组件,而不是 IPC 服务器的实现。

  1. 创建 IPC 客户端

    必须先初始化 IPC 客户端,然后才能使用它来处理请求。可以在IotmiLocalControllerClient库中使用构造函数,该构造函数将订阅者上下文 char *subscriberCtx作为参数,并基于该构造函数创建 IPC 客户端管理器。以下是创建 IPC 客户端的示例:

    // Context for subscriber char subscriberCtx[] = "example_ctx"; // Instantiate the client IotmiLocalControllerClient lcc(subscriberCtx);
  2. 订阅活动

    您可以向 IPC 客户端订阅目标 IPC 服务器的事件。当 IPC 服务器发布客户端已订阅的事件时,客户端将收到该事件。要订阅,请使用registerSubscriber函数并提供 IDs 要订阅的事件以及自定义的回调。

    以下是该registerSubscriber函数的定义及其用法示例:

    iotmi_statusCode_t registerSubscriber( std::vector<iotmiIpc_eventId_t> eventIds, SubscribeCallbackFunction cb);
    // A basic example of customized subscribe callback, which prints the event ID, data, and length received void customizedSubscribeCallback(iotmiIpc_eventId_t event_id, uint32_t length, const uint8_t *data, void *ctx) { IOTMI_IPC_LOGI("Received subscribed event id: %d\n" "length: %d\n" "data: %s\n", event_id, length, data); } iotmi_statusCode_t status; status = lcc.registerSubscriber({IOTMI_IPC_EVENT_DEVICE_UPDATE_TO_RE}, customerProvidedSubscribeCallback);

    的定义status是为了检查操作(如订阅或发送请求)是否成功。如果操作成功,则返回的状态为IOTMI_STATUS_OK (= 0)

    注意

    对于订阅中的订阅者和事件的最大数量,IPC 库具有以下服务配额:

    • 每个进程的最大订阅者数:5

      定义IOTMI_IPC_MAX_SUBSCRIBER在 IPC 库中。

    • 定义的最大事件数:32

      定义IOTMI_IPC_EVENT_PUBLIC_END在 IPC 库中。

    • 每个订阅者都有一个 32 位的事件字段,其中每个位对应一个定义的事件。

  3. 将 IPC 客户端连接到服务器

    IotmiLocalControllerClient库中的 connect 函数执行诸如初始化 IPC 客户端、注册订阅者和订阅函数中提供的事件之类的工作。registerSubscriber您可以在 IPC 客户端上调用连接函数。

    status = lcc.connect();

    在发送请求或进行其他操作IOTMI_STATUS_OK之前,请确认返回的状态为。

  4. 发送命令请求和设备状态查询

    代理中的 IPC 服务器可以处理命令请求和设备状态请求。

    • 命令请求

      形成命令请求有效载荷字符串,然后调用sendCommandRequest函数将其发送。例如:

      status = lcc.sendCommandRequest(payloadData, iotmiIpcMgr_commandRequestCb, nullptr);
      /** * @brief method to send local control command * @param payloadString A pre-defined data format for local command request. * @param callback a callback function with typedef as PublishCallbackFunction * @param client_ctx client provided context * @return */ iotmi_statusCode_t sendCommandRequest(std::string payloadString, PublishCallbackFunction callback, void *client_ctx);

      有关命令请求格式的更多信息,请参阅命令请求

      例 回调函数

      IPC 服务器首先向 IPC 客户端发送消息确认Command received, will send command response back。收到此确认后,IPC 客户端可以预期会出现命令响应事件。

      void iotmiIpcMgr_commandRequestCb(iotmi_statusCode_t ret_status, void *ret_data, void *ret_client_ctx) { char* data = NULL; char *ctx = NULL; if (ret_status != IOTMI_STATUS_OK) return; if (ret_data == NULL) { IOTMI_IPC_LOGE("error, event data NULL"); return; } if (ret_client_ctx == NULL) { IOTMI_IPC_LOGE("error, event client ctx NULL"); return; } data = (char *)ret_data; ctx = (char *)ret_client_ctx; IOTMI_IPC_LOGI("response received: %s \n", data); }
    • 设备状态请求

      与该sendCommandRequest函数类似,此sendDeviceStateQuery函数还接受有效载荷字符串、相应的回调和客户端上下文。

      status = lcc.sendDeviceStateQuery(payloadData, iotmiIpcMgr_deviceStateQueryCb, nullptr);

IPC 接口定义和有效载荷

本节重点介绍专门用于代理和外部组件之间通信的 IPC 接口,并提供了这两个组件 APIs 之间的 IPC 实现示例。在以下示例中,外部组件管理本地例程。

IoTManagedIntegrationsDevice-IPC库中,为代理和外部组件之间的通信定义了以下命令和事件。

typedef enum { // The async cmd used to send commands from the external component to Agent IOTMI_IPC_SVC_SEND_REQ_FROM_RE = 32, // The async cmd used to send device state query from the external component to Agent IOTMI_IPC_SVC_SEND_QUERY_FROM_RE = 33, // ... } iotmiIpcSvc_cmd_t;
typedef enum { // Event about device state update from Agent to the component IOTMI_IPC_EVENT_DEVICE_UPDATE_TO_RE = 3, // ... } iotmiIpc_eventId_t;

命令请求

命令请求格式
  • 例 命令请求
    { "payload": { "traceId": "LIGHT_DIMMING_UPDATE", "nodeId": "1", "managedThingId": <ManagedThingId of the device>, "endpoints": [{ "id": "1", "capabilities": [ { "id": "matter.LevelControl@1.4", "name": "Level Control", "version": "1.0", "actions":[ { "name": "UpdateState", "parameters": { "OnLevel": 5, "DefaultMoveRate": 30 } } ] } ] }] } }
命令响应格式
  • 如果来自外部组件的命令请求有效,则代理会将其发送到 CDMB(通用数据模型桥)。由于处理命令需要时间,因此包含命令执行时间和其他信息的实际命令响应不会立即发送回外部组件。此命令响应是代理的即时响应(如确认)。该响应告诉外部组件托管集成已收到该命令,如果没有有效的本地令牌,则会对其进行处理或将其丢弃。命令响应以字符串格式发送。

    std::string errorResponse = "No valid token for local command, cannot process."; *ret_buf_len = static_cast<uint32_t>(errorResponse.size()); *ret_buf = new uint8_t[*ret_buf_len]; std::memcpy(*ret_buf, errorResponse.data(), *ret_buf_len);

设备状态请求

外部组件向代理发送设备状态请求。请求会提供设备managedThingId的,然后代理会回复该设备的状态。

设备状态请求格式
  • 您的设备状态请求必须包含managedThingId所查询设备的。

    { "payload": { "managedThingId": "testManagedThingId" } }
设备状态响应格式
  • 如果设备状态请求有效,代理将以字符串格式发送回状态。

    例 有效请求的设备状态响应
    { "payload": { "currentState": "exampleState" } }

    如果设备状态请求无效(例如,没有有效的令牌、无法处理有效负载或其他错误情况),则代理会将响应发回。响应包括错误代码和错误消息。

    例 无效请求的设备状态响应
    { "payload": { "response":{ "code": 111, "message": "errorMessage" } } }

命令响应

例 命令响应格式
{ "payload": { "traceId": "LIGHT_DIMMING_UPDATE", "commandReceivedAt": "1684911358.533", "commandExecutedAt": "1684911360.123", "managedThingId": <ManagedThingId of the device>, "nodeId": "1", "endpoints": [{ "id": "1", "capabilities": [ { "id": "matter.OnOff@1.4", "name": "On/Off", "version": "1.0", "actions":[ {} ] } ] }] } }

通知事件

例 通知事件格式
{ "payload": { "hasState": "true" "nodeId": "1", "managedThingId": <ManagedThingId of the device>, "endpoints": [{ "id": "1", "capabilities": [ { "id": "matter.OnOff@1.4", "name": "On/Off", "version": "1.0", "properties":[ { "name": "OnOff", "value": true } ] } ] }] } }