:::warning 基于涂鸦NB-IoT模组的植物监测仪 :::
一、我们要做什么?
本项目作为我们在智慧农业中的第一个探索性项目,项目的出发点很简单,即监测环境并且采集数据,这两者是农业数字化的起点。通过监测农业环境的状态,我们能够了解植物的生长状态,以及对异常情况作出及时的处理等;通过持续的数据采集和大量的数据分析,我们能够优化种植的策略,从而提高农产品的质量和产量。
基于这个目的,我们将会采集农业环境中的环境温湿度、光照度、土壤湿度、土壤酸碱度和土壤氮磷钾含量这几个最重要的参数,并且发送到云端服务器,云端服务器一方面记录这些数据以供后续的数据分析;另一方面发送到手机App,当这些参数出现异常状况时,手机App给用户推送提醒。
二、系统演示与架构设计
1.总体设计
本技术方案的架构设计如下图所示。
本技术方案主要由边缘计算终端、IoT云平台以、手机App和Web管理后台这几部分组成。
2..边缘计算终端
(1)边缘计算终端内置STM32嵌入式微处理器,具备一定的边缘计算能力,边缘计算终端的原型开发板如图所示。
为了方便前期快速开发和适应需求变化,本系统选用了现成的原型开发板进行开发,其中内置了诸如转串口芯片、拨码开关和排针等辅助器件,后期在成品产品电路中去除这些辅助器件即可,软件代码无需修改

(2)边缘计算终端搭载环境温湿度传感器、光照强度传感器(光敏电阻模块)、土壤湿度传感器、土壤PH值传感器和土壤氮磷钾传感器,能够全方位感知植物的生长环境状态。这些传感器支持可插拔,即可以随意安装自己所需的传感器,而不会影响系统正常工作。
(3)在产品规划阶段中,我们设计了两种供电方式组合,即A.内置锂电池+USB线二合一供电;B.内置锂电池+太阳能供电,如图所示。
然而,我们采取的策略是在确定硬件器件选型后,软件开发先行,然后硬件设计、外观设计跟上。基于现有的原型开发板以及确定相关元器件的成本后,这种策略是可行的。因此,在基于原型开发板阶段,暂时只需要支持Micro USB线缆+外置电池供电即可,在后续可在硬件层面支持上述的A版本或B版本的供电方式。
(4)边缘计算终端支持监测电池电量状态。
(5)边缘计算终端内置涂鸦智能NB-IoT模组,支持把各个传感器信息、电池电量信息以及主板本身的状态信息通过NB-IoT网络上传到涂鸦智能IoT云平台。
4.手机App
(1)手机App支持查看由边缘计算终端发送过来的实时数据,以环境温湿度数据为例,如图所示。
实时环境温湿度
(2)移动端App支持针对环境温湿度、环境光照强度、土壤湿度、土壤PH值、土壤碳磷钾含量设置上限和下限阈值,当实际值高于上限阈值或低于下限阈值的时候,能够发出警报信息。以温度的设置为例,如下演示视频所示。
设备间智能联合控制
5.云平台
(1)IoT平台支持接收来自边缘计算终端的数据并且保存下来,支持在手机App查看这些数据,支持在基于涂鸦智能的Web管理后台中各种数据行进管理。
历史温湿度数据查看
涂鸦智能Web管理后台
三、终端的主要硬件组成
- 主芯片:STM32F030F4P6
 - NB-IoT模组:涂鸦智能 NE1 https://developer.tuya.com/cn/docs/iot/ne1-module-datasheet?id=K9t001ddkmio2
 - NB-IoT移动网络卡:中国移动NB-IoT卡
 - 网络天线:善学坊NB-IoT超级天线 CrossAir L01
 - 环境温湿度传感器:http://aosong.com/products-104.html
 - 光敏电阻模块:https://zhuanlan.zhihu.com/p/483620112
 - 土壤湿度传感器:https://zhuanlan.zhihu.com/p/483599993
 - 土壤PH值传感器:https://www.kancloud.cn/aiot/solution/2628607
 土壤碳磷钾传感器:https://www.kancloud.cn/aiot/solution/2677011
