AWS IOT Device C SDK 使用

Posted 行稳方能走远

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AWS IOT Device C SDK 使用相关的知识,希望对你有一定的参考价值。

AWS IOT Device C SDK 使用

AWS IOT接入及测试

阿里云设备影子:类似MQTT的遗嘱

阿里云一机一密、一型一密、CA证书、证书获取、证书烧录

亚马逊云物联网AWS IoT初体验

烟感器设备接入AWS IOT的一种方法

如何把设备安全的接入AWS IoT(一)

如何把设备安全的接入AWS IoT(二)

AWS Client端SDK授权方案(Amazon Cognito 身份池)

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <cJSON.h>
#include "aws_iot_config.h"
#include "aws_iot_log.h"
#include "aws_iot_version.h"
#include "aws_iot_mqtt_client_interface.h"
#include "aws_iot_shadow_interface.h"
#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 400
static char certDirectory[PATH_MAX + 1] = "./certs";
#define HOST_ADDRESS_SIZE 255
static char HostAddress[HOST_ADDRESS_SIZE] = AWS_IOT_MQTT_HOST;
static uint32_t port = AWS_IOT_MQTT_PORT;
static uint8_t numPubs = 5;


typedef struct cameras
    int power;
    int stream;
cameraState; 
cameraState camera;          //照相机的物模型
int reporetedFlag = 0;


void ShadowUpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status,
                                const char *pReceivedJsonDocument, void *pContextData) 
    //device 发起update请求,收到server accpected消息时会触发这个回调,用于判断update状态是否成功
    if(SHADOW_ACK_TIMEOUT == status) 
        IOT_INFO("Update Timeout--");
     else if(SHADOW_ACK_REJECTED == status) 
        IOT_INFO("Update RejectedXX");
     else if(SHADOW_ACK_ACCEPTED == status) 
        IOT_INFO("Update Accepted !!");
    




//***************CJSON*********************// parseCMDJSON create_monitor_with_helpers用于解析或构造state内容
int parseCMDJSON(const char * const monitor)//使用CJSON解析get shadow返回的消息
    const cJSON *state = NULL;
    const cJSON *desired = NULL;
    const cJSON *reported = NULL;
    const cJSON *power = NULL;
    const cJSON *stream = NULL;
    int status = 0;
    cJSON *monitor_json = cJSON_Parse(monitor);//它将解析JSON并分配cJSON表示它的项目树。
    if (monitor_json == NULL)
    
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL)
        
            fprintf(stderr, "Error before: %s\\n", error_ptr);
        
        status = 0;
        goto end;
    
    state = cJSON_GetObjectItemCaseSensitive(monitor_json, "state");        //得到state内容
    if (cJSON_IsString(state) && (state->valuestring != NULL))
    
        printf("Checking monitor \\"%s\\"\\n", state->valuestring);
    
    desired = cJSON_GetObjectItemCaseSensitive(state, "desired");           //从stated尝试解析desired
    reported = cJSON_GetObjectItemCaseSensitive(state, "reported");         //从stated尝试解析reported
    
    
    if(!cJSON_IsNull(reported))//如果reported不为空
    
        power = cJSON_GetObjectItemCaseSensitive(reported, "power");
        stream = cJSON_GetObjectItemCaseSensitive(reported, "stream");
        if (cJSON_IsNumber(power))//使用云上状态同步本地状态
            camera.power = power->valueint;
            IOT_INFO("reported power:%d",   camera.power );
        
        if (cJSON_IsNumber(stream))//使用云上状态同步本地状态
            camera.stream = stream->valueint;
            IOT_INFO("reported stream:%d",  camera.stream);
        
        status = 1;
    


    if (!cJSON_IsNull(desired))//如果desired不为空,所以应该用desired状态同步本状态。上面reported同步的状态将被覆盖
    
        power = cJSON_GetObjectItemCaseSensitive(desired, "power");
        stream = cJSON_GetObjectItemCaseSensitive(desired, "stream");
        if (cJSON_IsNumber(power)) 
            camera.power = power->valueint;
            IOT_INFO("desired power:%d",    camera.power );
        
        if (cJSON_IsNumber(stream)) 
            camera.stream = stream->valueint;
            IOT_INFO("desired stream:%d",   camera.stream);
        
        reporetedFlag = 1;//更新状态
        status = 1;
    
end:
    cJSON_Delete(monitor_json);
    return status;





