TuyaOS开发学习笔记(2)——NB-IoT开发SDK架构、运行流程

news2024/11/25 14:05:12

一、SDK架构

1.1 架构框图

基于 TuyaOS 系统,可以裁剪得到的适用于 NB-IoT 协议产品接入的 SDK。SDK 将设备配网、上下行数据通信、产测授权、固件 OTA 升级等接口进行封装,并提供相关函数。

1.2 目录结构

1.2.1 TuyaOS目录说明

  • adapter:TuyaOS kernel 适配层目录。包含了 TuyaOS kernel adapter layer 定义的标准接口头文件。
  • apps:TuyaOS 应用程序目录。包含了开发框架自带的演示程序,开发者应用程序。
    • tuyaos_demo_nb_sample:基础的数据上报与下发演示demo。
    • tuyaos_demo_nb_3rdcloud_app:接入第三方云应用demo。
  • build:编译配置文件目录
  • docs:TuyaOS 文档目录。包含了 TuyaOS 的使用说明、接口文档、各个功能模块的介绍和使用说明。
  • include:TuyaOS 外部头文件目录。包含了 TuyaOS 对外提供服务的功能组件的接口文件。
    • adapter:平台驱动适配目录
    • base:基础头文件。自动生成的通用头文件。
    • components:组件头文件,对外提供服务的组件头文件。
  • libs:TuyaOS 库文件目录。包含了组件的静态、动态库文件。库文件名一般为 libtuyaos.a,或者 libtuya_iot.so,也可以包含其他的名称的库,可以按需链接。
  • vendor:原厂 SDK,
  • CHANGELOG.md:修改记录。记录了各个版本的修改记录,包括修改的 bug,新增的特性支持。
  • LICENSE:授权声明。介绍使用 TuyaOS 开发框架的方式和范围、知识产权等。
  • README.md:介绍文档。包含了介绍、下载、编译、接口文档链接、应用对接文档链接等内容。
  • build_app.sh:应用编译入口脚本文件。编译脚本,用户可以根据自己的需求进行修改、适配。可以按照需求对 build_app.sh 的内容进行定制,比如说有较大的、特殊的 TuyaOS 开发框架,可以存放在指定的位置,在 build_app.sh 里进行下载。支持 sh、bat、py 格式。

1.2.2 应用程序及Demo目录说明

此处展示的 Demo 是 TuyaOS NB-IoT 开发包最基本的 Demo,开发者可以通过该 Demo 体验开发包支持的几乎所有功能,当然也可以基于该 Demo 开发任何产品。

  • tuyaos_demo_nb_sample:基础的数据上报与下发演示demo。
  • tuyaos_demo_nb_3rdcloud_app:接入第三方云应用demo。

1.2.3 组件(含库)目录说明

组件是 TuyaOS NB-IoT 开发包的主体部分,TuyaOS 的目标就是实现代码的组件化,熟练地掌握常用组件的基本原理和实现方法对于产品开发可以达到事半功倍的效果。

1.2.4 原厂SDK目录说明

Vender 是开发环境所在目录,包含芯片原厂 SDK、各类适配层以及通用头文件,由涂鸦和芯片原厂共同维护。

  • mt2625:MTK芯片原厂SDK。
  • toolchain:编译工具链。
  • tuyaos/tuya_os_adapter:TuyaOS 各类适配层。
    • include:通用头文件。为保证 TKL(Tuya Kernel Layer)层以上能够达到一套代码适用于多个芯片平台的目标,Flash 地址、外设引脚、线程优先级等平台相关的因素都通过统一的宏定义设置。
    • driver:涉及TKL(Tuya Kernel Layer)层 NB-IoT、外设驱动(ADC、Flash、GPIO、I2C、SPI、UART……)等适配。
    • system:涉及TKL(Tuya Kernel Layer)层系统驱动(Memory、Network、OTA、Mutex、Semaphore、Thread……)等适配。

二、运行流程

2.1 涂鸦SDK初始化流程

2.1.1 tuya_app_main

static void app_init_thread(void* param)
{
    user_main();
    /* Kill init thread after all init tasks done */
    tal_thread_delete(app_init_task);
    app_init_task = NULL;
}

