如何用C语言实现 IoT Core

涂鸦 IoT Core SDK 使用 C 语言实现,支持涂鸦设备模型协议,适用于开发者自主开发硬件设备逻辑业务接入涂鸦。

功能概述

涂鸦 IoT Core SDK 提供设备激活、发送上下行 DP 和固件 OTA 升级等基础业务接口封装。SDK 不依赖具体设备平台及操作系统环境,也可以运行在单任务环境。仅需要支持 TCP/IP 协议栈及提供 SDK 必要的系统依赖接口,即可完成接入。

开发步骤

第一步:下载 SDK

先在在 涂鸦 GitHub 仓库 下载 IoT Core SDK。

该 SDK 的 C 代码文件通过以下目录结构提供:

文件 说明
certs 设备私钥,设备证书,服务端 CA 根证书
docs 参考文档
libraries 外部依赖库,包含 MQTT client、HTTP client、mbedTLS 等
interface 平台必要移植接口,SDK 功能接口
include SDK 有文件,包含了 SDK API
src SDK 源代码
platform 平台移植接口适配
utils 通用工具模块
examples 例程

第二步:配置设备信息

首先需要在涂鸦 IoT 开发平台创建产品,获取授权信息,然后将产品和授权相关信息写入到代码中,实现云服务的接入。详细步骤如下:

  1. 登录 涂鸦 IoT 开发平台。

  2. 单击 创建产品

    IoT Core SDK(C)

  3. 选择 行业解决方案 > 智慧工业 > 工业网关 品类。

    如何用C语言实现 IoT Core_第1张图片

  4. 在 智能化方式 区域选择 生态设备接入,并填写产品相关信息,完成产品创建。

    如何用C语言实现 IoT Core_第2张图片

  5. 在 功能定义 界面,单击 添加功能 并填写相关参数,完成产品功能定义。

    如何用C语言实现 IoT Core_第3张图片

  6. 在 设备开发 界面,选择并下载 SDK 方案,单击 下一步 进入激活信息获取页面。

    如何用C语言实现 IoT Core_第4张图片

  7. 领取授权码,然后单击 注册设备。设备相应信息会显示在下方。

    涂鸦提供免费的授权码供测试使用,可以免费领取 2 个激活码。

    如何用C语言实现 IoT Core_第5张图片

  8. 将注册的设备信息,填写到 examples/subdevice_basic_demo/subdevice_basic_demo.c 文件中,编译并运行 Demo 即可连接云服务,关于编译的具体流程,请参考下文编译执行章节内容。

    如何用C语言实现 IoT Core_第6张图片

    const char productId[] = "rwosj58aaqjk **** ";
    const char deviceId[] = "6c95875d0f5ba69607 **** ";
    const char deviceSecret[] = " ******************* ";
    

    可通过购买授权码,在设备管理页面进行设备注册,获取 productIddeviceIddeviceSecret 等信息。

第三步:编译执行(Ubuntu)

本小节以 Ubuntu 系统为例,介绍 SDK 编译步骤。本节介绍同样适用于 Debian 系统。

  1. 安装 make 等相关环境依赖。

    sudo apt-get install make cmake
    
  2. 进入获取到的 SDK 文件内,新建一个 build 文件夹并且进入该文件夹,输入 cmake.. 先进行环境编译,再输入 make 开始编译固件。编译完成后,固件会生成在 build 文件夹下的 bin 文件夹。

    mkdir build && cd build
    cmake ..
    make
    
  3. 进入 bin 文件夹,运行 Demo。SDK 内置了基础的通信 Demo 代码,例如子设备管理基础 Demo。

    ./bin/subdevice_basic_demo
    
  4. 在设备端查看运行接口。

    以下日志显示设备与云端连接成功。

    如何用C语言实现 IoT Core_第7张图片

  5. 设备成功连接到涂鸦 IoT 开发平台后,单击进行刷新,设备状态会显示为在线。

    如何用C语言实现 IoT Core_第8张图片