char *create_monitor_with_helpers(void)//构造reported update 的state内容 

    char *string = NULL;
    cJSON *monitor = cJSON_CreateObject();
    cJSON *state = cJSON_CreateObject();
    cJSON *reporteds = cJSON_CreateObject();
    cJSON *desired = cJSON_CreateObject();
    cJSON *reported = cJSON_CreateObject();
    if (cJSON_AddNumberToObject(reported, "power", camera.power) == NULL)       //构造power属性到reported中
        goto end;
    if (cJSON_AddNumberToObject(reported, "stream", camera.stream) == NULL)     //构造stream属性到reported中
        goto end;
    cJSON_AddItemToObject(state, "reported", reported);
    cJSON_AddItemToObject(state, "desired", desired);       //将reported和desired添加到state
    cJSON_AddItemToObject(monitor, "state", state);         //将state添加到返回的主json中

    char tempClientTokenBuffer[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE];
    if(aws_iot_fill_with_client_token(tempClientTokenBuffer, MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE) != SUCCESS)
        return false;
    
    cJSON_AddStringToObject(monitor, "clientToken", tempClientTokenBuffer);//将clientToken标识添加到主JSON中
    string = cJSON_PrintUnformatted(monitor);//生成JSON PrintUnformatted函数为不格式化生成,生成一个紧凑的json字串 
    if (string == NULL) 
        fprintf(stderr, "Failed to print monitor.\\n");
    
end:
    cJSON_Delete(monitor);
    return string;




// get shadow API的回调 当得到server返回时会触发这个函数
                                                //收到的回复的名称          操作的反应      通知操作是接受/拒绝/超时
static void ShadowGetStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status,
                                const char *pReceivedJsonDocument, void *pContextData) 
                                            //收到json文档         动作调用期间传入的void *数据(更新,获取或删除)
    IOT_INFO("get shadow json:\\n%s",pReceivedJsonDocument);
    parseCMDJSON(pReceivedJsonDocument);//解析出reported desired 
    if(SHADOW_ACK_TIMEOUT == status) 
        IOT_INFO("get Timeout--");
     else if(SHADOW_ACK_REJECTED == status) 
        IOT_INFO("get RejectedXX");
     else if(SHADOW_ACK_ACCEPTED == status) 
        IOT_INFO("get Accepted !!");
    




//****************************************************//
//当收到delta消息中<disired>中含有该属性时 会触发该回调函数
                                //json数据内容           json数据长度
void power_Callback(const char *pJsonString, uint32_t JsonStringDataLen, jsonStruct_t *pContext) 
    char res[10];
    strncpy(res, pJsonString, JsonStringDataLen);
    camera.power = atoi(res);//得到delta消息中power的值
    if(camera.power == 1)
        IOT_INFO("power on");
    
    else
        IOT_INFO("power off");
    
    reporetedFlag = 1;

//当收到delta消息中<disired>中含有该属性时 会触发该回到函数
void stream_Callback(const char *pJsonString, uint32_t JsonStringDataLen, jsonStruct_t *pContext) 
    char res[10];
    strncpy(res, pJsonString, JsonStringDataLen);
    camera.stream = atoi(res);//得到delta消息中stream的值
    if(camera.stream == 0)
        IOT_INFO("stream off");
    
    else
        IOT_INFO("stream open");
    
    reporetedFlag = 1;




//reported函数 内部封装了sdk update接口 用于update reported state
void iot_reporte(AWS_IoT_Client *mqttClient, jsonStruct_t JsonHander[2])
    IoT_Error_t rc = FAILURE;
    char JsonDocumentBuffer[MAX_LENGTH_OF_UPDATE_JSON_BUFFER];
    size_t sizeOfJsonDocumentBuffer = sizeof(JsonDocumentBuffer) / sizeof(JsonDocumentBuffer[0]);
    char test[300];
    strcpy(test, create_monitor_with_helpers());
    IOT_INFO("Update Shadow: %s", test);
    rc = aws_iot_shadow_update(mqttClient, AWS_IOT_MY_THING_NAME, test,ShadowUpdateStatusCallback, NULL, 10, true);//数字为超时时间          aws_iot_shadow_update