void tuya_app_main(void)
{
	THREAD_CFG_T cfg = {
		.priority = TASK_PRIO_NORMAL,
		.stackDepth = 4096*2,
		.thrdname = "app_init_thread",
	};
	tal_thread_create_and_start(&app_init_task, NULL, NULL, app_init_thread, NULL, &cfg);
}

2.1.2 user_main()

void user_main(void)
{
    OPERATE_RET op_ret = OPRT_OK;

    //涂鸦Device OS   日志及kv初始化:不要修改
    tuya_nbiot_init_params();

    // 应用初始化前置准备工作,用户在此处可以进行一些设置,为后续继续标准化预留
    pre_init();

    //涂鸦Device OS SDK 初始化前准备:不要修改
    #ifdef TUYA_RELEASE
    __tuya_nbiot_pre_init(APP_BIN_NAME, USER_SW_VER, true);
    #else
    __tuya_nbiot_pre_init(APP_BIN_NAME, USER_SW_VER, false);
    #endif

    // 产测初始化, 注册函数需要应用实现,其中串口驱动不需要应用提供
    MF_IMPORT_INTF_S user_intf = {
        .user_test = tuya_user_prod_test,
    };
    mf_test_system_start(&user_intf,APP_BIN_NAME, USER_SW_VER);

    //涂鸦Device OS SDK 初始化:不要修改
    __tuya_nbiot_init();

    //应用初始化
    device_init();

    //标记涂鸦应用初始化完成:不要修改
    tuya_nbiot_set_initialized();
}

2.2 设备应用初始化流程

2.2.1 pre_init()

此阶段对应初始化 NBIOT SDK 之前需要做的一些工作,用户可以根据自己的需求在 tuya_device.c 文件中实现,也可以不实现,不实现便不会执行,该函数主要用于一些外设的基本配置与需要上电快速启动的一些功能,例如:唤醒引脚初始化ADC 初始化快速点亮 LED 灯 或者 使能外设 等操作。注意:请不要在此函数中使用较长时间延时。

例如在 tuyaos_demo_nb_sample 基础的数据上报与下发演示 Demo 中进行 按键初始化与中断配置LED 灯 GPIO 配置

int pre_init(void)
{
    /*
    该位置仅可以添加系统启动时硬件相关的初始化操作例如GPIO、ADC、I2C等
    注:UART1不可在此处配置,请在device_init()内配置
        请不要在此处操作长时间延时
    */

    tuya_key_init_test();
    tuya_gpio_init_test();
    return 0;
}

例如在 tuyaos_demo_nb_3rdcloud_app 接入第三方云应用 Demo 中进行 接入云参数配置

int pre_init(void)
{
    TAL_NBIOT_LWM2M_REGISTER_T params;
    int ret = 0;

    params.bootstrap_en     = 0;                        // ctcc及直连:不开启bs;cmcc:drx专网不开启,psm网络开启
    params.srv_ip           = "117.60.157.137";         //服务器地址,电信线上
    params.srv_port         = 5684;                     //服务器端口号,5684(加密),5683(不加密),移动暂时支持不加密
    params.isp_type         = NBIOT_ISP_OTHER;          //NBIOT_ISP_TUYA:表示直连三方云;否则连运营商云中转
    params.lifetime         = 7200;                     //lwm2m协议交互心跳间隔,单位:秒
    params.psk              = "bFFFcDDDEB7aaBbc";       //16~32个字符lwm2m协议交互秘钥
    //params.imei             = "862363050000149";        //15个字符的imei,可以由底层获取,可选!/*endpoint_name,pskid*/
    //device attribute:
    params.attri.obj_id = 19;
    params.attri.ins_id_up = 0;
    params.attri.ins_id_down = 1;
    params.attri.res_id = 0;
    ret = tuya_user_api_3rd_cloud_config(&params);   //返回0:成功
    return ret;
}

2.2.2 device_init()

此阶段用于初始化产品功能,用户根据自己的需求在 tuya_device.c 文件中实现。如果是连接涂鸦云,需要配置 PRODUCT_KEY 与一些必要的回调注册,下面以一种经典的场景举例介绍该函数的使用方法:

int device_init(void)
{
    int ret = OPRT_OK;
    // 配置产品 PID
    tuya_user_api_set_product_key(PRODUCT_KEY);
    // 设置事件捕获回调函数
    tuya_user_api_event_loop_set_cb(tuya_event_process_cb, NULL);
    // 启动事件捕获任务
    tuya_user_api_event_loop_start();
    // 设置云端下发数据点回调函数
    tuya_user_api_dp_write_default_cb(tuya_dp_write_cb);
    // 设置记录型数据点上报结果回调函数
    tuya_user_api_dp_report_record_ack_register_cb(dp_report_notify_callback);
    // 设置心跳时间
    tuya_user_api_lifetime_set(600);
    // 设置记录型数据在弱网条件下的上报时间间隔
    tuya_user_api_record_dp_lifetime_set(600);
    /*
    此处可创建用户任务
    */
    return ret;
}

2.3 系统事件捕获流程

  • svc_nb NB-IoT服务组件

API 位于 TuyaOS/include/components/svc_nb/include/tuya_event_loop.h

首先在 device_init() 函数中进行 tuya_user_api_event_loop_set_cb() 设置事件捕获回调和 tuya_user_api_event_loop_start() 启动事件捕获任务。

int device_init(void)
{
    ···
    ···
    // 设置事件捕获回调函数
    tuya_user_api_event_loop_set_cb(tuya_event_process_cb, NULL);
    // 启动事件捕获任务
    tuya_user_api_event_loop_start();
    ···
    ···
}

2.3.1 系统事件捕获回调

在事件捕获回调 tuya_event_process_cb() 中进行判断和处理 SDK 返回的事件 ID

static OPERATE_RET tuya_event_process_cb(void* ctx, system_event_t* event)
{
    USER_API_LOGD("tuya user event:%d",(event->event_id));
    switch (event->event_id) {
        case SYSTEM_EVENT_NETWORK_DISCONNECT:
            if (STR_EQU(event->event_info.param, "TRUE")) {
                //网络断开,数据无法发送!
                USER_API_LOGD("SYSTEM_EVENT_NETWORK_DISCONNECT");
            }
            break;

        case SYSTEM_EVENT_NETWORK_READY:
            USER_API_LOGD("SYSTEM_EVENT_NETWORK_READY");
            break;

        case EVENT_LWM2M_CONNECTED:
            USER_API_LOGD("EVENT_LWM2M_CONNECTED");
            break;

        case EVENT_LWM2M_READY:
            USER_API_LOGD("EVENT_LWM2M_READY");
            data_send();
            break;

        case SYSTEM_EVENT_GOING_REBOOT:
            //系统准备重启!
            USER_API_LOGD("SYSTEM_EVENT_GOING_REBOOT");
            break;

        case SYSTEM_EVENT_GOING_SLEEP:
            //系统准备进入睡眠!
            USER_API_LOGD("SYSTEM_EVENT_GOING_SLEEP");
            break;

        default:
            break;
    }
    return OPRT_OK;
}

2.3.2 系统事件ID

位于 TuyaOS/include/components/svc_nb/include/tuya_comm.h 中,事件 ID 包含以下各种状态:

typedef enum {
    SYSTEM_EVENT_ID_CARD,           //设备识别到SIM卡正常
    SYSTEM_EVENT_NO_ID_CARD,        //设备未识别到SIM卡
    SYSTEM_EVENT_NETWORK_READY,     //成功附着基站
    SYSTEM_EVENT_NETWORK_DISCONNECT,//网络断开
    SYSTEM_EVENT_REG_DENIED,
    SYSTEM_EVENT_BE_AWAKENED,       //设备正准备睡眠时被打断醒来!
    SYSTEM_EVENT_DELAY_SLEEP,       //进入睡眠倒计时阶段!
    SYSTEM_EVENT_GOING_SLEEP,       //马上进入睡眠!
    SYSTEM_EVENT_DELAY_REBOOT,      //进入重启倒计时阶段!
    SYSTEM_EVENT_GOING_REBOOT,      //设备正在重启
    SYSTEM_EVENT_WAKE_FROM_NORMAL_RTC_TIMEOUT,        //普通RTC超时唤醒
    SYSTEM_EVENT_WAKE_FROM_DISCRETE_RTC_TIMEOUT,      //离散RTC超时唤醒
    EVENT_LWM2M_CONNECTED,          //已连接LWM2M服务器
    EVENT_LWM2M_READY,              //LWM2M网络服务已可用
    EVENT_LWM2M_UPDATE_SUCCESS,     //数据上报成功
    EVENT_LWM2M_RESPONSE_SUCCESS,   //数据响应成功 
    EVENT_LWM2M_SEND_FAIL,          //LWM2M协议层发送失败
    EVENT_LWM2M_RESTART,            //LWM2M网络重连
    EVENT_DEVICE_INFO_RESET,        //设备信息重置
    EVENT_DEVICE_BIND_ON,           //设备已绑定
    EVENT_DEVICE_UNBIND_ON,         //设备未绑定
    EVENT_DEVICE_DEACTIVE,          //设备重置 
    EVENT_POWERKEY_PRESS,           //POWER按键被按下
    EVENT_SLP_UNLOCK,    
    EVENT_FOTA_UPDATE_DELAY,
    EVENT_HEARTBEAT_SEND,           //心跳发送
    EVENT_FACTORY_RESETING,
    EVENT_COMPOSITE_ACTIVE_SUCCESS, //复合产品NB为X模组激活成功
    EVENT_LWDP_PACKET_SEND,         //LWDP数据包异步发送
    EVENT_SLEEP_TYPE,               //睡眠事件类型
    EVENT_DISCRETE_ON,              //离散开始
    EVENT_CFUN_ON,
    EVENT_HEARTBEAT_LIFETIME_UPDATE,     //心跳周期更新
    SYSTEM_EVENT_MAX
} system_event_id_t;

主要事件包括:

  • 当设备读到SIM卡后,响应 SYSTEM_EVENT_ID_CARD 此事件。
  • 当网络注册上基站后,响应 SYSTEM_EVENT_NETWORK_READY 此事件。
  • 当ISP模式(代理服务器模式)时,设备会先与代理服务器通讯,通讯正常,则设备响应 EVENT_LWM2M_READY 事件。
  • 当设备登录上代理服务器,则响应 EVENT_LWM2M_CONNECTED 事件。
  • 当设备网络断开,响应 SYSTEM_EVENT_NETWORK_DISCONNECT 事件。

• 由 Leung 写于 2023 年 9 月 9 日

• 参考:SDK 架构-TuyaOS-涂鸦开发者
    TuyaOS>NB-IoT开发框架>能力地图>设备初始化

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

transformer 总结(超详细-初版)

相关知识链接 attention1attention2 引言 本文主要详解 transformer 的算法结构以及理论解释,代码实现以及具体实现时候的细节放在下一篇来详述。 下面就通过上图中 transformer 的结构来依次解析 输入部分(Encode 侧) input 输出主要包含 两个部分&#xff1a…

[acwing周赛复盘] 第 120 场周赛20230909

[acwing周赛复盘] 第 120 场周赛20230909 总结5146. 最大GCD1. 题目描述2. 思路分析3. 代码实现 5147. 数量1. 题目描述2. 思路分析3. 代码实现 5148. 字符串匹配1. 题目描述2. 思路分析3. 代码实现 六、参考链接 总结 T1好难啊。T1 数学T2 dfs/数位dpT3 计数贪心 5146. 最大…

第51节:cesium 范围查询(含源码+视频)

结果示例: 完整源码: <template><div class="viewer"><el-button-group class="top_item"><el-button type=

render和jsx

render和jsx 1..vue文件最后会变成一个对象。 一个vue文件要么是render写法&#xff0c;要么是模板写法。 为什么React在大型项目中比较适合&#xff1f; 在大型项目中比较适合&#xff1f; 因为React使用jsx&#xff0c;比较灵活。

ISYSTEM调试实践11-Profiler Timeline和软件运行时间分析

一 前言 本文主要内容是讨论嵌入式软件的时间分析&#xff0c;供大家探讨&#xff0c;如果有疑问欢迎探讨。 对于汽车软件&#xff0c;往往对执行的时序和代码运行的时间有着严格要求。对于在主循环内执行的任务函数&#xff0c;不论是手写还是Autosar生成,能否节拍执行到&…

flink时间处理语义

背景 在flink中有两种不同的时间处理语义&#xff0c;一种是基于算子处理时间的时间&#xff0c;也就是以flink的算子所在的机器的本地时间为准&#xff0c;一种是事件发生的实际时间&#xff0c;它只与事件发生时的时间有关&#xff0c;而与flink算子的所在的本地机器的本地时…