应用示例

  1. 实例化和初始化一个设备对象 tuya_iot_client_t,用来初始化产品 ID 和授权信息等配置参数。

    /* instantiate the client */
    tuya_mqtt_context_t* client = &client_instance;
    
    /* initialize the client */
    ret = tuya_mqtt_init(client, &(const tuya_mqtt_config_t) {
        .host = "m2.tuyacn.com",
        .port = 8883,
        .cacert = tuya_cacert_pem,
        .cacert_len = sizeof(tuya_cacert_pem),
        .device_id = deviceId,
        .device_secret = deviceSecret,
        .keepalive = 60,
        .timeout_ms = 2000,
        .on_connected = on_connected,
        .on_disconnect = on_disconnect,
        .on_messages = on_messages
    });
    
  2. 定义应用层事件回调,回调函数用于应用层接收 SDK 事件通知,如数据功能点(DP)下发,云端连接状态通知。

    /* Tuya SDK event callback */
    void on_messages(tuya_mqtt_context_t* context, void* user_data, const tuyalink_message_t* msg)
    {
        TY_LOGI("on message id:%s, type:%d, code:%d", msg->msgid, msg->type, msg->code);
        switch (msg->type) {
            case THING_TYPE_MODEL_RSP:
                TY_LOGI("Model data:%s", msg->data_string);
                break;
    
            case THING_TYPE_PROPERTY_SET:
                TY_LOGI("property set:%s", msg->data_string);
                break;
    
            case THING_TYPE_PROPERTY_REPORT_RSP:
                break;
    
            default:
                break;
        }
    printf("\r\n");
    }
    
  3. 启动 TuyaOS SDK 服务。

    ret = tuya_mqtt_connect(client);
    //TuyaOS SDK 服务任务,数据接收处理,设备在线保活等任务处理:
    
  4. 循环调用将当前线程产生给底层的 Link SDK 客户端。

    tuya_mqtt_loop(client);
    
  5. 定义上报函数,调用相关上报接口函数实现数据上报。下方示例为产品连接时,将部分产品数据上报到云端。大家可以根据自己产品的数据上报需求,参考该函数编写自身应用代码。

     void on_connected(tuya_mqtt_context_t* context, void* user_data)
    {
    TY_LOGI("on connected");
    
    /* data model test code */
    tuyalink_thing_data_model_get(context, NULL);
    tuyalink_thing_desired_get(context, NULL, "[\"power\"]");
    tuyalink_thing_property_report(context, NULL, "{\"power\":    {\"value\":1234,\"time\":1631708204231}}");
    tuyalink_thing_property_report_with_ack(context, NULL, "{\"power\":{\"value\":1234,\"time\":1631708204231}}");
    tuyalink_thing_event_trigger(context, NULL, "{\"eventCode\":\"boom\",\"eventTime\":1626197189630,\"outputParams\":{\"param1\":100}}");
    tuyalink_thing_batch_report(context, "{\"msgId\":\"45lkj3551234001\",\"time\":1626197189638,\"sys\":{\"ack\":1},\"data\":{\"properties\":{\"power\":{\"value\":11,\"time\":1626197189638}},\"events\":{\"boom\":{\"outputParams\":    {\"param1\":\"10\"},\"eventTime\":1626197189001}}}}");
    }
    
    /*数据上报 API*/
    /* data model code */
    tuyalink_thing_data_model_get(context, NULL);
    tuyalink_thing_desired_get(context, NULL, "[\"power\"]");
    tuyalink_thing_property_report(context, NULL, "{\"power\":{\"value\":1234,\"time\":1631708204231}}");
    tuyalink_thing_property_report_with_ack(context, NULL, "{\"power\":{\"value\":1234,\"time\":1631708204231}}");
    tuyalink_thing_event_trigger(context, NULL, "{\"eventCode\":\"boom\",\"eventTime\":1626197189630,\"outputParams\":{\"param1\":100}}");
    tuyalink_thing_batch_report(context, "{\"msgId\":\"45lkj3551234001\",\"time\":1626197189638,\"sys\":{\"ack\":0},\"data\":{\"properties\":{\"power\":{\"value\":11,\"time\":1626197189638}},\"events\":{\"boom\":{\"outputParams\":{\"param1\":\"10\"},\"eventTime\":1626197189001}}}}");}
    /* subdevice code */
    tuyalink_subdevice_bind(context, "[{\"productId\":\"jtwe4q9jrs0bbc8q\",\"nodeId\":\"123456\",\"clientId\":\"123455asdf\"}]");
    tuyalink_subdevice_bind_login(context, "[\"6c17c5ba952143f592b8g1\",\"6c41626e5cea758aees0ik\"]");
    tuyalink_subdevice_bind_logout(context, "[\"6c17c5ba952143f592b8g1\"]");
    tuyalink_subdevice_topo_add(context, "[{\"productId\":\"jtwe4q9jrs0bbc8q\",\"deviceId\":\"6c17c5ba952143f592b8g1\",\"sign\":\"366508ed895644e70a3006bdef2dbe77ef73e18a\",\"signMethod\":\"hmacSha1\",\"timestamp\":\"1636989480\"}]");
    tuyalink_subdevice_topo_delete(context,"[\"6c41626e5cea758aees0ik\"]");
    tuyalink_subdevice_topo_get(context);
    