四.主要技术参数
1.主控芯片技术参数
STM32F030采用ARM Cortex内核,运算速度高达48 MHz。另外,STM32F030具有全套外设,例如高速12位ADC、先进且灵活的定时器、日历RTC和通信接口。该组合轻松超越了现有的8位架构,让所有应用设计者均能得益于先进32位内核的简单性和高效率。STM32F030超值系列提供多种存储容量和引脚数组合,能与之匹敌的器件少之又少,从而进一步优化项目成本。
2.NB-IoT模组技术参数
NE1 是由涂鸦智能开发的一款低功耗嵌入式 NB-IoT 系列 LPWA 模组。支持 NB-IoT 无线电通信协议(3GPP Rel.14)。它由一个高集成度的 Soc EC616(内置了应用处理器、低功耗多波段窄带物联网收发器和电源管理单元PMU)和少量外围器件构成。NE1 内嵌低功耗 32 位Cortex-M3 CPU,支持 MPU,集成 272KB 晶圆内SRAM,4MB NOR Flash,还支持包括 UART、I2C、SPI、PWM、4 通道 12-bit AUXADC、32KHz RTC timer和 USIM 等接口。
特点内置低功耗32位 Cortex-M3 处理器
- 供电
- 工作电压范围:2.2~4.5V
 - 典型工作电压:3.3V
 
 - 外设:17×GPIOs,3×UARTs, 6×PWMs,1×ADC,1×SPI,1×I2C
 - SIM: 3V/1.8V SIM card
 - NB-IoT 网络
- Cat NB1/Cat NB2
 - 3GPP R14 NB-IoT 标准
 - B3/B5/B8
 - 最大发射功率 23dBm±2dB
 - 接收灵敏度 <-127.3dBm/15kHz(非重传)
 - 50Ω 特征阻抗,天线需第三方提供
 - 数据速率:
- R13:
- Single-tone:25.5kbps(下行),16.7kbps(上行)
 - Multi-tone:25.5kbps(下行),62.5kbps(上行)
 
 - R14:
- Multi-tone:102kbps(下行),157kbps(上行)
 
 
 - R13:
 - 网络协议特性:UDP/TCP/CoAP/LWM2M/ PPP/SSL/DTLS/FTP/ HTTP/MQTT/HTTPS*
 - 正常工作温度:-35°C ~ +75°C
 - 扩展工作温度:-40°C ~ +85°C
 - 存储温度:-40°C ~+90°C
 
 - 升级通过主串口,FOTA
 
3.中国移动NB-IoT卡类型
类型为cmnbiot,这是中国移动推出的支持终端控制PSM和eDRX的NB-IoT卡类型,详细介绍可参考https://ec.iot.10086.cn/onelink/pages/nbiot.html
3.NB-IoT超级天线 CrossAir L01
CrossAir L01是一款SMT自动焊接的微型天线,详细参数如图所示。
五、系统选型优势
1.NB-IoT模组对比
本方案中默认选取了涂鸦智能NE1模组,我们拿国内的另外的NB-IoT模组来对比一下。
价格对比
对于大多数的企业来说,元器件的价格是一个重要的参考因素,涂鸦智能NE1模组的价格仅为14元(含3元的云平台使用授权费),如图所示。(价格查询时间为2022年3月15日)
涂鸦智能NE1模组价格
而国内的其他模组零售价如图所示。据我们过往采购的经验来看,采购量在1000片以内时,价格比零售价便宜约1~3元,可见涂鸦智能的NE1几乎是全网最便宜的!(价格查询时间为2022年3月15日,查询链接:点击自动跳转淘宝搜索)