利用grafana展示Zabbix数据可视化

导入zabbix数据源&#xff0c;可以直接创建图形了。 单击“”按钮&#xff0c;选择创建仪表盘&#xff0c;单击要创建的图形&#xff0c;图形种类有很多&#xff0c;常用的有图表&#xff0c;列表&#xff0c;报警清单&#xff0c;zabbix触发器&#xff0c;文本。 创建巡检图形…

C++ 多线程 学习笔记

线程睡眠很稳定&#xff0c;但无线程睡眠不稳定 线程调用类方法&#xff1a; 有参数时调用方法&#xff1a; 当参数为引用时&#xff1a; 当同一资源被多个线程同时引用时&#xff0c;为防止资源抢占&#xff0c;使用mutex&#xff0c;互斥锁 头文件#include "mutex"…

蓝桥杯官网练习题(纸牌三角形)

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 A,2,3,4,5,6,7,8,9 共 99 张纸牌排成一个正三角形&#xff08;A 按 1 计算&#xff09;。要求每个边的和相等。 下图就是一种排法。 这样的排法可能会有很多。 如果…

thinkphp6-简简单单地开发接口

目录 1.前言TP6简介 2.项目目录3.运行项目运行命令访问规则 4.model db使用db连接配置model编写及调用调用接口 5.返回json格式 1.前言 基于上篇文章环境搭建后&#xff0c;便开始简单学习上手开发接口…记录重要的过程&#xff01; Windows-试用phpthink发现原来可这样快速搭…

Spring Data JPA:简化数据库交互的艺术

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Jmeter 实现 mqtt 协议压力测试

1. 下载jmeter&#xff0c;解压 https://jmeter.apache.org/download_jmeter.cgi 以 5.4.3 为例&#xff0c;下载地址&#xff1a; https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.4.3.zip linux下解压&#xff1a; unzip apache-jmeter-5.4.3.zip 2. 下载m…

六)Stable Diffussion使用教程:图生图SD Upscale

这一篇说说SD放大(SD Upscale)。 图生图是没有 “高清修复” 选项的,因为从文生图的高清修复原理来看,图生图本身就是高清修复:只需要在重绘目标图像时,等比例增大图像的分辨率就可以了。 这里我们通过图库浏览器浏览一张图片,然后点击图生图,图片的所有出图参数就会…

运维学习之采集器 node_exporter 1.3.1安装并使用

参考《监控系统部署prometheus基本功能》先完成prometheus部署。 wget https://github.com/prometheus/node_exporter/releases/download/v1.3.1/node_exporter-1.3.1.linux-amd64.tar.gz下载压缩包。 tar -zxf node_exporter-1.3.1.linux-amd64.tar.gz进行解压。 cp node_e…

安全实战 | 怎么用零信任防范弱密码?

防范弱密码&#xff0c;不仅需要提升安全性&#xff0c;更需要提升用户体验。 比如在登录各类业务系统时&#xff0c;我们希望员工登录不同系统不再频繁切换账号密码&#xff0c;不再需要3-5个月更换一次密码&#xff0c;也不再需要频繁的输入、记录、找回密码。 员工所有的办…

Spring Boot与Kubernetes:现代云部署的完美组合

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

第六章 图 四、图的广度优先遍历(BFS算法、广度优先生成树、广度优先生成森林)

一、实现步骤 广度优先遍历的实现步骤如下&#xff1a; 1.从图的某一个节点开始&#xff0c;将该节点标记为已经访问过的节点。 2.将该节点加入到队列中。 3.当队列非空时&#xff0c;执行以下操作&#xff1a; a. 取出队列队首节点&#xff0c;并遍历该节点与之相邻的所有…

Spring AOP:面向切面编程在实际项目中的应用

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

算法之位运算

前言 位运算在我们的学习中占有很重要的地位&#xff0c;从二进制中数的存储等都需要我们进行位运算 一、位运算复习 1.位运算复习 按位与(&)&#xff1a;如果两个相应的二进制位都为1&#xff0c;则该位的结果值才为1&#xff0c;否则为0 按位或( | )&#xff1a;如果…

Spring Batch:处理大数据和批量任务的解决方案

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…