如何用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 功能接口
includeSDK 有文件,包含了 SDK API
srcSDK 源代码
platform平台移植接口适配
utils通用工具模块
examples例程

第二步:配置设备信息

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

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

  2. 单击 创建产品

    IoT Core SDK(C)

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

    IoT Core SDK(C)

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

    IoT Core SDK(C)

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

    IoT Core SDK(C)

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

    IoT Core SDK(C)

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

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

    IoT Core SDK(C)

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

    IoT Core SDK(C)

    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. 在设备端查看运行接口。

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

    IoT Core SDK(C)

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

    IoT Core SDK(C)

应用示例

  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,即可获取到设备当前定义的功能点合集。

    IoT Core SDK(C)

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

    IoT Core SDK(C)

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

    IoT Core SDK(C)

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

    IoT Core SDK(C)

接口说明

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 <assert.h>
#include <stdio.h>
#include <stdlib.h>#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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/112649.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【笔试强训选择题】Day44.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01;&#xff…

二叉树顺序结构及实现

&#x1f449;二叉树顺序结构及实现 1.二叉树的顺序结构2.堆的概念及结构3.堆的实现3.1堆向下调整算法3.2堆向上调整算法 4.堆的创建4.1堆创建方法14.1.1构建堆结构体4.1.2堆的初始化4.1.3堆数据添加向上调整4.1.4主函数内容 4.2堆的创建方法24.2.1堆数据添加向下调整 4.3堆数据…

GE WES5162-9101电源模块

GE WES5162-9101 电源模块通常用于工业自动化和控制系统中&#xff0c;用于提供稳定的电源供应。以下是该电源模块的一些主要特点&#xff1a; 电源输出&#xff1a; WES5162-9101 电源模块的主要功能是提供电源输出&#xff0c;通常以直流电压或交流电压的形式&#xff0c;以满…

C++:new 和 delete

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》《C》 文章目录 前言一、C内存管理1.内置类型2.自定义类型3.delete 与 new不匹配使用问题(VS平台下) 二、operator new 与 operator delete函数三、 new 和delete的实现原理内置类型自定义类型 四…

每日一题~二叉树的最近公共祖先

题目连接&#xff1a;236. 二叉树的最近公共祖先 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 思路分析&#xff1a; 由题可知&#xff0c;我们需要找到 p 和 q 两个二叉树的最近公共祖先节点&#xff0c;首先我们分析一下&#xff0c;这个最近公共祖先节点…

数字孪生:助力机载软件构型管理

飞机机载软件具有研发周期长、版本更新频繁、相关工程资料密集等特性。由于各个系统的软件分别由不同供应商开发&#xff0c;其设计保障等级、设计架构、实现方法等方面都各有不同&#xff0c;对机载软件进行高效、规范的构型管理显得尤为重要。 Q&#xff1a;什么是构型管理&…

如何解决 503 Service Temporarily Unavailable?

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f405;&#x1f43e;猫头虎建议程序员必备技术栈一览表&#x1f4d6;&#xff1a; &#x1f6e0;️ 全栈技术 Full Stack: &#x1f4da…

VR全景需要加盟吗?简述VR全景加盟的意义

对于一个刚开始了解VR全景行业的新人来说&#xff0c;VR全景不是有软件、有设备、会拍摄就行了吗&#xff1f;为什么还要找全景平台进行加盟呢&#xff1f;VR全景加盟的作用又是什么呢&#xff1f;那么&#xff0c;我们就不得不多问几个问题了&#xff0c;例如不加盟的话&#…

云原生Kubernetes:K8S资源控制之污点与容忍

目录 一、理论 1.污点 2.容忍 3. Pod启动阶段 4. 故障排除步骤 5.对节点执行维护操作 二、实验 1.污点 2.容忍 三、问题 1.pod上配置容忍生成资源报错 四、总结 一、理论 1.污点 &#xff08;1&#xff09;作用 节点亲和性,是Pod的一种属性(偏好或硬性要求) ,它…

无涯教程-JavaScript - ROUNDUP函数

描述 ROUNDUP函数将数字四舍五入,而不是0(零)。 ROUNDUP是Excel四舍五入函数之一。 语法 ROUNDUP (number, num_digits)争论 Argument描述Required/OptionalNumberAny real number that you want rounded up.RequiredNum_digitsThe number of digits to which you want to …

Jetson Xavier NX 与飞控(Pixhawk 4 Mini)实现串口通信

一、飞控端配置 首先对 Pixhawk 4 Mini 烧录固件参考 Kakute H7 刷写 px4 固件_想要个小姑娘的博客-CSDN博客 烧录完成后打开 QGroundControl&#xff0c;进入参数设置并搜索 MAV&#xff0c;如下所示 然后修改 MAV_1_CONFIG&#xff0c;修改为自己想要连接机载电脑&#xf…

图神经网络系列之消息传递

文章目录 1.前言2.消息传递机制1.RecGNN2.ConvGNNs3.GAT 1.前言 相比较于神经网络最基本的网络结构全连接层&#xff08;MLP&#xff09;&#xff0c;特征矩阵乘以权重矩阵&#xff0c;图神经网络多了一个邻接矩阵。计算形式很简单&#xff0c;三个矩阵相乘再加上一个非线性变…