int main(int argc, char **argv) 
    IoT_Error_t rc = FAILURE;
    int32_t i = 0;
    char *pJsonStringToUpdate;
    jsonStruct_t powerHandler;                                        //aws c sdk里state中某个属性的结构 这里定义power
    powerHandler.cb = power_Callback;     //当接受delta消息有该参数时触发的回调函数地址
    powerHandler.pKey = "power";          //属性名称
    powerHandler.pData = &(camera.power); //属性值地址
    powerHandler.dataLength = sizeof(int);//属性大小
    powerHandler.type = SHADOW_JSON_INT32;//属性类型
    jsonStruct_t streamHandler;                                       //aws c sdk里state中某个属性的结构 这里定义stream
    streamHandler.cb = stream_Callback;
    streamHandler.pKey = "stream";
    streamHandler.pData = &(camera.stream);
    streamHandler.dataLength = sizeof(int);
    streamHandler.type = SHADOW_JSON_INT32;

    jsonStruct_t HandlerArray[2] = powerHandler, streamHandler;
    //******************完成client为接入 iot server 不用更改*************//
    char rootCA[PATH_MAX + 1];
    char clientCRT[PATH_MAX + 1];
    char clientKey[PATH_MAX + 1];
    char CurrentWD[PATH_MAX + 1];
    IOT_INFO("\\nAWS IoT SDK Version %d.%d.%d-%s\\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);
    getcwd(CurrentWD, sizeof(CurrentWD));
    snprintf(rootCA, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_ROOT_CA_FILENAME);
    snprintf(clientCRT, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_CERTIFICATE_FILENAME);
    snprintf(clientKey, PATH_MAX + 1, "%s/%s/%s", CurrentWD, certDirectory, AWS_IOT_PRIVATE_KEY_FILENAME);
    AWS_IoT_Client mqttClient;
    ShadowInitParameters_t sp = ShadowInitParametersDefault;
    sp.pHost = AWS_IOT_MQTT_HOST;
    sp.port = AWS_IOT_MQTT_PORT;
    sp.pClientCRT = clientCRT;
    sp.pClientKey = clientKey;
    sp.pRootCA = rootCA;
    sp.enableAutoReconnect = false;
    sp.disconnectHandler = NULL;
    IOT_INFO("Shadow Init");
    rc = aws_iot_shadow_init(&mqttClient, &sp);
    if(SUCCESS != rc) 
        IOT_ERROR("Shadow Connection Error");
        return rc;
    
    ShadowConnectParameters_t scp = ShadowConnectParametersDefault;
    scp.pMyThingName = AWS_IOT_MY_THING_NAME;
    scp.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID;
    scp.mqttClientIdLen = (uint16_t) strlen(AWS_IOT_MQTT_CLIENT_ID);
    IOT_INFO("Shadow Connect");
    rc = aws_iot_shadow_connect(&mqttClient, &scp);
    if(SUCCESS != rc) 
        IOT_ERROR("Shadow Connection Error");
        return rc;
    
    rc = aws_iot_shadow_set_autoreconnect_status(&mqttClient, true);
    if(SUCCESS != rc) 
        IOT_ERROR("Unable to set Auto Reconnect to true - %d", rc);
        return rc;
    
    
    
    //*******************************//                                                                  //aws_iot_shadow_register_delta
    rc = aws_iot_shadow_register_delta(&mqttClient, &streamHandler);//注册收到delta消息 stream内容的结构 收到delta消息时会触发回调函数 stream_Callback                     
    rc = aws_iot_shadow_register_delta(&mqttClient, &powerHandler); //注册收到delta消息 power内容的结构  收到delta消息时会触发回调函数 power_Callback
    if(SUCCESS != rc) 
        IOT_ERROR("Shadow Register Delta Error");
    
    else
        IOT_INFO("Shadow Register Success");
        camera.power = 1;
        camera.stream = 0;                                                           数字为超时时间                                       
        aws_iot_shadow_get(&mqttClient, AWS_IOT_MY_THING_NAME, ShadowGetStatusCallback, NULL, 2, true);  //aws_iot_shadow_get
        // while(updateFlag==0)                                                                         //启动时获取设备配置 shadow_get的结果将在callback中传递给程序
        //  sleep(1);
        // 
        // iot_reporte(&mqttClient, HandlerArray);   //调用aws_iot_shadow_update
        // 上线自检 更新状态
    


    while(NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc) 
        rc = aws_iot_shadow_yield(&mqttClient, 200);//此函数可以在单独的线程中使用,等待传入消息,确保使用AWS服务保持连接。它还确保清除Shadow操作的过期请求并执行Timeout回调。
        if(NETWORK_ATTEMPTING_RECONNECT == rc) 
            continue;
        
        if(reporetedFlag == 1)   //检测状态改变标志位 进行reported当前状态
            IOT_INFO("stream and power handle function");  
            iot_reporte(&mqttClient, HandlerArray);                                                      //调用aws_iot_shadow_update
            reporetedFlag = 0;
        
        sleep(1);
    

    if(SUCCESS != rc) 
        IOT_ERROR("An error occurred in the loop %d", rc);
    
    IOT_INFO("Disconnecting");
    rc = aws_iot_shadow_disconnect(&mqttClient);           
    if(SUCCESS != rc) 
        IOT_ERROR("Disconnect error %d", rc);
    
    return rc;

以上是关于AWS IOT Device C SDK 使用的主要内容,如果未能解决你的问题,请参考以下文章

同时使用 AWS IOT 获取多台设备状态的问题

aws iot 使用 php sdk 订阅?

使用 Golang-AWS-SDK IoTDataPlane 到 AWS IoT 的 HTTP POST

如何使用IoT规则将数据从AWS IoT发送到AWS DynamoDB v2

设备如何使用go sdk轻松连接华为云IoT平台

使用mitmproxy嗅探双向认证ssl链接——嗅探AWS IoT SDK的mqtts