设备调试

设备成功连接 MQTT 服务器并上线后,可以在涂鸦 IoT 开发平台设备调试页面对设备进行调试。

  1. 进入 设备调试 页面,单击 选择设备,填入上线设备的 DeviceID,即可获取到设备当前定义的功能点合集。

    如何用C语言实现 IoT Core_第9张图片

  2. 设备操作的日志信息都会显示在右侧实时日志处,大家可以通过日志确认设备当前的信息。

    如何用C语言实现 IoT Core_第10张图片

  3. 单击功能点操作列的 获取 选项,可以获取到当前设备的数据。

    如何用C语言实现 IoT Core_第11张图片

  4. 单击功能点操作列的 设置 选项,可以对设备当前的数据进行设置,日志处会显示当前云端下发的 payload 日志信息,通过本地 log 也可以看到云端下发的 payload 信息。

    如何用C语言实现 IoT Core_第12张图片

接口说明

SDK 初始化

接口信息 说明
函数原型 int tuya_mqtt_init(tuya_mqtt_context_t* context, const tuya_mqtt_config_t* config);
功能描述 设备初始化
输入参数
  • context:设备管理句柄
  • config:设备初始化信息配置
输出参数
返回值 参考通用错误码

启动服务

接口信息 说明
函数原型 int tuya_mqtt_connect(tuya_mqtt_context_t* context);
功能描述 启动设备 SDK 服务
输入参数 context:设备管理句柄
输出参数
返回值 参考通用错误码

停止服务

接口信息 说明
函数原型 int tuya_mqtt_disconnect(tuya_mqtt_context_t* context);
功能描述 停止设备 SDK 服务
输入参数 context:设备管理句柄
输出参数
返回值 参考通用错误码

后台运行服务

接口信息 说明
函数原型 int tuya_mqtt_loop(tuya_mqtt_context_t* context);
功能描述 SDK 后台运行服务
输入参数 context:设备管理句柄
输出参数
返回值 参考通用错误码
备注 需要在程序主循环调用该服务函数

获取设备物模型

接口信息 说明
函数原型 int tuyalink_thing_data_model_get(tuya_mqtt_context_t* context, const char* device_id);
功能描述 使用该函数获取设备的物模型
输入参数
  • context:设备管理句柄
  • device_id:设备 ID
输出参数
返回值 参考通用错误码

设备属性上报

接口信息 说明
函数原型 int tuyalink_thing_property_report(tuya_mqtt_context_t* context, const char* device_id, const char* data);
功能描述 设备属性上报
输入参数
  • context:设备管理句柄
  • device_id:设备 ID
输出参数
返回值 参考通用错误码

设备属性上报(包含应答)

接口信息 说明
函数原型 int tuyalink_thing_property_report_with_ack(tuya_mqtt_context_t* context, const char* device_id, const char* data);
功能描述 上报设备的属性并得到云端应答
输入参数
  • context:设备管理句柄
  • device_id:设备 ID
  • data:上报的属性数据
输出参数
返回值 参考通用错误码

设备事件响应

接口信息 说明
函数原型 int tuyalink_thing_event_trigger(tuya_mqtt_context_t* context, const char* device_id, const char* data);
功能描述 设备事件响应
输入参数
  • context:设备管理句柄
  • device_id:设备 ID
  • data:事件数据
输出参数
返回值 参考通用错误码

设备批量上报

接口信息 说明
函数原型 int tuyalink_thing_batch_report(tuya_mqtt_context_t* context, const char* data);
功能描述 设备批量上报数据
输入参数
  • context:设备管理句柄
  • data:数据
输出参数
返回值 参考通用错误码

子设备绑定

接口信息 说明
函数原型 int tuyalink_subdevice_bind(tuya_mqtt_context_t* context, const char* data);
功能描述 子设备绑定
输入参数
  • context:设备管理句柄
  • data:数据
输出参数
返回值 参考通用错误码

子设备上线

接口信息 说明
函数原型 int tuyalink_subdevice_bind_login(tuya_mqtt_context_t* context, const char* data);
功能描述 子设备上线
输入参数
  • context:设备管理句柄
  • data:数据
输出参数
返回值 参考通用错误码

子设备下线