资源对比
涂鸦智能NE1模组的资源上文已经罗列过,此处我们给出在淘宝销量第1的模组的资源说明,如图所示。(图片来自其官网)
可见双方的资源和技术参数有一定差异,但是均能满足本技术方案的需求。
稳定性对比
稳定性是很重要的参考指标,但作为模块的用户,我们非常难去测试,因此大部分的情况下,我们只能从模块厂商的知名度、模块本身的出货量等方面去简介评估模块的稳定性。
从厂商的知名度来看,据涂鸦智能官网介绍,它是“全球IoT云平台上市第1股”(参考链接:https://www.tuya.com/cn/?_source=d441cd2712521cfcb4c151e9e58d4c8b),知名度可见一斑。
2.IoT云平台对比
涂鸦智能NE1模组能够直连涂鸦智能云平台,而其他模组一般需要对接第三方云平台。我们把涂鸦智能云平台与第3方云平台做一个简单的对比,见表。
| 项目 | 涂鸦智能云平台 | 主流第3方云平台 | 
|---|---|---|
| 资费 | 无(使用模组即可连接云平台) | 按通信数据量、连接时长或设备数量收费 | 
| 通信模组提供方 | 自营 | 第3方 | 
| 终端设备开发 | 0代码,支持自定义开发 | 支持二次开发 | 
| 手机App端开发 | 0代码,支持二次开发 | 支持二次开发 | 
| 微信小程序端开发 | 提供SDK供二次开发 | 支持二次开发 | 
| 云平台端开发 | 0代码,支持云云对接 | 支持二次开发 | 
总的来说,如果涂鸦智能的标准设备模型如果满足功能需要,那么从终端设备、手机App、云平台端的开发量将会非常少,非常适用于希望减少开发工作量和加快产品上市时间的团队。
六、云平台与手机App的实现
登录涂鸦智能官网https://www.tuya.com/,然后点击“登录IoT平台”,如图所示。
输入账号密码,如图所示。
选择产品,如图所示。
点击创建产品,如图所示。
依次选择传感、植物监测仪,如图所示。
选择产品开发,如图所示。
选择自定义方案,如图所示。
输入名称,并且选择NB-IoT、DRX,然后点击创建产品,如图所示。
选择红框中的功能点,然后点击确定,如图所示。
点击下一步设备交互,如图所示。
选择默认的Studio面板,如图所示。
点击下一步硬件开发,如图所示。
选择NE1模组,如图所示。
点击下一步产品配置,如图所示。
点击下一步测试服务,如图所示。
至此,云平台和App端的配置已经初步完成,读者可以初步测试一下App端的效果。点击设备交互,并且使用”智能生活“App扫描页面中的二维码,即可体验,如图所示。
七、设备终端的实现
7.1 涂鸦智能MCU SDK下载
点击硬件开发,如图所示。
下翻到页面底部,然后下载功能点调试文件、快速入门指南、MCU SDK等资料,如图所示。
解压其中的MCU SDK文件,得到如下内容。
把这个SDK添加进自有的工程中,这里以STM32F030F4P6 + Keil MDK工程为例,如图所示。
7.2 终端代码架构设计
7.2.1 MVC 架构简介
经典的MVC是一种常用的代码架构设计思想,其中M表示Model(模型),V表示View(视图),C表示控制器(Controller),相关含义如下:
- Model(模型):封装了数据和对数据的操作,是实际进行数据处理的地方
 - View(视图):负责程序和用户之间的交互,例如负责把数据在在屏幕上显示出来
 - Controller(控制器):用于操作模型和视图
 
7.2.2 SDK 设计模式
SDK可以分解成3个层次,自定向下分别是:
- HAL: HAL(Hardware Abstraction Layer,硬件抽象层),前面课程已经一步一步地带读者实现了部分HAL API。
 - Service:服务组件,对HAL进行服务化抽象和管理。HAL的重点是操作和管理某一个硬件,例如串口和显示器等。然而,Service的重点是为上层提供服务,例如Log组件为上层提供日志打印服务,这个组件既能通过串口写入日志数据,又能通过显示器上显示日志;又例如Sender组件为上层提供NB-IoT数据发送服务,上层无需理会使用哪个型号的NB-IoT模组去发送的,因此这个组件会自行去处理这些细节。
 - Task:是指某种更贴合用户需求的任务,例如定时地获取传感器的数值,并上报给指定的服务器。
 
7.2.3 终端代码详解
代码下载链接:https://pan.baidu.com/s/1uw5YxxaHSd8IqVTRMqTvkw 密码:d8io
完整的结构如图所示。
其中较为重要的的分别是HalPort、Users和Tuya。HalPort负责硬件驱动与抽象,Users负责处理终端的业务逻辑,而Tuya中存放的是Tuya MCU SDK。
其中的Tuya MCU SDK,我们主要需要修改的是protocol.c文件,修改后的代码如下:
/****************************************Copyright (c)*************************** 版权所有 (C), 2015-2020, 涂鸦科技**** http://www.tuya.com****--------------文件信息-------------------------------------------------------**文 件 名: protocol.c**描 述: 下发/上报数据处理函数**使 用 说 明 :*******非常重要,一定要看哦!!!********** 1、用户在此文件中实现数据下发/上报功能** 2、DP的ID/TYPE及数据处理函数都需要用户按照实际定义实现** 3、当开始某些宏定义后需要用户实现代码的函数内部有#err提示,完成函数后请删除该#err**-----------------------------------------------------------------------------******************************************************************************/#include "nbiot.h"/******************************************************************************移植须知:1:MCU必须在while中直接调用mcu_api.c内的nbiot_uart_service()函数2:程序正常初始化完成后,建议不进行关串口中断,如必须关中断,关中断时间必须短,关中断会引起串口数据包丢失3:请勿在中断/定时器中断内调用上报函数******************************************************************************//******************************************************************************第一步:初始化1:在需要使用到nbiot相关文件的文件中include "nbiot.h"2:在MCU初始化中调用mcu_api.c文件中的nbiot_protocol_init()函数3:将MCU串口单字节发送函数填入protocol.c文件中uart_transmit_output函数内,并删除#error4:在MCU串口接收函数中调用mcu_api.c文件内的uart_receive_input函数,并将接收到的字节作为参数传入5:单片机进入while循环后调用mcu_api.c文件内的nbiot_uart_service()函数******************************************************************************//******************************************************************************1:dp数据点序列类型对照表**此为自动生成代码,如在开发平台有相关修改请重新下载MCU_SDK********************************************************************************/const DOWNLOAD_CMD_S download_cmd[] ={{DPID_SOIL_HUMIDITY, DP_TYPE_VALUE},{DPID_SOIL_PH, DP_TYPE_VALUE},{DPID_AIR_HUMIDITY, DP_TYPE_VALUE},{DPID_AIR_TEMP, DP_TYPE_VALUE},{DPID_RAIN_INTENSITY, DP_TYPE_VALUE},{DPID_SUN_INTENSITY, DP_TYPE_VALUE},{DPID_LIQUID_TEMP, DP_TYPE_VALUE},{DPID_LIQUID_TURBIDITY, DP_TYPE_VALUE},};/******************************************************************************2:串口单字节发送函数请将MCU串口发送函数填入该函数内,并将接收到的数据作为参数传入串口发送函数******************************************************************************//*****************************************************************************函数名称 : uart_transmit_output功能描述 : 发数据处理输入参数 : value:串口收到字节数据返回参数 : 无使用说明 : 请将MCU串口发送函数填入该函数内,并将接收到的数据作为参数传入串口发送函数*****************************************************************************/void uart_transmit_output(unsigned char value){halUartWrite(&value, 1);// #error "请将MCU串口发送函数填入该函数,并删除该行"/*//示例:extern void Uart_PutChar(unsigned char value);Uart_PutChar(value); //串口发送函数*/}/******************************************************************************第二步:实现具体用户函数1:APP下发数据处理2:数据上报处理******************************************************************************//******************************************************************************1:所有数据上报处理当前函数处理全部数据上报(包括可下发/可上报和只上报)需要用户按照实际情况实现:1:需要实现可下发/可上报数据点上报2:需要实现只上报数据点上报此函数为MCU内部必须调用用户也可调用此函数实现全部数据上报******************************************************************************///自动化生成数据上报函数/*****************************************************************************函数名称 : all_data_update功能描述 : 系统所有dp点信息上传,实现APP和muc数据同步输入参数 : 无返回参数 : 无使用说明 : 此函数SDK内部需调用;MCU必须实现该函数内数据上报功能;包括只上报和可上报可下发型数据*****************************************************************************/void all_data_update(void){// #error "请在此处理可下发可上报数据及只上报数据示例,处理完成后删除该行"if(DHT20_Alive())// 如果DHT20传感器存在,则读取温湿度数据{DHT20_ReadHT();//读取AHT20的 20Bit原始数据StandardUnitCon();//实际标准单位转换mcu_dp_value_update(DPID_AIR_HUMIDITY,(unsigned long)DHT20_Humi()); //VALUE型数据上报;mcu_dp_value_update(DPID_AIR_TEMP,(unsigned long)DHT20_Temp()); //VALUE型数据上报;}//此代码为平台自动生成,请按照实际数据修改每个可下发可上报函数和只上报函数mcu_dp_value_update(DPID_SOIL_HUMIDITY,get_Soil()); //VALUE型数据上报;mcu_dp_value_update(DPID_SOIL_PH,get_PH());mcu_dp_value_update(DPID_RAIN_INTENSITY,get_Rain());mcu_dp_value_update(DPID_SUN_INTENSITY,get_Sun()); //VALUE型数据上报;mcu_dp_value_update(DPID_LIQUID_TURBIDITY,get_Turbidity()); //VALUE型数据上报;mcu_dp_value_update(DPID_LIQUID_TEMP,halDS18B20GetTemp()); //VALUE型数据上报;}/*****************************************************************************函数名称 : dp_record_combine_update功能描述 : 记录型数据组合上报输入参数 : time : 时间数据长度7,首字节表示是否传输标志位,其余依次为年、月、日、时、分、秒dp_bool : bool型dpid号, v_bool:对应值dp_enum : enum型dpid号, v_enum:对应值dp_value : value型dpid号, v_value:对应值dp_string: string型dpid号, v_string:对应值,len:string长度返回参数 : 无*****************************************************************************/unsigned char dp_record_combine_update(unsigned char time[],unsigned char dp_bool,unsigned char v_bool,unsigned char dp_enum,unsigned char v_enum,unsigned char dp_value,unsigned char v_value,unsigned char dp_string,unsigned char v_string[],unsigned char len){unsigned short length = 0;if(stop_update_flag == ENABLE)return SUCCESS;//local_timelength = set_nbiot_uart_buffer(length,(unsigned char *)time,7);//boollength = set_nbiot_uart_byte(length,dp_bool);length = set_nbiot_uart_byte(length,DP_TYPE_BOOL);length = set_nbiot_uart_byte(length,0);length = set_nbiot_uart_byte(length,1);if(v_bool == FALSE){length = set_nbiot_uart_byte(length,FALSE);}else{length = set_nbiot_uart_byte(length,1);}//enumlength = set_nbiot_uart_byte(length,dp_enum);length = set_nbiot_uart_byte(length,DP_TYPE_ENUM);length = set_nbiot_uart_byte(length,0);length = set_nbiot_uart_byte(length,1);length = set_nbiot_uart_byte(length,v_enum);//valuelength = set_nbiot_uart_byte(length,dp_value);length = set_nbiot_uart_byte(length,DP_TYPE_VALUE);length = set_nbiot_uart_byte(length,0);length = set_nbiot_uart_byte(length,4);length = set_nbiot_uart_byte(length,v_value >> 24);length = set_nbiot_uart_byte(length,v_value >> 16);length = set_nbiot_uart_byte(length,v_value >> 8);length = set_nbiot_uart_byte(length,v_value & 0xff);//stringlength = set_nbiot_uart_byte(length,dp_string);length = set_nbiot_uart_byte(length,DP_TYPE_STRING);length = set_nbiot_uart_byte(length,len / 0x100);length = set_nbiot_uart_byte(length,len % 0x100);length = set_nbiot_uart_buffer(length,(unsigned char *)v_string,len);nbiot_uart_write_frame(STATE_RC_UPLOAD_CMD,length);return SUCCESS;}/******************************************************************************WARNING!!!2:所有数据上报处理自动化代码模板函数,具体请用户自行实现数据处理******************************************************************************//******************************************************************************WARNING!!!此代码为SDK内部调用,请按照实际dp数据实现函数内部数据******************************************************************************/#ifdef SUPPORT_MCU_RTC_CHECK/*****************************************************************************函数名称 : mcu_write_rtctime功能描述 : MCU校对本地RTC时钟输入参数 : 无返回参数 : 无使用说明 : MCU需要自行实现该功能*****************************************************************************/void mcu_write_rtctime(unsigned char time[]){#error "请自行完成RTC时钟写入代码,并删除该行"/*time[0]为是否获取时间成功标志,为 0 表示失败,为 1表示成功time[1] 为 年 份 , 0x00 表 示2000 年time[2]为月份,从 1 开始到12 结束time[3]为日期,从 1 开始到31 结束time[4]为时钟,从 0 开始到23 结束time[5]为分钟,从 0 开始到59 结束time[6]为秒钟,从 0 开始到59 结束time[7]为星期,从 1 开始到 7 结束,1代表星期一*/if(time[0] == 1){//正确接收到模块返回的本地时钟数据}else{//获取本地时钟数据出错,有可能是当前模块未联网}}#endif/*****************************************************************************函数名称 : nbiot_update_handle功能描述 : MCU请求mcu固件升级返回函数输入参数 : status:校验标志返回参数 : 无使用说明 : MCU主动调用 nbiot_update_request 函数完成后该函数内可获取升级当前状态*****************************************************************************/void nbiot_update_handle(unsigned char status){// #error "请自行完成模块升级状态返回代码,并删除该行"switch (status){case 0:{//开始检查固件更新break;}case 1:{//已经是最新固件break;}case 2:{//正在更新固件break;}case 3:{//固件更新成功break;}case 4:{//固件更新失败break;}default:break;}}#ifdef SUPPORT_MCU_FIRM_UPDATE/*****************************************************************************函数名称 : mcu_firm_update_handle功能描述 : MCU进入固件升级模式输入参数 : value:固件缓冲区position:当前数据包在于固件位置length:当前固件包长度(固件包长度为0时,表示固件包发送完成)返回参数 : 无使用说明 : MCU需要自行实现该功能*****************************************************************************/unsigned char mcu_firm_update_handle(const unsigned char value[],unsigned long position,unsigned short length){// #error "请自行完成MCU固件升级代码,完成后请删除该行"if(length == 0){//固件数据发送完成//#error "请完成crc32校验,结果返回0或者1,完成后请删除该行"//mcu_firm_update_data_ack(1, 0); //请根据crc32校验情况,去回复crc成功或者失败}else{//mcu_firm_update_data_ack(0, 0);//固件数据处理}return SUCCESS;}/*****************************************************************************函数名称 : mcu_file_update_handle功能描述 : MCU文件下载数据处理输入参数 : value:固件缓冲区position:当前数据包在于固件位置length:当前固件包长度(固件包长度为0时,表示固件包发送完成)返回参数 : 无使用说明 : MCU需要自行实现该功能*****************************************************************************/unsigned char mcu_file_update_handle(const unsigned char value[],unsigned long position,unsigned short length){//#error "请自行完成MCU文件下载数据处理,完成后请删除该行"if(length == 0){//文件数据接收完成// #error "请完成crc32校验,crc32_result结果返回0或者1,完成后请删除该行"//mcu_file_data_ack(1, 0); //请根据crc32校验情况,去回复crc成功或者失败}else{//mcu_file_data_ack(0, 0);//固件数据处理}return SUCCESS;}#endif#ifdef SUPPORT_NBIOT_DONGLE_SERVICE/*****************************************************************************函数名称 : get_nb_active_info_response功能描述 : 复合产品下 NB返回的激活所需的设备信息输入参数 : NB返回的激活信息返回参数 : 无使用说明 : MCU需要自行实现该功能*****************************************************************************/void get_nb_active_info_response(unsigned char nb_active_info[], unsigned short active_info_len){//nb_active_info[0]为是否获取激活信息成功标志,为 0 表示失败,为 1表示成功//nb_active_info[1] - nb_active_info[active_info_len-1] 为数据内容//{"pv":"2.0","bv":"3.0","sv":"1.0.0","i":"860102040125729","opt":0,"h":28800}if(nb_active_info[0] == 1){//返回激活信息成功 后续可进行NB的激活 并调用mcu_set_nb_active_response 回复给NB}else{//返回激活信息成失败}}/*****************************************************************************函数名称 : get_mcu_active_response功能描述 : 复合产品下 NB返回的 为MCU激活的结果输入参数 : NB返回的激活信息返回参数 : 无使用说明 : MCU需要自行实现该功能*****************************************************************************/void get_mcu_active_response(unsigned char mcu_active_ack[], unsigned short active_ack_len){//mcu_active_info[0]为是否获取激活信息成功标志,为 0 表示失败,为 1表示成功//mcu_active_info[1] - mcu_active_info[active_info_len-1] 为数据内容//例如:{"localkey":"12345678"}if(mcu_active_ack[0] == 1){//获取MCU激活信息成功}else{//获取MCU激活信息失败}}#endif/******************************************************************************WARNING!!!以下函数用户请勿修改!!******************************************************************************//*****************************************************************************函数名称 : dp_download_handle功能描述 : dp下发处理函数输入参数 : dpid:DP序号value:dp数据缓冲区地址length:dp数据长度返回参数 : 成功返回:SUCCESS/失败返回:ERRO使用说明 : 该函数用户不能修改*****************************************************************************/unsigned char dp_download_handle(unsigned char dpid,const unsigned char value[], unsigned short length){/*********************************当前函数处理可下发/可上报数据调用具体函数内需要实现下发数据处理完成用需要将处理结果反馈至APP端,否则APP会认为下发失败***********************************/unsigned char ret;switch(dpid){default:break;}return ret;}/*****************************************************************************函数名称 : get_download_cmd_total功能描述 : 获取所有dp命令总和输入参数 : 无返回参数 : 下发命令总和使用说明 : 该函数用户不能修改*****************************************************************************/unsigned char get_download_cmd_total(void){return(sizeof(download_cmd) / sizeof(download_cmd[0]));}
补充一句
如果你也想尝试使用涂鸦云平台开发物联网项目,可联系他们的工作人员进行咨询,工作人员个人号:qtbb121
