涂鸦智能 ① tuya-wifi-mcu-sdk-arduino-library 简单剖析
Posted 单片机菜鸟哥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了涂鸦智能 ① tuya-wifi-mcu-sdk-arduino-library 简单剖析相关的知识,希望对你有一定的参考价值。
tuya-wifi-mcu-sdk-arduino-library
- 1、简介
- 2、配置Arduino环境
- 3、剖析SDK
- 3.1 TuyaUart —— 处理和模组进行串口通信(了解即可)
- 3.2 TuyaTools —— 工具类方法(了解即可)
- 3.3 TuyaDataPoint —— 处理数据节点(上传、下发)
- 3.4 TuyaWifi —— 处理wifi网络相关操作,重点内容
- 3.4.1 unsigned char TuyaWifi::init(unsigned char *pid, unsigned char *mcu_ver) —— 初始化
- 3.4.2 void set_dp_cmd_total(unsigned char download_cmd_array[][2], unsigned char download_cmd_num) —— 配置节点
- 3.4.3 void mcu_set_wifi_mode(unsigned char mode) —— 配网模式
- 3.4.4 void dp_process_func_register(tuya_callback_dp_download _func) —— 下发回调注册
- 3.4.5 mcu_dp_update —— 真正上报设备状态
- 3.4.6 dp_update_all_func_register —— 上报设备状态函数注册
- 3.4.7 mcu_get_wifi_work_state —— 获取wifi连接状态
- 3.4.8 void TuyaWifi::uart_service(void) —— 轮询串口数据
- 4、官方案例
1、简介
Tuya MCU SDK Arduino Library 基于涂鸦Wi-Fi 通用对接方案进行开发的,设备 MCU 通过串口与 Wi-Fi 模组连接实现设备联网。涂鸦模组中的固件应为通用固件,通用固件支持9600,115200
两种波特率自适应。
注意点:
Arduino板子 + 涂鸦模块
的开发方式,据说后期可以单独模块开发。- 串口通信
2、配置Arduino环境
2.1 下载Arduino sdk
- 方式一:
https://gitee.com/ant_onio/tuya-wifi-mcu-sdk-arduino-library 点击下载
解压到自己的电脑路径(此电脑->文档->Arduino->libraries)
- 方式二(推荐):
Arduino IDE -> 工具 -> 管理库 -> 搜索 tuya-> 安装最新版本
3、剖析SDK
记住一点,这种方式是mcu + module
串口通信开发方式
简单来说,肯定数据是
不断处理串口通信
,那么从另外一个点来说就是模组已经内置了串口协议数据处理逻辑。
博哥大概代码看了一下:
3.1 TuyaUart —— 处理和模组进行串口通信(了解即可)
class TuyaUart
{
public:
// 主要是定义串口通信buffer缓存大小
volatile unsigned char wifi_uart_rx_buf[PROTOCOL_HEAD + WIFI_UART_RECV_BUF_LMT]; //Serial data processing buffer
volatile unsigned char wifi_uart_tx_buf[PROTOCOL_HEAD + WIFIR_UART_SEND_BUF_LMT]; //Serial receive buffer
volatile unsigned char wifi_data_process_buf[PROTOCOL_HEAD + WIFI_DATA_PROCESS_LMT]; //Serial port send buffer
TuyaUart(void);
~TuyaUart(void);
void wifi_protocol_init(void);
// 接收数据
unsigned char uart_receive_input(unsigned char data);
void uart_receive_buff_input(unsigned char value[], unsigned short data_len);
unsigned char take_byte_rxbuff(void);
unsigned char with_data_rxbuff(void);
// 传输发送数据
void uart_transmit_output(unsigned char value);
void wifi_uart_write_data(unsigned char *in, unsigned short len);
void wifi_uart_write_frame(unsigned char fr_type, unsigned char fr_ver, unsigned short len);
unsigned short set_wifi_uart_byte(unsigned short dest, unsigned char byte);
unsigned short set_wifi_uart_buffer(unsigned short dest, const unsigned char *src, unsigned short len);
/* serial set */
bool _isHWSerial;
// 串口设置
void set_serial(HardwareSerial *serial);
void set_serial(SoftwareSerial *serial);
void begin(long baud_rate);
char read(void);
size_t write(char value);
int available(void);
private:
volatile unsigned char *rx_buf_in;
volatile unsigned char *rx_buf_out;
Stream *_port;
};
3.2 TuyaTools —— 工具类方法(了解即可)
class TuyaTools
{
public:
TuyaTools(void);
~TuyaTools(void);
unsigned char hex_to_bcd(unsigned char Value_H, unsigned char Value_L);
// 计算字符串长度
unsigned long my_strlen(unsigned char *str);
// 设置字符串
void *my_memset(void *src, unsigned char ch, unsigned short count);
// 内存拷贝
void *my_memcpy(void *dest, const void *src, unsigned short count);
// 字符串拷贝
char *my_strcpy(char *dest, const char *src);
// 字符串对比
int my_strcmp(char *s1, char *s2);
// int 转字节数组
void int_to_byte(unsigned long number, unsigned char value[4]);
// 字节数组 转int
unsigned long byte_to_int(const unsigned char value[4]);
unsigned char get_check_sum(unsigned char *pack, unsigned short pack_len);
private:
};
3.3 TuyaDataPoint —— 处理数据节点(上传、下发)
class TuyaDataPoint
{
public:
// TuyaDataPoint(void);
// ~TuyaDataPoint(void);
// 下发节点数据
unsigned char mcu_get_dp_download_bool(const unsigned char value[], unsigned short len);
unsigned char mcu_get_dp_download_enum(const unsigned char value[], unsigned short len);
unsigned long mcu_get_dp_download_value(const unsigned char value[], unsigned short len);
// 上报节点数据
unsigned char mcu_dp_raw_update(unsigned char dpid, const unsigned char value[], unsigned short len);
unsigned char mcu_dp_bool_update(unsigned char dpid, unsigned char value);
unsigned char mcu_dp_value_update(unsigned char dpid, unsigned long value);
unsigned char mcu_dp_string_update(unsigned char dpid, const unsigned char value[], unsigned short len);
unsigned char mcu_dp_enum_update(unsigned char dpid, unsigned char value);
unsigned char mcu_dp_fault_update(unsigned char dpid, unsigned long value);
private:
};
注意区分一下数据类型。
DP为 Data Point 的缩写,即数据点,偶尔被称为 DP 点,表示智能设备所具备的功能点。
- 涂鸦智能将每个功能点抽象成数据点,数据点定义成不同的类型,例如布尔、枚举、数值等。
- 数据点具备读写属性。例如,一个两路的开关,可以抽象成两个数据点,每个数据点类型为布尔型,可取值为
True
或False
。 - 数据点可读写,读表示获取开关目前的值,写表示改变开关目前的值。
DPID:指定通信协议下 DP 事件的 ID。
节点类型:
#define DP_TYPE_RAW 0x00 //RAW type
#define DP_TYPE_BOOL 0x01 //bool type
#define DP_TYPE_VALUE 0x02 //value type
#define DP_TYPE_STRING 0x03 //string type
#define DP_TYPE_ENUM 0x04 //enum type
#define DP_TYPE_BITMAP 0x05 //fault type
3.4 TuyaWifi —— 处理wifi网络相关操作,重点内容
在Arduino中使用该库进行编程开发时,必须在你的Arduino工程文件中包含 TuyaWifi.h 头文件。
一般很多sdk的开发方式都是:
- 1、创建对象 构造方法
- 2、初始化 init
- 3、回调配置、信息注册 register、callbackHandler
- 4、不断轮询处理响应
3.4.1 unsigned char TuyaWifi::init(unsigned char *pid, unsigned char *mcu_ver) —— 初始化
PID通过在 Tuya IoT平台 上创建产品获取,wifi类的长度一般为16,mcu_ver 这个参数是软件的版本号。
3.4.2 void set_dp_cmd_total(unsigned char download_cmd_array[][2], unsigned char download_cmd_num) —— 配置节点
在Tuya IoT平台创建产品,获取产品DP点信息。
DP为 Data Point 的缩写,即数据点,偶尔被称为 DP 点,表示智能设备所具备的功能点。
- 涂鸦智能将每个功能点抽象成数据点,数据点定义成不同的类型,例如布尔、枚举、数值等。
- 数据点具备读写属性。例如,一个两路的开关,可以抽象成两个数据点,每个数据点类型为布尔型,可取值为
True
或False
。 - 数据点可读写,读表示获取开关目前的值,写表示改变开关目前的值。
DPID:指定通信协议下 DP 事件的 ID。
MCU SDK需要知道你创建了哪些DP点,他们是什么类型的。
3.4.3 void mcu_set_wifi_mode(unsigned char mode) —— 配网模式
/**
* @description: MCU set wifi working mode
* @param {unsigned char} mode : enter mode
* 0(SMART_CONFIG):enter smartconfig mode
* 1(AP_CONFIG):enter AP mode
* @return {*}
*/
void TuyaWifi::mcu_set_wifi_mode(unsigned char mode);
3.4.4 void dp_process_func_register(tuya_callback_dp_download _func) —— 下发回调注册
当APP控制设备的时候,会从云端下发对应的DP命令到设备,设备对数据进行解析后,对下发的命令执行相对于的动作。
对下发命令的处理,通过回调函数来调用,所以我们需要把你的处理函数注册一下。
伪代码:
//register DP download processing callback function
my_device.dp_process_func_register(dp_process);
/**
* @description: DP download callback function.
* @param {unsigned char} dpid
* @param {const unsigned char} value
* @param {unsigned short} length
* @return {unsigned char}
*/
unsigned char dp_process(unsigned char dpid, const unsigned char value[], unsigned short length)
{
switch (dpid) {
case DPID_BOOL:
DebugSerial.println("Bool type:");
dp_bool_value = my_device.mcu_get_dp_download_data(dpid, value, length);
DebugSerial.println(dp_bool_value);
/* After processing the download DP command, the current status should be reported. */
my_device.mcu_dp_update(DPID_BOOL, dp_bool_value, 1);
break;
case DPID_VALUE:
DebugSerial.println("Value type:");
dp_value_value = my_device.mcu_get_dp_download_data(DPID_VALUE, value, length);
DebugSerial.println(dp_value_value);
/* After processing the download DP command, the current status should be reported. */
my_device.mcu_dp_update(DPID_VALUE, dp_value_value, 1);
break;
case DPID_ENUM:
DebugSerial.println("Enum type:");
dp_enum_value = my_device.mcu_get_dp_download_data(dpid, value, length);
DebugSerial.println(dp_enum_value);
/* After processing the download DP command, the current status should be reported. */
my_device.mcu_dp_update(DPID_ENUM, dp_enum_value, 1);
break;
case DPID_STRING:
DebugSerial.println("String type:");
/* */
for (unsigned int i=0; i<length; i++) {
dp_string_value[i] = value[i];
DebugSerial.write(dp_string_value[i]);
}
DebugSerial.println("");
/* After processing the download DP command, the current status should be reported. */
my_device.mcu_dp_update(DPID_STRING, dp_string_value, length);
break;
case DPID_RAW:
DebugSerial.println("Raw type:");
/* */
for (unsigned int i=0; i<length; i++) {
dp_raw_value[i] = value[i];
DebugSerial.write(dp_raw_value[i]);
}
DebugSerial.println("");
/* After processing the download DP command, the current status should be reported. */
my_device.mcu_dp_update(DPID_RAW, dp_raw_value, length);
break;
default:
break;
}
return SUCCESS;
}
这里得注意一个方法:
mcu_get_dp_download_data (`下发DP数据处理`)
对字节数组进行数据解析。
3.4.5 mcu_dp_update —— 真正上报设备状态
/* char * */
unsigned char mcu_dp_update(unsigned char dpid, const unsigned char value[], unsigned short len); /* char raw */
/* unsigned long / long */
unsigned char mcu_dp_update(unsigned char dpid, unsigned long value, unsigned short len);
unsigned char mcu_dp_update(unsigned char dpid, long value, unsigned short len);
/* unsigned char / char */
unsigned char mcu_dp_update(unsigned char dpid, unsigned char value, unsigned short len);
unsigned char mcu_dp_update(unsigned char dpid, char value, unsigned short len);
/* unsigned int / int */
unsigned char mcu_dp_update(unsigned char dpid, unsigned int value, unsigned short len);
unsigned char mcu_dp_update(unsigned char dpid, int value, unsigned short len);
基本上大同小异。注意一下dpid和数据类型即可。
3.4.6 dp_update_all_func_register —— 上报设备状态函数注册
#include <TuyaWifi.h>
TuyaWifi my_device;
#define DPID_SWITCH 20
//Record the current status of the led
unsigned char switch_value = 0;
...
void setup()
{
...
//register DP download processing callback function
my_device.dp_update_all_func_register(dp_update_all);
...
}
/**
* @description: Upload all DP status of the current device.
* @param {*}
* @return {*}
*/
void dp_update_all(void)
{
my_device.mcu_dp_update(DPID_SWITCH, switch_v
3.4.7 mcu_get_wifi_work_state —— 获取wifi连接状态
3.4.8 void TuyaWifi::uart_service(void) —— 轮询串口数据
/**
* @description: Wifi serial port processing service
* @param {*}
* @return {*}
*/
void TuyaWifi::uart_service(void)
在arduino loop中调用。不断检测串口数据。
4、官方案例
/*
* @FileName: DataPointType.ino
* @Author: Tuya
* @Email:
* @LastEditors: Tuya
* @Date: 2021-04-19 14:31:52
* @LastEditTime: 2021-04-28 19:47:36
* @Copyright: HANGZHOU TUYA INFORMATION TECHNOLOGY CO.,LTD
* @Company: http://www.tuya.com
* @Description:
* @Github:https://github.com/tuya/tuya-wifi-mcu-sdk-arduino-library
*/
#include <TuyaWifi.h>
#include <SoftwareSerial.h>
TuyaWifi my_device;
SoftwareSerial DebugSerial(8,9);
/* Current LED status */
unsigned char led_state = 0;
/* Connect network button pin */
int wifi_key_pin = 7;
/* Data point define */
#define DPID_BOOL 101
#define DPID_VALUE 102
#define DPID_ENUM 103
#define DPID_STRING 104
#define DPID_RAW 105
#define DPID_FAULT 106
/* Current device DP values */
unsigned char dp_bool_value = 0;
long dp_value_value = 0;
unsigned char dp_enum_value = 0;
unsigned char dp_string_value[8] = {"Hi,Tuya"};
unsigned char dp_raw_value[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
int dp_fault_value = 0x01;
/* Stores all DPs and their types. PS: array[][0]:dpid, array[][1]:dp type.
* dp type(TuyaDefs.h) : DP_TYPE_RAW, DP_TYPE_BOOL, DP_TYPE_VALUE, DP_TYPE_STRING, DP_TYPE_ENUM, DP_TYPE_BITMAP
*/
unsigned char dp_array[][2] = {
{DPID_BOOL, DP_TYPE_BOOL},
{DPID_VALUE, DP_TYPE_VALUE},
{DPID_ENUM, DP_TYPE_ENUM},
{DPID_STRING, DP_TYPE_STRING},
{DPID_RAW, DP_TYPE_RAW},
{DPID_FAULT, DP_TYPE_BITMAP},
};
unsigned char pid[] = {"xxxxxxxxxxx"}; // 填上自己的产品ID
unsigned char mcu_ver[] = {"1.0.0"};
/* last time */
unsigned long last_time = 0;
void setup()
{
Serial.begin(9600);
DebugSerial.begin(9600);
//Initialize led port, turn off led.
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
//Initialize networking keys.
pinMode(wifi_key_pin, INPUT_PULLUP);
// 三部曲 —— 初始化、配置、注册回调
//Enter the PID and MCU software version
my_device.init(pid, mcu_ver);
//incoming all DPs and their types array, DP numbers
my_device.set_dp_cmd_total(dp_array, 6);
//register DP download processing callback function
my_device.dp_process_func_register(dp_process);
//register upload all DP callback function
my_device.dp_update_all_func_register(dp_update_all);
last_time = millis();
}
void loop()
{
// 不断轮询
my_device.uart_service();
//Enter the connection network mode when Pin7 is pressed.
if (digitalRead(wifi_key_pin) == LOW) {
delay(80);
if (digitalRead(wifi_key_pin) == LOW) {
my_device.mcu_set_wifi_mode(SMART_CONFIG);
}
}
/* LED blinks when network is being connected */
if ((my_device.mcu_get_wifi_work_state() != WIFI_LOW_POWER) && (my_device.mcu_get_wifi_work_state() != WIFI_CONN_CLOUD) && (my_device.mcu_get_wifi_work_state() != WIFI_SATE_UNKNOW)) {
if (millis() - last_time >= 500) {
last_time = millis();
/* Toggle current LED status */
if (led_state == LOW) {
以上是关于涂鸦智能 ① tuya-wifi-mcu-sdk-arduino-library 简单剖析的主要内容,如果未能解决你的问题,请参考以下文章