接口信息 说明
函数原型 int tuyalink_subdevice_bind_logout(tuya_mqtt_context_t* context, const char* data);
功能描述 子设备下线
输入参数
  • context:设备管理句柄
  • data:数据
输出参数
返回值 参考通用错误码

子设备拓扑添加

接口信息 说明
函数原型 int tuyalink_subdevice_topo_add(tuya_mqtt_context_t* context, const char* data);
功能描述 子设备拓扑添加
输入参数
  • context:设备管理句柄
  • data:数据
输出参数
返回值 参考通用错误码

子设备拓扑删除

接口信息 说明
函数原型 int tuyalink_subdevice_topo_delete(tuya_mqtt_context_t* context, const char* data);
功能描述 子设备拓扑删除
输入参数
  • context:设备管理句柄
  • data:数据
输出参数
返回值 参考通用错误码

子设备拓扑获取

接口信息 说明
函数原型 int tuyalink_subdevice_topo_get(tuya_mqtt_context_t* context);
功能描述 子设备拓扑获取
输入参数 context:设备管理句柄
输出参数
返回值 参考通用错误码

Demo 设备例程

#include 
#include 
#include 

#include "cJSON.h"
#include "tuya_cacert.h"
#include "tuya_log.h"
#include "tuya_error_code.h"
#include "system_interface.h"
#include "mqtt_client_interface.h"
#include "tuyalink_core.h"

const char productId[] = "3jbcpefnn1jxxxxx";
const char deviceId[] = "6ced2aa564727c01xxxxx";
const char deviceSecret[] = "ac5d367db39xxxxx";

tuya_mqtt_context_t client_instance;

void on_connected(tuya_mqtt_context_t* context, void* user_data)
{
    TY_LOGI("on connected");

    /* data model test code */
    tuyalink_thing_data_model_get(context, NULL);
    tuyalink_thing_desired_get(context, NULL, "[\"power\"]");
    tuyalink_thing_property_report(context, NULL, "{\"power\":{\"value\":1234,\"time\":1631708204231}}");
    tuyalink_thing_property_report_with_ack(context, NULL, "{\"power\":{\"value\":1234,\"time\":1631708204231}}");
    tuyalink_thing_event_trigger(context, NULL, "{\"eventCode\":\"boom\",\"eventTime\":1626197189630,\"outputParams\":{\"param1\":100}}");
    tuyalink_thing_batch_report(context, "{\"msgId\":\"45lkj3551234001\",\"time\":1626197189638,\"sys\":{\"ack\":0},\"data\":{\"properties\":{\"power\":{\"value\":11,\"time\":1626197189638}},\"events\":{\"boom\":{\"outputParams\":{\"param1\":\"10\"},\"eventTime\":1626197189001}}}}");
}

void on_disconnect(tuya_mqtt_context_t* context, void* user_data)
{
    TY_LOGI("on disconnect");
}

void on_messages(tuya_mqtt_context_t* context, void* user_data, const tuyalink_message_t* msg)
{
    TY_LOGI("on message id:%s, type:%d, code:%d", msg->msgid, msg->type, msg->code);
    switch (msg->type) {
        case THING_TYPE_MODEL_RSP:
            TY_LOGI("Model data:%s", msg->data_string);
            break;

        case THING_TYPE_PROPERTY_SET:
            TY_LOGI("property set:%s", msg->data_string);
            break;

        case THING_TYPE_PROPERTY_REPORT_RSP:
            break;

        default:
            break;
    }
    printf("\r\n");
}

int main(int argc, char** argv)
{
    int ret = OPRT_OK;

    tuya_mqtt_context_t* client = &client_instance;

    ret = tuya_mqtt_init(client, &(const tuya_mqtt_config_t) {
        .host = "m2.tuyacn.com",
        .port = 8883,
        .cacert = tuya_cacert_pem,
        .cacert_len = sizeof(tuya_cacert_pem),
        .device_id = deviceId,
        .device_secret = deviceSecret,
        .keepalive = 60,
        .timeout_ms = 2000,
        .on_connected = on_connected,
        .on_disconnect = on_disconnect,
        .on_messages = on_messages
    });
    assert(ret == OPRT_OK);

    ret = tuya_mqtt_connect(client);
    assert(ret == OPRT_OK);

    for (;;) {
        /* Loop to receive packets, and handles client keepalive */
        tuya_mqtt_loop(client);
    }

    return ret;
}

你可能感兴趣的:(大数据,物联网,c语言,云开发,SDK,人工智能,开发语言)