diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..2edb906 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +*.d \ No newline at end of file diff --git a/README.md b/README.md new file mode 100755 index 0000000..0b676f0 --- /dev/null +++ b/README.md @@ -0,0 +1,279 @@ +# Tuya MCU SDK Arduino Library + +[English](./README.md) | [中文](./README_zh.md) + +Tuya MCU SDK Arduino Library is developed based on the Tuya Wi-Fi general integration solution. The device's MCU is connected to a Wi-Fi module through a serial port to implement a network connection. **The development is based on general firmware, which supports the adaptative 9600 and115200 baud rate. Please read this document carefully before development.** + +
+ +
+ + + +## Document introduction + +```bash +├── config.h // Configuration file. Add and define features in the MCU SDK with macros. +├── examples // The folder to save routines. +├── keywords.txt +├── library.properties +├── README.md +└── src // The folder to save Tuya MCU SDK Arduino Library. + ├── TuyaWifi.cpp // The APIs for users. + ├── TuyaDataPoint.cpp // The class of DP operations. + ├── TuyaDataPoint.h + ├── TuyaDefs.h // Some constants. + ├── TuyaWifi.h + ├── TuyaTools.cpp // Tools used by the MCU SDK. + ├── TuyaTools.h + ├── TuyaUart.cpp // Functions for serial communications and data buffer. + └── TuyaUart.h +``` + + + +## Important functions + +When you use this library for development with Arduino, you must add the header file `TuyaWifi.h` in your Arduino project. + +### 1. Initialization + +Every product that is created on the Tuya IoT Platform will have a unique product ID (PID). The PID is associated with all information related to this product, including specific DP, app control panel, and delivery information. + +In `unsigned char TuyaWifi::init(unsigned char *pid, unsigned char *mcu_ver)`, the PID is obtained after you create a product on the [Tuya IoT Platform](https://iot.tuya.com/?_source=97c44038fafc20e9c8dd5fdb508cc9c2). The PID of a Wi-Fi product is typically 16 bytes. The `mcu_ver` parameter is the version number of the software. Pay attention to this parameter if you want to support OTA updates of the MCU. +> **Note**: The current version of the library does not support the OTA feature. + +```c +#include + +TuyaWifi my_device; +... +void setup() +{ + Serial.begin(9600); + ... + my_device.init("xxxxxxxxxxxxxxxx", "1.0.0");// "xxxxxxxxxxxxxxxx": the PID on the Tuya IoT Platform. "1.0.0" is the default value. You can change "1.0.0" to the actual version number of the current software. + + ... +} + +void loop() +{ + ... + my_device.uart_service(); + ... +} +... +``` + + + +### 2. Pass in the DP information to the MCU SDK + +Create products on the [Tuya IoT Platform](https://iot.tuya.com/?_source=97c44038fafc20e9c8dd5fdb508cc9c2) and get information on product DP points. + +A data point (DP) represents a smart device function. + ++ Tuya abstracts each function into a data point. DPs are defined in different data types, such as Boolean, enumeration, and integer. ++ DPs have read and write attributes. For example, a 2-gang switch has two Boolean DPs, and each DP has either a `True` or `False` value, which is readable and writable. ++ To read means to get the current value of the switch, and to write means to change the current value of the switch. + +DPID: specifies the ID of a DP event under a communication protocol. + + +The MCU SDK needs to know which DPs you have created and what type they are. Pass them to the MCU SDK through the `void TuyaWifi::set_dp_cmd_total(unsigned char dp_cmd_array[][2], unsigned char dp_cmd_num)` function. +The Tuya IoT Platform has six types of DPs: + +```c +#define DP_TYPE_RAW 0x00 // Raw type +#define DP_TYPE_BOOL 0x01 // Boolean type +#define DP_TYPE_VALUE 0x02 // Numeric type +#define DP_TYPE_STRING 0x03 // String type +#define DP_TYPE_ENUM 0x04 // Enum type +#define DP_TYPE_BITMAP 0x05 // Fault type +``` + +In the `void TuyaWifi::set_dp_cmd_total(unsigned char dp_cmd_array[][2], unsigned char dp_cmd_num)` function, `dp_cmd_array[][2]` is the array that stores DP information, and `dp_cmd_num` is the total number of DPs. + + + +Assume that a light has three functions, corresponding to three DPs as below: +* Switch (DP ID: 20, DP type: Boolean type). +* Brightness (DP ID: 21, DP type: numeric type). +* Light mode (DP ID: 22, DP type: enum type). + +```c +#include + +TuyaWifi my_device; +... +#define DPID_SWITCH 20 // The switch DP of the light. +#define DPID_LIGHT 21 // The brightness DP of the light. +#define DPID_MODE 22 // The working mode DP of the light. + +// Note: array[][0] is DP ID, and array[][1] is DP type. +unsigned char dp_id_array[][2] = { + /* DPID | DP type */ + {DPID_SWITCH, DP_TYPE_BOOL}, + {DPID_LIGHT, DP_TYPE_VALUE}, + {DPID_MODE, DP_TYPE_ENUM}, +}; +... +void setup() +{ + ... + my_device.set_dp_cmd_total(dp_id_array, 3); + ... +} +``` + + + +### 3. Pairing mode setting + +Call `void TuyaWifi::mcu_set_wifi_mode(unsigned char mode)` to enter the pairing mode. + +```c +/** + * @description: The MCU sets Wi-Fi working mode + * @param {unsigned char} mode: Enter the specified mode + * 0(SMART_CONFIG): Enter SmartConfig (Wi-Fi Easy Connect) mode + * 1(AP_CONFIG): Enter AP mode + * @return {*} + */ +void TuyaWifi::mcu_set_wifi_mode(unsigned char mode); +``` + + + + + +### 4. Send and process DP data + +After the cloud sends data, the sent data must be parsed through the `unsigned char TuyaWifi::mcu_get_dp_download_data(unsigned char dpid, const unsigned char value[], unsigned short len)` function. +Currently, this function only supports three types: `DP_TYPE_BOOL`, `DP_TYPE_VALUE`, and `DP_TYPE_ENUM`. `DP_TYPE_BITMAP` refers to the data of fault type, in which the data is only reported to the cloud. You do not need to handle this type. `DP_TYPE_RAW` and `DP_TYPE_STRING` must be implemented yourself. + +```c +/** + * @description: The MCU gets Boolean, numeric, and enum types to send DP value. (The data of the raw and string types shall be handled at the user's discretion. The data of the fault type can only be reported.) + * @param {unsigned char} dpid: Data point (DP) ID + * @param {const unsigned char} value: DP data buffer address + * @param {unsigned short} len: Data length + * @return {unsigned char} Parsed data + */ +unsigned char TuyaWifi::mcu_get_dp_download_data(unsigned char dpid, const unsigned char value[], unsigned short len); +``` + + + +### 5. Register a function to process DP sending + +The app sends DP control commands to the device through the cloud. After data parsing, the device executes the specified actions accordingly. + +A callback function is required to process the sent commands, so a processing function must be registered. We can call `void TuyaWifi::dp_process_func_register(tuya_callback_dp_download _func)` to register the callback function. + +```c +#include + +TuyaWifi my_device; +... + +void setup() +{ + ... + // 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_SWITCH: + switch_value = my_device.mcu_get_dp_download_data(dpid, value, length); + if (switch_value) { + // Turn on + + } else { + // Turn off + + } + // Status changes must be reported. + my_device.mcu_dp_update(dpid, value, length); + break; + + default:break; + } + return SUCCESS; +} +``` + + + +### 6. Report device status + +Reporting the device status is to report the values of all DPs. It is also implemented through function registration. + +Six data types of DPs are defined as follows: + +DP reporting function: + +```c +/** + * @description: DP data upload + * @param {unsigned char} dpid + * @param {const unsigned char} value + * @param {unsigned short} length + * @return {*} + */ +unsigned char mcu_dp_update(unsigned char dpid, const unsigned char value[], unsigned short len);//update raw, string type +unsigned char mcu_dp_update(unsigned char dpid, unsigned long value, unsigned short len); +unsigned char mcu_dp_update(unsigned char dpid, unsigned int value, unsigned short len); +``` + + +Example of registering a device status reporting function + +```c +#include + +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_value, 1); +} +``` + +## Technical Support + +You can get support for Tuya by using the following methods: + +- Developer Centre: https://developer.tuya.com +- Help Centre: https://support.tuya.com/help +- Technical Support Work Order Centre: https://service.console.tuya.com + diff --git a/README_zh.md b/README_zh.md new file mode 100755 index 0000000..869491b --- /dev/null +++ b/README_zh.md @@ -0,0 +1,287 @@ +# Tuya MCU SDK Arduino Library + +[English](./README.md) | [中文](./README_zh.md) + +Tuya MCU SDK Arduino Library 基于涂鸦Wi-Fi 通用对接方案进行开发的,设备 MCU 通过串口与 Wi-Fi 模组连接实现设备联网。**涂鸦模组中的固件应为通用固件,通用固件支持9600,115200两种波特率自适应。开发前请仔细阅读该文档。** + +
+ +
+ + + +## 文件介绍 + +```bash +├── config.h //配置文件,通过一些宏对mcu sdk内的功能进行添加和裁剪 +├── examples //例程存放文件夹(DataPointType例程对于涂鸦的数据类型进行了示例,具有较强的参考价值) +├── keywords.txt +├── library.properties +├── README.md +└── src //Tuya mcu sdk Arduino Library 存放文件夹 + ├── TuyaWifi.cpp //用户会使用到的API接口 + ├── TuyaDataPoint.cpp //对DP点相关操作的类 + ├── TuyaDataPoint.h + ├── TuyaDefs.h //会用到的,用户不需改动的一些常量 + ├── TuyaWifi.h + ├── TuyaTools.cpp //MCU SDK会使用到的一些工具 + ├── TuyaTools.h + ├── TuyaUart.cpp //对串口和数据缓存区处理的一些函数 + └── TuyaUart.h +``` + + + +## 重要函数 + +在Arduino中使用该库进行编程开发时,必须在你的Arduino工程文件中包含 `TuyaWifi.h` 头文件。 + + + +### 1、相关信息初始化 + +在使用Tuya IoT 云平台的时候,Product ID(简称:PID) 关联了产品具体的功能点、App 控制面板、出货信息等所有跟这个产品相关的信息。 + +`unsigned char TuyaWifi::init(unsigned char *pid, unsigned char *mcu_ver)` ,PID通过在 [Tuya IoT平台](https://iot.tuya.com/?_source=97c44038fafc20e9c8dd5fdb508cc9c2) 上创建产品获取,wifi类的长度一般为16,`mcu_ver` 这个参数是软件的版本号,如果你的mcu想要支持OTA的话,该信息也是非常重要的。 + +> **提示**:当前版本的library暂不支持OTA功能。 + +```c +#include + +TuyaWifi my_device; +... +void setup() +{ + Serial.begin(9600); + ... + my_device.init("xxxxxxxxxxxxxxxx", "1.0.0");//"xxxxxxxxxxxxxxxx":应为你在Tuya IoT 平台上获取的的PID,"1.0.0"应是当前软件的实际版本号 + + ... +} + +void loop() +{ + ... + my_device.uart_service(); + ... +} + +... +``` + + + +### 2、DP信息传入MCU SDK + +在[Tuya IoT平台](https://iot.tuya.com/?_source=97c44038fafc20e9c8dd5fdb508cc9c2)创建产品,获取产品DP点信息。 + +DP为 Data Point 的缩写,即数据点,偶尔被称为 DP 点,表示智能设备所具备的功能点。 + ++ 涂鸦智能将每个功能点抽象成数据点,数据点定义成不同的类型,例如布尔、枚举、数值等。 ++ 数据点具备读写属性。例如,一个两路的开关,可以抽象成两个数据点,每个数据点类型为布尔型,可取值为 `True` 或 `False`。 ++ 数据点可读写,读表示获取开关目前的值,写表示改变开关目前的值。 + +DPID:指定通信协议下 DP 事件的 ID。 + + + +MCU SDK需要知道你创建了哪些DP点,他们是什么类型的,通过 `void TuyaWifi::set_dp_cmd_total(unsigned char dp_cmd_array[][2], unsigned char dp_cmd_num)` 函数传入MCU SDK。Tuya IoT 对于DP的类型分为6类: + +```c +#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 +``` + +关于`void TuyaWifi::set_dp_cmd_total(unsigned char dp_cmd_array[][2], unsigned char dp_cmd_num)` 函数,`dp_cmd_array[][2]` 为存储的信息的数组,`dp_cmd_num` 为DP总数。 + + + +这里我们假设有一个灯,它主要有3个功能也就是3个DP点,分别是: + ++ 开关(DP ID : 20, DP 类型:布尔类型) ++ 灯的亮度(DP ID : 20, DP 类型:数值类型) ++ 灯光模式(DP ID : 20, DP 类型:枚举类型) + +```c +#include + +TuyaWifi my_device; +... +#define DPID_SWITCH 20 //灯的开关DP +#define DPID_LIGHT 21 //灯的亮度DP +#define DPID_MODE 22 //灯的工作模式DP + +//注意:array[][0]为DPID, array[][1]为DP type +unsigned char dp_id_array[][2] = { + /* DPID | DP type */ + {DPID_SWITCH, DP_TYPE_BOOL}, + {DPID_LIGHT, DP_TYPE_VALUE}, + {DPID_MODE, DP_TYPE_ENUM}, +}; +... +void setup() +{ + ... + my_device.set_dp_cmd_total(dp_id_array, 3); + ... +} +``` + + + +### 3、配网模式设置 + +调用 `void TuyaWifi::mcu_set_wifi_mode(unsigned char mode)` 进入配网模式。 + +```c +/** + * @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); +``` + + + +### 4、下发DP数据处理 + +当云端下发数据后,需要对下发的数据进行解析,通过`unsigned char TuyaWifi::mcu_get_dp_download_data(unsigned char dpid, const unsigned char value[], unsigned short len)` 这个函数进行解析。该函数目前只支持`DP_TYPE_BOOL`,`DP_TYPE_VALUE`,`DP_TYPE_ENUM` 这3种类型;`DP_TYPE_BITMAP` 为故障型一般只上报处理,不会下发,对该类型不用处理;`DP_TYPE_RAW` ,`DP_TYPE_STRING` 这两种类型需要用户自己进行处理。 + + + +```c +/** + * @description: mcu gets bool,value,enum type to send dp value. (raw, string type needs to be handled at the user's discretion. fault only report) + * @param {unsigned char} dpid : data point ID + * @param {const unsigned char} value : dp data buffer address + * @param {unsigned short} len : data length + * @return {unsigned char} Parsed data + */ +unsigned char TuyaWifi::mcu_get_dp_download_data(unsigned char dpid, const unsigned char value[], unsigned short len); +``` + + + +### 5、DP下发处理函数注册 + +当APP控制设备的时候,会从云端下发对应的DP命令到设备,设备对数据进行解析后,对下发的命令执行相对于的动作。 + +对下发命令的处理,通过回调函数来调用,所以我们需要把你的处理函数注册一下。调用这个`void TuyaWifi::dp_process_func_register(tuya_callback_dp_download _func)` 对回调函数进行注册。 + +```c +#include + +TuyaWifi my_device; +... + +void setup() +{ + ... + //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_SWITCH: + switch_value = my_device.mcu_get_dp_download_data(dpid, value, length); + if (switch_value) { + //Turn on + + } else { + //Turn off + + } + //Status changes should be reported. + my_device.mcu_dp_update(dpid, value, length); + break; + + default:break; + } + return SUCCESS; +} +``` + + + +### 6、上报设备状态 + +上报设备状态也就是上报所有DP点值,也是通过注册函数的方式进行的。 + + + +接收 DataPoint 的 6 种不同DP类型的数据类型定义: + +DP上报函数: + +```c +/** + * @description: dp data upload + * @param {unsigned char} dpid + * @param {const unsigned char} value + * @param {unsigned short} len + * @return {*} + */ +unsigned char mcu_dp_update(unsigned char dpid, const unsigned char value[], unsigned short len);//update raw, string type +unsigned char mcu_dp_update(unsigned char dpid, unsigned long value, unsigned short len); +unsigned char mcu_dp_update(unsigned char dpid, unsigned int value, unsigned short len); +``` + + + +上报设备状态函数注册示例: + +```c +#include + +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_value, 1); +} +``` + + + +## 技术支持 + +您可以通过以下方法获得涂鸦的支持: + +- 开发者中心:https://developer.tuya.com +- 帮助中心: https://support.tuya.com/help +- 技术支持工单中心: https://service.console.tuya.com \ No newline at end of file diff --git a/config.h b/config.h new file mode 100755 index 0000000..ead1c82 --- /dev/null +++ b/config.h @@ -0,0 +1,38 @@ +/* + * @FileName: config.h + * @Author: Tuya + * @Email: + * @LastEditors: Tuya + * @Date: 2021-04-10 11:24:27 + * @LastEditTime: 2021-04-28 19:50:37 + * @Copyright: HANGZHOU TUYA INFORMATION TECHNOLOGY CO.,LTD + * @Company: http://www.tuya.com + * @Description: Tuya mcu sdk Arduino library config file. + */ +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +#include "TuyaDefs.h" + +/* Distribution mode selection, only three choices, Anti-touch mode is recommende */ +//#define CONFIG_MODE CONFIG_MODE_DEFAULT //Default working mode +//#define CONFIG_MODE CONFIG_MODE_LOWPOWER //Safe mode (low power working mode) +#define CONFIG_MODE CONFIG_MODE_SPECIAL // Anti-touch mode (special working mode) + +#ifndef SUPPORT_MCU_FIRM_UPDATE +#define WIFI_UART_RECV_BUF_LMT 16 //UART data receiving buffer size, can be reduced if the MCU has insufficient RAM +#define WIFI_DATA_PROCESS_LMT 24 //UART data processing buffer size, according to the user DP data size, must be greater than 24 +#else +#define WIFI_UART_RECV_BUF_LMT 128 //UART data receiving buffer size, can be reduced if the MCU has insufficient RAM + +/* Select the appropriate UART data processing buffer size here + (select the buffer size based on the size selected by the above MCU firmware upgrade package and whether to turn on the weather service) */ +#define WIFI_DATA_PROCESS_LMT 1000 //UART data processing buffer size. If the MCU firmware upgrade is required, the single-packet size is 256, the buffer must be greater than 260, or larger if the weather service is enabled +//#define WIFI_DATA_PROCESS_LMT 600 //UART data processing buffer size. If the MCU firmware upgrade is required, the single-packet size is 512, the buffer must be greater than 520, or larger if the weather service is enabled +//#define WIFI_DATA_PROCESS_LMT 1200 //UART data processing buffer size. If the MCU firmware upgrade is required, the single-packet size is 1024, the buffer must be greater than 1030, or larger if the weather service is enabled + +#endif + +#define WIFIR_UART_SEND_BUF_LMT 48 //According to the user's DP data size, it must be greater than 48 + +#endif /* __CONFIG_H__ */ diff --git a/examples/DataPointType/DataPointType.ino b/examples/DataPointType/DataPointType.ino new file mode 100755 index 0000000..e209d7c --- /dev/null +++ b/examples/DataPointType/DataPointType.ino @@ -0,0 +1,191 @@ +/* + * @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 +#include + +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[] = {"yw3fhhvcbsfnl3eg"}; +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) { + led_state = HIGH; + } else { + led_state = LOW; + } + + digitalWrite(LED_BUILTIN, led_state); + } + } + + delay(10); +} + +/** + * @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= 500) { + last_time = millis(); + + if (led_state == LOW) { + led_state = HIGH; + } else { + led_state = LOW; + } + + digitalWrite(LED_BUILTIN, led_state); + } + ... +} +``` + + + +Device information initialization. + +```c +#include + +TuyaWifi my_device; + +/* Data point define */ +#define DPID_TEMP_CURRENT 1 +#define DPID_HUMIDITY_CURRENT 2 + +/* Current device DP values */ +int temperature = 0; +int humidity = 0; + +/* 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_TEMP_CURRENT, DP_TYPE_VALUE}, + {DPID_HUMIDITY_CURRENT, DP_TYPE_VALUE}, +}; + +unsigned char pid[] = {"xxxxxxxxxxxxxxxx"};//xxxxxxxxxxxxxxxx is your PID +unsigned char mcu_ver[] = {"1.0.0"}; + +void setup() +{ + Serial.begin(9600); + ... + my_device.init(pid, mcu_ver); + //incoming all DPs and their types array, DP numbers + my_device.set_dp_cmd_total(dp_array, 2); + //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); + ... +} + +void loop() +{ + my_device.uart_service(); + ... + delay(1000); +} + +/** + * @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) +{ + /* all DP only report */ + return SUCCESS; +} + +/** + * @description: Upload all DP status of the current device. + * @param {*} + * @return {*} + */ +void dp_update_all(void) +{ + my_device.mcu_dp_update(DPID_TEMP_CURRENT, temperature, 1); + my_device.mcu_dp_update(DPID_HUMIDITY_CURRENT, humidity, 1); +} +``` + + + + Get SHT30 sensor data. + +```c +#include + +/* SHT30 */ +#define SHT30_I2C_ADDR 0x44 + +/* Current device DP values */ +int temperature = 0; +int humidity = 0; + +void setup() +{ + ... + // Initialise I2C communication as MASTER + Wire.begin(); + ... +} + +void loop() +{ + ... + /* get the temperature and humidity */ + get_sht30_value(&temperature, &humidity); + + if ((my_device.mcu_get_wifi_work_state() == WIFI_CONNECTED) || (my_device.mcu_get_wifi_work_state() == WIFI_CONN_CLOUD)) { + my_device.mcu_dp_update(DPID_TEMP_CURRENT, temperature, 1); + my_device.mcu_dp_update(DPID_HUMIDITY_CURRENT, humidity, 1); + } + + delay(1000); +} + +void get_sht30_value(int *temp_value, int *humi_value) +{ + unsigned char i2c_data[6]; + + // Start I2C Transmission + Wire.beginTransmission(SHT30_I2C_ADDR); + // Send measurement command + Wire.write(0x2C); + Wire.write(0x06); + // Stop I2C transmission + Wire.endTransmission(); + delay(500); + + // Request 6 bytes of data + Wire.requestFrom(SHT30_I2C_ADDR, 6); + + // Read 6 bytes of i2c_data + // temperature msb, temperature lsb, temperature crc, humidity msb, humidity lsb, humidity crc + if (Wire.available() == 6) { + for (int i = 0; i < 6 ; i++) { + i2c_data[i] = Wire.read(); + } + + if ((sht30_crc(i2c_data, 2) == i2c_data[2]) && (sht30_crc(i2c_data+3, 2) == i2c_data[5])) {/* crc success */ + *temp_value = (((((i2c_data[0] * 256.0) + i2c_data[1]) * 175) / 65535.0) - 45) * 100; + *humi_value = ((((i2c_data[3] * 256.0) + i2c_data[4]) * 100) / 65535.0) * 100; + } else { + *temp_value = 0; + *humi_value = 0; + } + } +} + +/** + * @description: check sht30 temperature and humidity data + * @param {unsigned char} *data + * @param {unsigned int} count + * @return {*} + */ +unsigned char sht30_crc(unsigned char *data, unsigned int count) +{ + unsigned char crc = 0xff; + unsigned char current_byte; + unsigned char crc_bit; + + /* calculates 8-Bit checksum with given polynomial */ + for (current_byte = 0; current_byte < count; ++current_byte) + { + crc ^= (data[current_byte]); + for (crc_bit = 8; crc_bit > 0; --crc_bit) + { + if (crc & 0x80) + crc = (crc << 1) ^ 0x31; + else + crc = (crc << 1); + } + } + return crc; +} +``` + + + +## III. Technical support + +You can get support for Tuya by using the following methods: + +- Developer Centre: https://developer.tuya.com +- Help Centre: https://support.tuya.com/help +- Technical Support Work Order Centre: https://service.console.tuya.com \ No newline at end of file diff --git a/examples/SHT30/README_zh.md b/examples/SHT30/README_zh.md new file mode 100755 index 0000000..f85f701 --- /dev/null +++ b/examples/SHT30/README_zh.md @@ -0,0 +1,249 @@ +# SHT30 + +[English](./README.md) | [中文](./README_zh.md) + +该库仅支持烧录了通用固件的涂鸦 WiFi+BLE 、WiFi模组,在Arduino UNO板子上验证通过。 + +**注意:Arduino 中的 默认Serial 串口已被Tuya mcu sdk 接管,请不要对默认Serial(引脚 0 ,1)做任何操作。** + +## 一、demo 介绍 + +涂鸦模组和Arduino板连接时会干扰到对Arduino板的烧录,烧录时应断开Arduino板与涂鸦通信板或涂鸦通信板的连接。例程烧录成功后将Arduino板上串口(Serial) 与 涂鸦模组上的 `RXD` 和 `TXD` 连接起来,然后将UNO板子上的 `Pin7` 脚拉低1s左右(模拟按键按下),设备将会进入配网模式,在进入配网状态和配网过程中Arduino板上LED将会闪烁,打开涂鸦智能APP对设备(Arduino_SHT30)进行配网操作,连接成功后Arduino板上LED将会停止闪烁,配网成功后即可通过APP对设备进行控制。 + +本例程硬件使用了Arduino板+涂鸦wifi通信板+SHT30温湿度传感器,设备每隔1秒上传一次当前环境下温湿度值,可通过涂鸦智能APP配网后查看。 + +## 二、功能实现 + +在[涂鸦IoT平台](https://iot.tuya.com/?_source=97c44038fafc20e9c8dd5fdb508cc9c2) 创建完产品后,代码部分的实现主要可以分为配网、设备信息初始化、获取SHT30传感信息三大部分。 + +配网部分: + +```c +/* Current LED status */ +unsigned char led_state = 0; +/* Connect network button pin */ +int wifi_key_pin = 7; +/* last time */ +unsigned long last_time = 0; + +void setup() +{ + ... + /* 相关外设初始化 */ + //Initialize led port, turn off led. + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, LOW); + //Initialize networking keys. + pinMode(wifi_key_pin, INPUT_PULLUP); + ... + last_time = millis(); +} + +void loop() +{ + ... + //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(); + + if (led_state == LOW) { + led_state = HIGH; + } else { + led_state = LOW; + } + + digitalWrite(LED_BUILTIN, led_state); + } + ... +} +``` + + + +设备信息初始化: + +```c +#include + +TuyaWifi my_device; + +/* Data point define */ +#define DPID_TEMP_CURRENT 1 +#define DPID_HUMIDITY_CURRENT 2 + +/* Current device DP values */ +int temperature = 0; +int humidity = 0; + +/* 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_TEMP_CURRENT, DP_TYPE_VALUE}, + {DPID_HUMIDITY_CURRENT, DP_TYPE_VALUE}, +}; + +unsigned char pid[] = {"xxxxxxxxxxxxxxxx"};//xxxxxxxxxxxxxxxx 应为你的PID +unsigned char mcu_ver[] = {"1.0.0"}; + +void setup() +{ + Serial.begin(9600); + ... + my_device.init(pid, mcu_ver); + //incoming all DPs and their types array, DP numbers + my_device.set_dp_cmd_total(dp_array, 2); + //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); + ... +} + +void loop() +{ + my_device.uart_service(); + ... + delay(1000); +} + +/** + * @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) +{ + /* all DP only report */ + return SUCCESS; +} + +/** + * @description: Upload all DP status of the current device. + * @param {*} + * @return {*} + */ +void dp_update_all(void) +{ + my_device.mcu_dp_update(DPID_TEMP_CURRENT, temperature, 1); + my_device.mcu_dp_update(DPID_HUMIDITY_CURRENT, humidity, 1); +} +``` + + + +获取SHT30传感器信息: + +```c +#include + +/* SHT30 */ +#define SHT30_I2C_ADDR 0x44 + +/* Current device DP values */ +int temperature = 0; +int humidity = 0; + +void setup() +{ + ... + // Initialise I2C communication as MASTER + Wire.begin(); + ... +} + +void loop() +{ + ... + /* get the temperature and humidity */ + get_sht30_value(&temperature, &humidity); + + if ((my_device.mcu_get_wifi_work_state() == WIFI_CONNECTED) || (my_device.mcu_get_wifi_work_state() == WIFI_CONN_CLOUD)) { + my_device.mcu_dp_update(DPID_TEMP_CURRENT, temperature, 1); + my_device.mcu_dp_update(DPID_HUMIDITY_CURRENT, humidity, 1); + } + + delay(1000); +} + +void get_sht30_value(int *temp_value, int *humi_value) +{ + unsigned char i2c_data[6]; + + // Start I2C Transmission + Wire.beginTransmission(SHT30_I2C_ADDR); + // Send measurement command + Wire.write(0x2C); + Wire.write(0x06); + // Stop I2C transmission + Wire.endTransmission(); + delay(500); + + // Request 6 bytes of data + Wire.requestFrom(SHT30_I2C_ADDR, 6); + + // Read 6 bytes of i2c_data + // temperature msb, temperature lsb, temperature crc, humidity msb, humidity lsb, humidity crc + if (Wire.available() == 6) { + for (int i = 0; i < 6 ; i++) { + i2c_data[i] = Wire.read(); + } + + if ((sht30_crc(i2c_data, 2) == i2c_data[2]) && (sht30_crc(i2c_data+3, 2) == i2c_data[5])) {/* crc success */ + *temp_value = (((((i2c_data[0] * 256.0) + i2c_data[1]) * 175) / 65535.0) - 45) * 100; + *humi_value = ((((i2c_data[3] * 256.0) + i2c_data[4]) * 100) / 65535.0) * 100; + } else { + *temp_value = 0; + *humi_value = 0; + } + } +} + +/** + * @description: check sht30 temperature and humidity data + * @param {unsigned char} *data + * @param {unsigned int} count + * @return {*} + */ +unsigned char sht30_crc(unsigned char *data, unsigned int count) +{ + unsigned char crc = 0xff; + unsigned char current_byte; + unsigned char crc_bit; + + /* calculates 8-Bit checksum with given polynomial */ + for (current_byte = 0; current_byte < count; ++current_byte) + { + crc ^= (data[current_byte]); + for (crc_bit = 8; crc_bit > 0; --crc_bit) + { + if (crc & 0x80) + crc = (crc << 1) ^ 0x31; + else + crc = (crc << 1); + } + } + return crc; +} +``` + + + +## 三、技术支持 + +您可以通过以下方法获得涂鸦的支持: + +- 开发者中心:https://developer.tuya.com +- 帮助中心: https://support.tuya.com/cn/help +- 技术支持工单中心: https://service.console.tuya.com \ No newline at end of file diff --git a/examples/SHT30/SHT30.ino b/examples/SHT30/SHT30.ino new file mode 100755 index 0000000..65be222 --- /dev/null +++ b/examples/SHT30/SHT30.ino @@ -0,0 +1,196 @@ +/* + * @FileName: SHT30_DIS.ino + * @Author: Tuya + * @Email: + * @LastEditors: Tuya + * @Date: 2021-04-21 15:23:49 + * @LastEditTime: 2021-04-28 19:51:42 + * @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 +#include + +TuyaWifi my_device; + +/* Current LED status */ +unsigned char led_state = 0; +/* Connect network button pin */ +int wifi_key_pin = 7; + +/* SHT30 */ +#define SHT30_I2C_ADDR 0x44 + +/* Data point define */ +#define DPID_TEMP_CURRENT 1 +#define DPID_HUMIDITY_CURRENT 2 + +/* Current device DP values */ +int temperature = 0; +int humidity = 0; + +/* 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_TEMP_CURRENT, DP_TYPE_VALUE}, + {DPID_HUMIDITY_CURRENT, DP_TYPE_VALUE}, +}; + +unsigned char pid[] = {"so33adeiympep2v6"}; +unsigned char mcu_ver[] = {"1.0.0"}; + +/* last time */ +unsigned long last_time = 0; + +void setup() +{ + Serial.begin(9600); + + // Initialise I2C communication as MASTER + Wire.begin(); + + //Initialize led port, turn off led. + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, LOW); + //Initialize networking keys. + pinMode(wifi_key_pin, INPUT_PULLUP); + + my_device.init(pid, mcu_ver); + //incoming all DPs and their types array, DP numbers + my_device.set_dp_cmd_total(dp_array, 2); + //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); + + delay(300); + 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(); + + if (led_state == LOW) { + led_state = HIGH; + } else { + led_state = LOW; + } + + digitalWrite(LED_BUILTIN, led_state); + } + } + + /* get the temperature and humidity */ + get_sht30_value(&temperature, &humidity); + + /* report the temperature and humidity */ + if ((my_device.mcu_get_wifi_work_state() == WIFI_CONNECTED) || (my_device.mcu_get_wifi_work_state() == WIFI_CONN_CLOUD)) { + my_device.mcu_dp_update(DPID_TEMP_CURRENT, temperature, 1); + my_device.mcu_dp_update(DPID_HUMIDITY_CURRENT, humidity, 1); + } + + delay(1000); +} + +void get_sht30_value(int *temp_value, int *humi_value) +{ + unsigned char i2c_data[6]; + + // Start I2C Transmission + Wire.beginTransmission(SHT30_I2C_ADDR); + // Send measurement command + Wire.write(0x2C); + Wire.write(0x06); + // Stop I2C transmission + Wire.endTransmission(); + delay(500); + + // Request 6 bytes of data + Wire.requestFrom(SHT30_I2C_ADDR, 6); + + // Read 6 bytes of i2c_data + // temperature msb, temperature lsb, temperature crc, humidity msb, humidity lsb, humidity crc + if (Wire.available() == 6) { + for (int i = 0; i < 6 ; i++) { + i2c_data[i] = Wire.read(); + } + + if ((sht30_crc(i2c_data, 2) == i2c_data[2]) && (sht30_crc(i2c_data+3, 2) == i2c_data[5])) {/* crc success */ + *temp_value = (((((i2c_data[0] * 256.0) + i2c_data[1]) * 175) / 65535.0) - 45) * 100; + *humi_value = ((((i2c_data[3] * 256.0) + i2c_data[4]) * 100) / 65535.0) * 100; + } else { + *temp_value = 0; + *humi_value = 0; + } + } +} + +/** + * @description: check sht30 temperature and humidity data + * @param {unsigned char} *data + * @param {unsigned int} count + * @return {*} + */ +unsigned char sht30_crc(unsigned char *data, unsigned int count) +{ + unsigned char crc = 0xff; + unsigned char current_byte; + unsigned char crc_bit; + + /* calculates 8-Bit checksum with given polynomial */ + for (current_byte = 0; current_byte < count; ++current_byte) + { + crc ^= (data[current_byte]); + for (crc_bit = 8; crc_bit > 0; --crc_bit) + { + if (crc & 0x80) + crc = (crc << 1) ^ 0x31; + else + crc = (crc << 1); + } + } + return crc; +} + +/** + * @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) +{ + /* all DP only report */ + return SUCCESS; +} + +/** + * @description: Upload all DP status of the current device. + * @param {*} + * @return {*} + */ +void dp_update_all(void) +{ + my_device.mcu_dp_update(DPID_TEMP_CURRENT, temperature, 1); + my_device.mcu_dp_update(DPID_HUMIDITY_CURRENT, humidity, 1); +} + + diff --git a/examples/start/README.md b/examples/start/README.md new file mode 100755 index 0000000..eb24184 --- /dev/null +++ b/examples/start/README.md @@ -0,0 +1,149 @@ +# start +[English](./README.md) | [中文](./README_zh.md) + +This library only supports the Tuya WiFi+BLE, WiFi module with the generic firmware burned in and verified on the Arduino UNO board. + +**Note: The default Serial serial port in Arduino has been taken over by the Tuya mcu sdk, please do not do anything with the default Serial (pins 0 , 1).** + + + +## I. Introduction to the demo + +The connection between the Tuya module and the Arduino board will interfere with the burning of the Arduino board. The Arduino board should be disconnected from the Tuya communication board or the Tuya communication board when burning. After the routine is successfully burned, connect the serial port (Serial) on the Arduino board to the `RXD` and `TXD` on the Tuya module, then pull down the `Pin7` pin on the UNO board for about 1s (simulating a key press), the device will enter the connection network mode, the LED on the Arduino board will flash during the connection network state and connection network process After successful connection, the LED on the Arduino board will stop flashing and the device can be controlled by the APP. + +This example uses Arduino board + Tuya wifi communication board, which can be controlled by the Arduino board after connection network through the Tuya Smart App. + + + +## II. Function Implementation + +### 1. Create product + +Go to [Tuya IoT Platform](https://iot.tuya.com/?_source=97c44038fafc20e9c8dd5fdb508cc9c2) to create a product. + +![creat_produce1](https://images.tuyacn.com/smart/shiliu_zone/Tuya_Arduino_library/creat_produce1.png) + +Select category, programme. + +![creat_produce2](https://images.tuyacn.com/smart/shiliu_zone/Tuya_Arduino_library/creat_produce2.png) + +Complete the product information and click on create product: ! + +![creat_produce3](https://images.tuyacn.com/smart/shiliu_zone/Tuya_Arduino_library/creat_produce3.png) + +Select the relevant functions according to your needs and click on Confirm: ! + +![create_produce4](https://images.tuyacn.com/smart/shiliu_zone/Tuya_Arduino_library/creat_produce4.png) + +After selecting the device panel, go to Hardware Development, select the Tuya Standard Module MCU SDK development method and select the corresponding module: + +![create_produce6](https://images.tuyacn.com/smart/shiliu_zone/Tuya_Arduino_library/creat_produce6.png) + +Select the firmware. + +![create_produce7](https://images.tuyacn.com/smart/shiliu_zone/Tuya_Arduino_library/creat_produce7.png) + +### 2. Important function descriptions + +Initialise the serial port, the generic firmware of the Tuya WIFi module supports 115200, 9600 baud rate adaptive, so the serial port should be initialised to 115200 or 9600 when initialising the serial port. in `setup()`. + +```c++ +Serial.begin(9600); +``` + +mcu needs to send the created PID and the mcu's software version number to the Tuya Cloud module. In `setup()`. + +```c++ + //Enter the PID and MCU software version + my_device.init("ma67l9sgmdyg3d2k", "1.0.0"); +``` + +We need to pass the ID and type of the DP selected when creating the product into the MCU SDK to use. + +```c++ +TuyaWifi my_device; + +#define DPID_SWITCH 20 //DP ID + +unsigned char dp_array[][2] = +{ + //This product was created with only one DP point selected, so there is only one piece of information in this array + {DPID_SWITCH, DP_TYPE_BOOL}, // the first one is filled with the DP point ID, the second one is the data type of the DP point +}; + +void setup() +{ + ... + my_device.set_dp_cmd_total(dp_array, 1); //dp_array: is an array of DP point IDs and data types, 1: is the number of DPs defined in the array + ... +} + +``` + +The initialization also requires registration of the DP point down processing function and the upload all DP points function. + +```c++ +unsigned char led_state = 0; + +void setup() +{ +... + //register DP download processing callback function + my_device.dp_process_func_register(led_dp_process); //register DP download processing callback function + //register upload all DP callback function + my_device.dp_update_all_func_register(dp_update_all); //register device status function, upload all DP points +... +} + +void loop() +{ + ... + my_device.uart_service(); + ... +} + +/** + * @description: DP download callback function. + * @param {unsigned char} dpid + * @param {const unsigned char} value + * @param {unsigned short} length + * @return {unsigned char} + */ +unsigned char led_dp_process(unsigned char dpid,const unsigned char value[], unsigned short length) +{ + switch(dpid) { + case DPID_SWITCH: + led_state = my_device.mcu_get_dp_download_data(dpid, value, length);//get the data of this DP in the downstream data frame + if (led_state) { + digitalWrite(LED_BUILTIN, HIGH); + } else { + digitalWrite(LED_BUILTIN, LOW); + } + my_device.mcu_dp_update(dpid, value, length); + break; + + default:break; + } + return 1; +} + +/** + * @description: Upload all DP status of the current device. + * @param {*} + * @return {*} + */ +void dp_update_all(void) +{ + my_device.mcu_dp_update(DPID_SWITCH, &led_state, 1); +} +``` + + + +## III. Technical Support + +You can get support for Tuya by using the following methods: + +- Developer Centre: https://developer.tuya.com +- Help Centre: https://support.tuya.com/help +- Technical Support Work Order Centre: https://service.console.tuya.com \ No newline at end of file diff --git a/examples/start/README_zh.md b/examples/start/README_zh.md new file mode 100755 index 0000000..103b80d --- /dev/null +++ b/examples/start/README_zh.md @@ -0,0 +1,149 @@ +# start +[English](./README.md) | [中文](./README_zh.md) + +该库仅支持烧录了通用固件的涂鸦 WiFi+BLE 、WiFi模组,在Arduino UNO板子上验证通过。 + +**注意:Arduino 中的 默认Serial 串口已被Tuya mcu sdk 接管,请不要对默认Serial(引脚 0 ,1)做任何操作。** + + + +## 一、demo 介绍 + +涂鸦模组和Arduino板连接时会干扰到对Arduino板的烧录,烧录时应断开Arduino板与涂鸦通信板或涂鸦通信板的连接。例程烧录成功后将Arduino板上串口(Serial) 与 涂鸦模组上的 `RXD` 和 `TXD` 连接起来,然后将UNO板子上的 `Pin7` 脚拉低1s左右(模拟按键按下),设备将会进入配网模式,在进入配网状态和配网过程中Arduino板上LED将会闪烁,打开涂鸦智能APP对设备(Arduino_led)进行配网操作,连接成功后Arduino板上LED将会停止闪烁,配网成功后即可通过APP对设备进行控制。 + +本例程硬件使用了Arduino板+涂鸦wifi通信板,可通过涂鸦智能APP配网后对Arduino板上LED进行控制。 + + + +## 二、功能实现 + +### 1、创建产品 + +进入 [Tuya IoT平台](https://iot.tuya.com/?_source=97c44038fafc20e9c8dd5fdb508cc9c2) 创建产品: + +![creat_produce1](https://images.tuyacn.com/smart/shiliu_zone/Tuya_Arduino_library/creat_produce1.png) + +选择品类,方案: + +![creat_produce2](https://images.tuyacn.com/smart/shiliu_zone/Tuya_Arduino_library/creat_produce2.png) + +完善产品信息,点击创建产品: + +![creat_produce3](https://images.tuyacn.com/smart/shiliu_zone/Tuya_Arduino_library/creat_produce3.png) + +根据自身需求选择相关功能,点击确认: + +![creat_produce4](https://images.tuyacn.com/smart/shiliu_zone/Tuya_Arduino_library/creat_produce4.png) + +选择设备面板后,进入硬件开发,选择 涂鸦标准模组 MCU SDK 开发方式,选择对应的模组: + +![creat_produce6](https://images.tuyacn.com/smart/shiliu_zone/Tuya_Arduino_library/creat_produce6.png) + +选择固件: + +![creat_produce7](https://images.tuyacn.com/smart/shiliu_zone/Tuya_Arduino_library/creat_produce7.png) + +### 2、重要函数说明 + +初始化串口,涂鸦WIFi模组的通用固件支持115200、9600波特率自适应,所以初始化串口时应将串口波特率初始化为115200或9600。在 `setup()` 中: + +```c++ +Serial.begin(9600); +``` + +mcu需要将创建的PID和mcu的软件版本号发送给涂鸦云模组。在 `setup()` 中: + +```c++ + //Enter the PID and MCU software version + my_device.init("ma67l9sgmdyg3d2k", "1.0.0"); +``` + +我们需要将创建产品时选择的所DP 的 ID 和类型传入MCU SDK内使用: + +```c++ +TuyaWifi my_device; + +#define DPID_SWITCH 20 //DP ID + +unsigned char dp_array[][2] = +{ + //该产品创建时只选择了一个DP点,所以该数组只有一条信息 + {DPID_SWITCH, DP_TYPE_BOOL}, //前一个填入DP点ID,后一个为DP点的数据类型 +}; + +void setup() +{ + ... + my_device.set_dp_cmd_total(dp_array, 1); //dp_array:为存储DP点ID和数据类型的数组, 1:为数组内定义的DP个数 + ... +} + +``` + +初始化时还需注册DP点下发处理函数和上传所有DP点函数: + +```c++ +unsigned char led_state = 0; + +void setup() +{ +... + //register DP download processing callback function + my_device.dp_process_func_register(led_dp_process); //注册DP下发处理函数 + //register upload all DP callback function + my_device.dp_update_all_func_register(dp_update_all);//注册设备状态函数,上传所有DP点 +... +} + +void loop() +{ + ... + my_device.uart_service(); + ... +} + +/** + * @description: DP download callback function. + * @param {unsigned char} dpid + * @param {const unsigned char} value + * @param {unsigned short} length + * @return {unsigned char} + */ +unsigned char led_dp_process(unsigned char dpid,const unsigned char value[], unsigned short length) +{ + switch(dpid) { + case DPID_SWITCH: + led_state = my_device.mcu_get_dp_download_data(dpid, value, length);//得到下发数据帧中该DP的数据 + if (led_state) { + digitalWrite(LED_BUILTIN, HIGH); + } else { + digitalWrite(LED_BUILTIN, LOW); + } + my_device.mcu_dp_update(dpid, value, length); + break; + + default:break; + } + return 1; +} + +/** + * @description: Upload all DP status of the current device. + * @param {*} + * @return {*} + */ +void dp_update_all(void) +{ + my_device.mcu_dp_update(DPID_SWITCH, &led_state, 1); +} +``` + + + +## 三、技术支持 + +您可以通过以下方法获得涂鸦的支持: + +- 开发者中心:https://developer.tuya.com +- 帮助中心: https://support.tuya.com/help +- 技术支持工单中心: https://service.console.tuya.com \ No newline at end of file diff --git a/examples/start/start.ino b/examples/start/start.ino new file mode 100755 index 0000000..4cc9032 --- /dev/null +++ b/examples/start/start.ino @@ -0,0 +1,131 @@ +/* + * @FileName: start.ino + * @Author: Tuya + * @Email: + * @LastEditors: Tuya + * @Date: 2021-04-10 11:24:27 + * @LastEditTime: 2021-04-28 19:48:31 + * @Copyright: HANGZHOU TUYA INFORMATION TECHNOLOGY CO.,LTD + * @Company: http://www.tuya.com + * @Description: This demo is based on the Arduino UNO, and the LEDs on the UNO board are controlled by the Tuya Smart App. + * Enter network connection mode when Pin7 to GND. + * @Github:https://github.com/tuya/tuya-wifi-mcu-sdk-arduino-library + */ + +#include +#include + +TuyaWifi my_device; + + +/* Current LED status */ +unsigned char led_state = 0; +/* Connect network button pin */ +int key_pin = 7; + +/* Data point define */ +#define DPID_SWITCH 20 + +/* 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_SWITCH, DP_TYPE_BOOL}, +}; + +unsigned char pid[] = {"ma67l9sgmdyg3d2k"}; +unsigned char mcu_ver[] = {"1.0.0"}; + +/* last time */ +unsigned long last_time = 0; + +void setup() +{ + // Serial.begin(9600); + Serial.begin(9600); + + //Initialize led port, turn off led. + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, LOW); + + //Initialize networking keys. + pinMode(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, 1); + //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(key_pin) == LOW) { + delay(80); + if (digitalRead(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(); + + if (led_state == LOW) { + led_state = HIGH; + } else { + led_state = LOW; + } + digitalWrite(LED_BUILTIN, led_state); + } + } + + delay(10); +} + +/** + * @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_SWITCH: + led_state = my_device.mcu_get_dp_download_data(dpid, value, length); /* Get the value of the down DP command */ + if (led_state) { + //Turn on + digitalWrite(LED_BUILTIN, HIGH); + } else { + //Turn off + digitalWrite(LED_BUILTIN, LOW); + } + //Status changes should be reported. + my_device.mcu_dp_update(dpid, value, length); + break; + + default:break; + } + return SUCCESS; +} + +/** + * @description: Upload all DP status of the current device. + * @param {*} + * @return {*} + */ +void dp_update_all(void) +{ + my_device.mcu_dp_update(DPID_SWITCH, led_state, 1); +} diff --git a/keywords.txt b/keywords.txt new file mode 100755 index 0000000..39aee9f --- /dev/null +++ b/keywords.txt @@ -0,0 +1,53 @@ +####################################### +# Data types (KEYWORD1) +####################################### + +TuyaWifi KEYWORD1 +TuyaUart KEYWORD1 +TuyaTools KEYWORD1 +TuyaDataPoint KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +my_device KEYWORD2 +init KEYWORD2 +uart_service KEYWORD2 +dp_process_func_register KEYWORD2 +dp_update_all_func_register KEYWORD2 +data_point_handle KEYWORD2 +set_download_cmd_total KEYWORD2 +get_dowmload_dpid_index KEYWORD2 +mcu_get_dp_download_data KEYWORD2 +mcu_dp_update KEYWORD2 +mcu_set_wifi_mode KEYWORD2 +mcu_get_wifi_work_state KEYWORD2 +set_dp_cmd_total KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +SMART_CONFIG_STATE LITERAL1 +AP_STATE LITERAL1 +WIFI_NOT_CONNECTED LITERAL1 +WIFI_CONNECTED LITERAL1 +WIFI_CONN_CLOUD LITERAL1 +WIFI_LOW_POWER LITERAL1 +SMART_AND_AP_STATE LITERAL1 +WIFI_SATE_UNKNOW LITERAL1 + +DP_TYPE_RAW LITERAL1 +DP_TYPE_BOOL LITERAL1 +DP_TYPE_VALUE LITERAL1 +DP_TYPE_STRING LITERAL1 +DP_TYPE_ENUM LITERAL1 +DP_TYPE_BITMAP LITERAL1 + +SMART_CONFIG LITERAL1 +AP_CONFIG LITERAL1 + +CONFIG_MODE_DEFAULT LITERAL1 +CONFIG_MODE_LOWPOWER LITERAL1 +CONFIG_MODE_SPECIAL LITERAL1 diff --git a/library.properties b/library.properties new file mode 100755 index 0000000..77e9ddf --- /dev/null +++ b/library.properties @@ -0,0 +1,10 @@ +name=Tuya_WiFi_MCU_SDK +version=0.0.1 +author=Tuya +maintainer=Tuya +sentence=Communicate with Tuya modules that have flashed the Tuya common Wi-Fi firmware. +paragraph= +category=Communication +url=https://github.com/tuya/tuya-wifi-mcu-sdk-arduino-library +architectures=* +includes=TuyaWifi.h diff --git a/src/TuyaDataPoint.cpp b/src/TuyaDataPoint.cpp new file mode 100755 index 0000000..0761649 --- /dev/null +++ b/src/TuyaDataPoint.cpp @@ -0,0 +1,181 @@ +/* + * @FileName: TuyaDataPoint.cpp + * @Author: Tuya + * @Email: + * @LastEditors: Tuya + * @Date: 2021-04-10 15:34:17 + * @LastEditTime: 2021-04-28 19:48:05 + * @Copyright: HANGZHOU TUYA INFORMATION TECHNOLOGY CO.,LTD + * @Company: http://www.tuya.com + * @Description: tuya mcu sdk Arduino library about data point process. + */ +#include "TuyaDataPoint.h" +#include "TuyaDefs.h" +#include "TuyaTools.h" +#include "TuyaUart.h" +#include + +extern TuyaTools tuya_tools; +extern TuyaUart tuya_uart; + +unsigned char TuyaDataPoint::mcu_get_dp_download_bool(const unsigned char value[], unsigned short len) +{ + return (value[0]); +} + +unsigned char TuyaDataPoint::mcu_get_dp_download_enum(const unsigned char value[], unsigned short len) +{ + return (value[0]); +} + +unsigned long TuyaDataPoint::mcu_get_dp_download_value(const unsigned char value[], unsigned short len) +{ + return (tuya_tools.byte_to_int(value)); +} + +unsigned char TuyaDataPoint::mcu_dp_raw_update(unsigned char dpid, const unsigned char value[], unsigned short len) +{ + unsigned short send_len = 0; + + if (stop_update_flag == ENABLE) + return SUCCESS; + // + send_len = tuya_uart.set_wifi_uart_byte(send_len, dpid); + send_len = tuya_uart.set_wifi_uart_byte(send_len, DP_TYPE_RAW); + // + send_len = tuya_uart.set_wifi_uart_byte(send_len, len / 0x100); + send_len = tuya_uart.set_wifi_uart_byte(send_len, len % 0x100); + // + send_len = tuya_uart.set_wifi_uart_buffer(send_len, (unsigned char *)value, len); + + tuya_uart.wifi_uart_write_frame(STATE_UPLOAD_CMD, MCU_TX_VER, send_len); + + return SUCCESS; +} + +unsigned char TuyaDataPoint::mcu_dp_bool_update(unsigned char dpid, unsigned char value) +{ + unsigned short send_len = 0; + + if (stop_update_flag == ENABLE) + return SUCCESS; + + send_len = tuya_uart.set_wifi_uart_byte(send_len, dpid); + send_len = tuya_uart.set_wifi_uart_byte(send_len, DP_TYPE_BOOL); + // + send_len = tuya_uart.set_wifi_uart_byte(send_len, 0); + send_len = tuya_uart.set_wifi_uart_byte(send_len, 1); + // + if (value == FALSE) + { + send_len = tuya_uart.set_wifi_uart_byte(send_len, FALSE); + } + else + { + send_len = tuya_uart.set_wifi_uart_byte(send_len, 1); + } + + tuya_uart.wifi_uart_write_frame(STATE_UPLOAD_CMD, MCU_TX_VER, send_len); + + return SUCCESS; +} + +unsigned char TuyaDataPoint::mcu_dp_value_update(unsigned char dpid, unsigned long value) +{ + unsigned short send_len = 0; + + if (stop_update_flag == ENABLE) + return SUCCESS; + + send_len = tuya_uart.set_wifi_uart_byte(send_len, dpid); + send_len = tuya_uart.set_wifi_uart_byte(send_len, DP_TYPE_VALUE); + // + send_len = tuya_uart.set_wifi_uart_byte(send_len, 0); + send_len = tuya_uart.set_wifi_uart_byte(send_len, 4); + // + send_len = tuya_uart.set_wifi_uart_byte(send_len, value >> 24); + send_len = tuya_uart.set_wifi_uart_byte(send_len, value >> 16); + send_len = tuya_uart.set_wifi_uart_byte(send_len, value >> 8); + send_len = tuya_uart.set_wifi_uart_byte(send_len, value & 0xff); + + tuya_uart.wifi_uart_write_frame(STATE_UPLOAD_CMD, MCU_TX_VER, send_len); + + return SUCCESS; +} + +unsigned char TuyaDataPoint::mcu_dp_string_update(unsigned char dpid, const unsigned char value[], unsigned short len) +{ + unsigned short send_len = 0; + + if (stop_update_flag == ENABLE) + return SUCCESS; + // + send_len = tuya_uart.set_wifi_uart_byte(send_len, dpid); + send_len = tuya_uart.set_wifi_uart_byte(send_len, DP_TYPE_STRING); + // + send_len = tuya_uart.set_wifi_uart_byte(send_len, len / 0x100); + send_len = tuya_uart.set_wifi_uart_byte(send_len, len % 0x100); + // + send_len = tuya_uart.set_wifi_uart_buffer(send_len, (unsigned char *)value, len); + + tuya_uart.wifi_uart_write_frame(STATE_UPLOAD_CMD, MCU_TX_VER, send_len); + + return SUCCESS; +} + +unsigned char TuyaDataPoint::mcu_dp_enum_update(unsigned char dpid, unsigned char value) +{ + unsigned short send_len = 0; + + if (stop_update_flag == ENABLE) + return SUCCESS; + + send_len = tuya_uart.set_wifi_uart_byte(send_len, dpid); + send_len = tuya_uart.set_wifi_uart_byte(send_len, DP_TYPE_ENUM); + // + send_len = tuya_uart.set_wifi_uart_byte(send_len, 0); + send_len = tuya_uart.set_wifi_uart_byte(send_len, 1); + // + send_len = tuya_uart.set_wifi_uart_byte(send_len, value); + + tuya_uart.wifi_uart_write_frame(STATE_UPLOAD_CMD, MCU_TX_VER, send_len); + + return SUCCESS; +} + +unsigned char TuyaDataPoint::mcu_dp_fault_update(unsigned char dpid, unsigned long value) +{ + unsigned short send_len = 0; + + if (stop_update_flag == ENABLE) + return SUCCESS; + + send_len = tuya_uart.set_wifi_uart_byte(send_len, dpid); + send_len = tuya_uart.set_wifi_uart_byte(send_len, DP_TYPE_BITMAP); + // + send_len = tuya_uart.set_wifi_uart_byte(send_len, 0); + + if ((value | 0xff) == 0xff) + { + send_len = tuya_uart.set_wifi_uart_byte(send_len, 1); + send_len = tuya_uart.set_wifi_uart_byte(send_len, value); + } + else if ((value | 0xffff) == 0xffff) + { + send_len = tuya_uart.set_wifi_uart_byte(send_len, 2); + send_len = tuya_uart.set_wifi_uart_byte(send_len, value >> 8); + send_len = tuya_uart.set_wifi_uart_byte(send_len, value & 0xff); + } + else + { + send_len = tuya_uart.set_wifi_uart_byte(send_len, 4); + send_len = tuya_uart.set_wifi_uart_byte(send_len, value >> 24); + send_len = tuya_uart.set_wifi_uart_byte(send_len, value >> 16); + send_len = tuya_uart.set_wifi_uart_byte(send_len, value >> 8); + send_len = tuya_uart.set_wifi_uart_byte(send_len, value & 0xff); + } + + tuya_uart.wifi_uart_write_frame(STATE_UPLOAD_CMD, MCU_TX_VER, send_len); + + return SUCCESS; +} diff --git a/src/TuyaDataPoint.h b/src/TuyaDataPoint.h new file mode 100755 index 0000000..bc0e330 --- /dev/null +++ b/src/TuyaDataPoint.h @@ -0,0 +1,35 @@ +/* + * @FileName: TuyaDataPoint.h + * @Author: Tuya + * @Email: + * @LastEditors: Tuya + * @Date: 2021-04-10 15:34:17 + * @LastEditTime: 2021-04-28 19:48:45 + * @Copyright: HANGZHOU TUYA INFORMATION TECHNOLOGY CO.,LTD + * @Company: http://www.tuya.com + * @Description: + */ +#ifndef __TUYA_DATA_POINT_H__ +#define __TUYA_DATA_POINT_H__ + +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: +}; + +#endif /* __TUYA_DATA_POINT_H__ */ diff --git a/src/TuyaDefs.h b/src/TuyaDefs.h new file mode 100755 index 0000000..e7122be --- /dev/null +++ b/src/TuyaDefs.h @@ -0,0 +1,156 @@ +/* + * @FileName: TuyaDefs.h + * @Author: Tuya + * @Email: + * @LastEditors: Tuya + * @Date: 2021-04-10 11:28:40 + * @LastEditTime: 2021-04-28 19:48:57 + * @Copyright: HANGZHOU TUYA INFORMATION TECHNOLOGY CO.,LTD + * @Company: http://www.tuya.com + * @Description: Some necessary constant definitions. + */ +#ifndef __TUYA_DEFS_H__ +#define __TUYA_DEFS_H__ + +/* Define constant */ +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#ifndef SUCCESS +#define SUCCESS 1 +#endif + +#ifndef ERROR +#define ERROR 0 +#endif + +#ifndef INVALID +#define INVALID 0xFF +#endif + +#ifndef ENABLE +#define ENABLE 1 +#endif + +#ifndef DISABLE +#define DISABLE 0 +#endif + +#define MCU_RX_VER 0x00 //Module send frame protocol version number +#define MCU_TX_VER 0x03 //MCU send frame protocol version number(default) +#define PROTOCOL_HEAD 0x07 //Fixed protocol header length +#define FRAME_FIRST 0x55 //Frame header first byte +#define FRAME_SECOND 0xaa //Frame header second byte + +//============================================================================= +//Byte order of the frame +//============================================================================= +#define HEAD_FIRST 0 +#define HEAD_SECOND 1 +#define PROTOCOL_VERSION 2 +#define FRAME_TYPE 3 +#define LENGTH_HIGH 4 +#define LENGTH_LOW 5 +#define DATA_START 6 + +//============================================================================= +//Data frame type +//============================================================================= +#define HEAT_BEAT_CMD 0 //Heartbeat package +#define PRODUCT_INFO_CMD 1 //Product information +#define WORK_MODE_CMD 2 //Query the module working mode set by the MCU +#define WIFI_STATE_CMD 3 //Wifi working status +#define WIFI_RESET_CMD 4 //Reset wifi +#define WIFI_MODE_CMD 5 //Select smartconfig/AP mode +#define DATA_QUERT_CMD 6 //Order send +#define STATE_UPLOAD_CMD 7 //Status upload +#define STATE_QUERY_CMD 8 //Status query +#define UPDATE_START_CMD 0x0a //Upgrade start +#define UPDATE_TRANS_CMD 0x0b //Upgrade transfer +#define GET_ONLINE_TIME_CMD 0x0c //Get system time (Greenwich Mean Time) +#define FACTORY_MODE_CMD 0x0d //Enter production test mode +#define WIFI_TEST_CMD 0x0e //Wifi function test +#define GET_LOCAL_TIME_CMD 0x1c //Get local time +#define WEATHER_OPEN_CMD 0x20 //Turn on the weather +#define WEATHER_DATA_CMD 0x21 //Weather data +#define STATE_UPLOAD_SYN_CMD 0x22 //Status upload (synchronization) +#define STATE_UPLOAD_SYN_RECV_CMD 0x23 //Status upload results(synchronization) +#define HEAT_BEAT_STOP 0x25 //Turn off the WIFI module heartbeat +#define STREAM_TRANS_CMD 0x28 //Stream data transmission +#define GET_WIFI_STATUS_CMD 0x2b //Gets the wifi networking status +#define WIFI_CONNECT_TEST_CMD 0x2c //Wifi function test(connection designated route) +#define GET_MAC_CMD 0x2d //Get module mac +#define GET_IR_STATUS_CMD 0x2e //IR status notification +#define IR_TX_RX_TEST_CMD 0x2f //IR into send-receive test +#define MAPS_STREAM_TRANS_CMD 0x30 //streams trans(Support for multiple maps) +#define FILE_DOWNLOAD_START_CMD 0x31 //File download startup +#define FILE_DOWNLOAD_TRANS_CMD 0x32 //File download data transfer +#define MODULE_EXTEND_FUN_CMD 0x34 //Open the module time service notification +#define BLE_TEST_CMD 0x35 //Bluetooth functional test(Scan designated bluetooth beacon) +#define GET_VOICE_STATE_CMD 0x60 //Gets the voice status code +#define MIC_SILENCE_CMD 0x61 //MIC mute Settings +#define SET_SPEAKER_VOLUME_CMD 0x62 //speaker volume set +#define VOICE_TEST_CMD 0x63 //Audio production test +#define VOICE_AWAKEN_TEST_CMD 0x64 //Wake up production test +#define VOICE_EXTEND_FUN_CMD 0x65 //Voice module extension function + +//============================================================================= +//WIFI work status +//============================================================================= +#define SMART_CONFIG_STATE 0x00 +#define AP_STATE 0x01 +#define WIFI_NOT_CONNECTED 0x02 +#define WIFI_CONNECTED 0x03 +#define WIFI_CONN_CLOUD 0x04 +#define WIFI_LOW_POWER 0x05 +#define SMART_AND_AP_STATE 0x06 +#define WIFI_SATE_UNKNOW 0xff +//============================================================================= +//wifi reset status +//============================================================================= +#define RESET_WIFI_ERROR 0 +#define RESET_WIFI_SUCCESS 1 + +//============================================================================= +//wifi reset result +//============================================================================= +#define SET_WIFICONFIG_ERROR 0 +#define SET_WIFICONFIG_SUCCESS 1 + +//============================================================================= +//dp data point type +//============================================================================= +#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 + +//============================================================================= +//wifi distribution network +//============================================================================= +#define SMART_CONFIG 0x0 +#define AP_CONFIG 0x1 + +//============================================================================= +//Choose network access mode +//============================================================================= +#define CONFIG_MODE_DEFAULT "0" //Default mode +#define CONFIG_MODE_LOWPOWER "1" //low power mode +#define CONFIG_MODE_SPECIAL "2" //special mode + +#endif /* __TUYA_DEFS_H__ */ \ No newline at end of file diff --git a/src/TuyaTools.cpp b/src/TuyaTools.cpp new file mode 100755 index 0000000..6d6a703 --- /dev/null +++ b/src/TuyaTools.cpp @@ -0,0 +1,171 @@ +/* + * @FileName: TuyaTools.cpp + * @Author: Tuya + * @Email: + * @LastEditors: Tuya + * @Date: 2021-04-10 14:04:23 + * @LastEditTime: 2021-04-28 19:49:08 + * @Copyright: HANGZHOU TUYA INFORMATION TECHNOLOGY CO.,LTD + * @Company: http://www.tuya.com + * @Description: Some necessary tools. + */ +#include "TuyaTools.h" +#include "TuyaDefs.h" + +TuyaTools::TuyaTools(void) +{ +} + +TuyaTools::~TuyaTools(void) +{ +} + +unsigned char TuyaTools::hex_to_bcd(unsigned char Value_H, unsigned char Value_L) +{ + unsigned char bcd_value; + + if ((Value_H >= '0') && (Value_H <= '9')) + Value_H -= '0'; + else if ((Value_H >= 'A') && (Value_H <= 'F')) + Value_H = Value_H - 'A' + 10; + else if ((Value_H >= 'a') && (Value_H <= 'f')) + Value_H = Value_H - 'a' + 10; + + bcd_value = Value_H & 0x0f; + + bcd_value <<= 4; + if ((Value_L >= '0') && (Value_L <= '9')) + Value_L -= '0'; + else if ((Value_L >= 'A') && (Value_L <= 'F')) + Value_L = Value_L - 'a' + 10; + else if ((Value_L >= 'a') && (Value_L <= 'f')) + Value_L = Value_L - 'a' + 10; + + bcd_value |= Value_L & 0x0f; + + return bcd_value; +} + +unsigned long TuyaTools::my_strlen(unsigned char *str) +{ + unsigned long len = 0; + if (str == NULL) + { + return 0; + } + + for (len = 0; *str++ != '\0';) + { + len++; + } + + return len; +} + +void *TuyaTools::my_memset(void *src, unsigned char ch, unsigned short count) +{ + unsigned char *tmp = (unsigned char *)src; + + if (src == NULL) + { + return NULL; + } + + while (count--) + { + *tmp++ = ch; + } + + return src; +} + +void *TuyaTools::my_memcpy(void *dest, const void *src, unsigned short count) +{ + unsigned char *pdest = (unsigned char *)dest; + const unsigned char *psrc = (const unsigned char *)src; + unsigned short i; + + if (dest == NULL || src == NULL) + { + return NULL; + } + + if ((pdest <= psrc) || (pdest > psrc + count)) + { + for (i = 0; i < count; i++) + { + pdest[i] = psrc[i]; + } + } + else + { + for (i = count; i > 0; i--) + { + pdest[i - 1] = psrc[i - 1]; + } + } + + return dest; +} + +char *TuyaTools::my_strcpy(char *dest, const char *src) +{ + if ((NULL == dest) || (NULL == src)) + { + return NULL; + } + + char *p = dest; + while (*src != '\0') + { + *dest++ = *src++; + } + *dest = '\0'; + return p; +} + +int TuyaTools::my_strcmp(char *s1, char *s2) +{ + while (*s1 && *s2 && *s1 == *s2) + { + s1++; + s2++; + } + return *s1 - *s2; +} + +void TuyaTools::int_to_byte(unsigned long number, unsigned char value[4]) +{ + value[0] = number >> 24; + value[1] = number >> 16; + value[2] = number >> 8; + value[3] = number & 0xff; +} + +unsigned long TuyaTools::byte_to_int(const unsigned char value[4]) +{ + unsigned long nubmer = 0; + + nubmer = (unsigned long)value[0]; + nubmer <<= 8; + nubmer |= (unsigned long)value[1]; + nubmer <<= 8; + nubmer |= (unsigned long)value[2]; + nubmer <<= 8; + nubmer |= (unsigned long)value[3]; + + return nubmer; +} + +unsigned char TuyaTools::get_check_sum(unsigned char *pack, unsigned short pack_len) +{ + unsigned short i; + unsigned char check_sum = 0; + + for (i = 0; i < pack_len; i++) + { + check_sum += *pack++; + } + + return check_sum; +} diff --git a/src/TuyaTools.h b/src/TuyaTools.h new file mode 100755 index 0000000..7ccffb8 --- /dev/null +++ b/src/TuyaTools.h @@ -0,0 +1,34 @@ +/* + * @FileName: TuyaTools.h + * @Author: Tuya + * @Email: + * @LastEditors: Tuya + * @Date: 2021-04-25 17:44:25 + * @LastEditTime: 2021-04-28 19:49:36 + * @Copyright: HANGZHOU TUYA INFORMATION TECHNOLOGY CO.,LTD + * @Company: http://www.tuya.com + * @Description: + */ +#ifndef __TUYA_TOOLS_H__ +#define __TUYA_TOOLS_H__ + +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); + void int_to_byte(unsigned long number, unsigned char value[4]); + unsigned long byte_to_int(const unsigned char value[4]); + unsigned char get_check_sum(unsigned char *pack, unsigned short pack_len); + +private: +}; + +#endif /* __TUYA_TOOLS_H__ */ diff --git a/src/TuyaUart.cpp b/src/TuyaUart.cpp new file mode 100755 index 0000000..900f8ed --- /dev/null +++ b/src/TuyaUart.cpp @@ -0,0 +1,204 @@ +/* + * @FileName: TuyaUart.cpp + * @Author: Tuya + * @Email: + * @LastEditors: Tuya + * @Date: 2021-04-10 15:34:37 + * @LastEditTime: 2021-04-28 19:49:55 + * @Copyright: HANGZHOU TUYA INFORMATION TECHNOLOGY CO.,LTD + * @Company: http://www.tuya.com + * @Description: Tuya mcu sdk Arduino library about uart buffer, data receiving and sending. + */ +#include +#include "TuyaWifi.h" +#include "TuyaUart.h" +#include "TuyaTools.h" + +extern TuyaTools tuya_tools; + +TuyaUart::TuyaUart(void) +{ + wifi_protocol_init(); +} + +TuyaUart::~TuyaUart(void) +{ +} + +void TuyaUart::wifi_protocol_init(void) +{ + rx_buf_in = (unsigned char *)wifi_uart_rx_buf; + rx_buf_out = (unsigned char *)wifi_uart_rx_buf; + + stop_update_flag = DISABLE; + +#ifndef WIFI_CONTROL_SELF_MODE + wifi_work_state = WIFI_SATE_UNKNOW; +#endif +} + +void TuyaUart::uart_transmit_output(unsigned char value) +{ + write(value); +} + +unsigned char TuyaUart::uart_receive_input(unsigned char data) +{ + if (1 == rx_buf_out - rx_buf_in) + { + //UART receive buffer is full + return ERROR; + } + else if ((rx_buf_in > rx_buf_out) && ((unsigned long)(rx_buf_in - rx_buf_out) >= sizeof(wifi_uart_rx_buf))) + { + //UART receive buffer is full + return ERROR; + } + else + { + //UART receive buffer is not full + if (rx_buf_in >= (unsigned char *)(wifi_uart_rx_buf + sizeof(wifi_uart_rx_buf))) + { + rx_buf_in = (unsigned char *)(wifi_uart_rx_buf); + } + + *rx_buf_in++ = data; + } + return SUCCESS; +} + +void TuyaUart::uart_receive_buff_input(unsigned char value[], unsigned short data_len) +{ + unsigned short i = 0; + for (i = 0; i < data_len; i++) + { + uart_receive_input(value[i]); + } +} + +unsigned char TuyaUart::take_byte_rxbuff(void) +{ + unsigned char date; + + if (rx_buf_out != rx_buf_in) + { + //With data + if (rx_buf_out >= (unsigned char *)(wifi_uart_rx_buf + sizeof(wifi_uart_rx_buf))) + { + //The data has reached the end + rx_buf_out = (unsigned char *)(wifi_uart_rx_buf); + } + + date = *rx_buf_out++; + } + + return date; +} + +unsigned char TuyaUart::with_data_rxbuff(void) +{ + if (rx_buf_in != rx_buf_out) + return 1; + else + return 0; +} + +void TuyaUart::wifi_uart_write_data(unsigned char *in, unsigned short len) +{ + if ((NULL == in) || (0 == len)) + { + return; + } + + while (len--) + { + uart_transmit_output(*in); + in++; + } +} + +void TuyaUart::wifi_uart_write_frame(unsigned char fr_type, unsigned char fr_ver, unsigned short len) +{ + unsigned char check_sum = 0; + + wifi_uart_tx_buf[HEAD_FIRST] = 0x55; + wifi_uart_tx_buf[HEAD_SECOND] = 0xaa; + wifi_uart_tx_buf[PROTOCOL_VERSION] = fr_ver; + wifi_uart_tx_buf[FRAME_TYPE] = fr_type; + wifi_uart_tx_buf[LENGTH_HIGH] = len >> 8; + wifi_uart_tx_buf[LENGTH_LOW] = len & 0xff; + + len += PROTOCOL_HEAD; + check_sum = tuya_tools.get_check_sum((unsigned char *)wifi_uart_tx_buf, len - 1); + wifi_uart_tx_buf[len - 1] = check_sum; + + wifi_uart_write_data((unsigned char *)wifi_uart_tx_buf, len); +} + +unsigned short TuyaUart::set_wifi_uart_byte(unsigned short dest, unsigned char byte) +{ + unsigned char *obj = (unsigned char *)wifi_uart_tx_buf + DATA_START + dest; + + *obj = byte; + dest += 1; + + return dest; +} + +unsigned short TuyaUart::set_wifi_uart_buffer(unsigned short dest, const unsigned char *src, unsigned short len) +{ + unsigned char *obj = (unsigned char *)wifi_uart_tx_buf + DATA_START + dest; + + tuya_tools.my_memcpy(obj, src, len); + + dest += len; + return dest; +} + +void TuyaUart::set_serial(HardwareSerial *serial) +{ + _isHWSerial = TRUE; + _port = serial; +} + +void TuyaUart::set_serial(SoftwareSerial *serial) +{ + _isHWSerial = FALSE; + _port = serial; +} + +void TuyaUart::begin(long baud_rate) +{ + if (_isHWSerial) { + static_cast(_port)->begin(baud_rate); + } else { + static_cast(_port)->begin(baud_rate); + } +} + +char TuyaUart::read(void) +{ + if (_isHWSerial) { + return static_cast(_port)->read(); + } else { + return static_cast(_port)->read(); + } +} + +size_t TuyaUart::write(char value) +{ + if (_isHWSerial) { + return static_cast(_port)->write(value); + } else { + return static_cast(_port)->write(value); + } +} + +int TuyaUart::available(void) +{ + if (_isHWSerial) { + return static_cast(_port)->available(); + } else { + return static_cast(_port)->available(); + } +} diff --git a/src/TuyaUart.h b/src/TuyaUart.h new file mode 100755 index 0000000..973fbc8 --- /dev/null +++ b/src/TuyaUart.h @@ -0,0 +1,59 @@ +/* + * @FileName: TuyaUart.h + * @Author: Tuya + * @Email: + * @LastEditors: Tuya + * @Date: 2021-04-15 17:56:56 + * @LastEditTime: 2021-04-28 19:50:07 + * @Copyright: HANGZHOU TUYA INFORMATION TECHNOLOGY CO.,LTD + * @Company: http://www.tuya.com + * @Description: + */ +#ifndef __TUYA_UART_H__ +#define __TUYA_UART_H__ + +#include "../config.h" +#include "TuyaDefs.h" +#include +#include +#include + +class TuyaUart +{ +public: + 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; +}; + +#endif /* __TUYA_UART_H__ */ diff --git a/src/TuyaWifi.cpp b/src/TuyaWifi.cpp new file mode 100755 index 0000000..c674642 --- /dev/null +++ b/src/TuyaWifi.cpp @@ -0,0 +1,994 @@ +/* + * @FileName: Tuya.cpp + * @Author: Tuya + * @Email: + * @LastEditors: Tuya + * @Date: 2021-04-10 11:25:17 + * @LastEditTime: 2021-04-28 19:50:21 + * @Copyright: HANGZHOU TUYA INFORMATION TECHNOLOGY CO.,LTD + * @Company: http://www.tuya.com + * @Description: The functions that the user needs to actively call are in this file. + */ + +#define TUYA_GLOBAL + +#include +#include +#include "TuyaTools.h" +#include "TuyaDataPoint.h" + +TuyaTools tuya_tools; +TuyaUart tuya_uart; +TuyaDataPoint tuya_dp; + +/* Constants required to report product information */ +unsigned char pid_key[] = {"{\"p\":\""}; +unsigned char mcu_ver_key[] = {"\",\"v\":\""}; +unsigned char mode_key[] = {"\",\"m\":"}; +unsigned char product_info_end[] = {"}"}; + +/* Protocol serial port initialization */ +TuyaWifi::TuyaWifi(void) +{ + tuya_uart.set_serial(&Serial); +} + +TuyaWifi::TuyaWifi(HardwareSerial *serial) +{ + tuya_uart.set_serial(serial); +} + +TuyaWifi::TuyaWifi(SoftwareSerial *serial) +{ + tuya_uart.set_serial(serial); +} + +/** + * @description: Initialize product information + * @param {unsigned char} *pid : Product ID(Create products on the Tuya IoT platform to get) + * @param {unsigned char} *mcu_ver : MCU Software Version Number + * @return {*} + */ +unsigned char TuyaWifi::init(unsigned char *pid, unsigned char *mcu_ver) +{ + if (pid == NULL || mcu_ver == NULL) + { + return ERROR; + } + + if (tuya_tools.my_strlen(pid) <= PID_LEN) + { + tuya_tools.my_memcpy(product_id, pid, tuya_tools.my_strlen(pid)); + } + else + { + tuya_tools.my_memcpy(product_id, pid, PID_LEN); + return ERROR; + } + + if (tuya_tools.my_strlen(mcu_ver) <= VER_LEN) + { + tuya_tools.my_memcpy(mcu_ver_value, mcu_ver, tuya_tools.my_strlen(mcu_ver)); + } + else + { + tuya_tools.my_memcpy(mcu_ver_value, mcu_ver, VER_LEN); + return ERROR; + } + + return SUCCESS; +} + +/** + * @description: Wifi serial port processing service + * @param {*} + * @return {*} + */ +void TuyaWifi::uart_service(void) +{ + unsigned char ret; + static unsigned short rx_in = 0; + unsigned short offset = 0; + unsigned short rx_value_len = 0; + + /* extract serial data */ + while(tuya_uart.available()) { + ret = tuya_uart.uart_receive_input(tuya_uart.read()); + if (ret != SUCCESS) { + break; + } + } + + while ((rx_in < sizeof(tuya_uart.wifi_data_process_buf)) && tuya_uart.with_data_rxbuff() > 0) + { + tuya_uart.wifi_data_process_buf[rx_in++] = tuya_uart.take_byte_rxbuff(); + } + + if (rx_in < PROTOCOL_HEAD) + return; + + while ((rx_in - offset) >= PROTOCOL_HEAD) + { + if (tuya_uart.wifi_data_process_buf[offset + HEAD_FIRST] != FRAME_FIRST) + { + offset++; + continue; + } + + if (tuya_uart.wifi_data_process_buf[offset + HEAD_SECOND] != FRAME_SECOND) + { + offset++; + continue; + } + + if (tuya_uart.wifi_data_process_buf[offset + PROTOCOL_VERSION] != MCU_RX_VER) + { + offset += 2; + continue; + } + + rx_value_len = tuya_uart.wifi_data_process_buf[offset + LENGTH_HIGH] * 0x100; + rx_value_len += (tuya_uart.wifi_data_process_buf[offset + LENGTH_LOW] + PROTOCOL_HEAD); + if (rx_value_len > sizeof(tuya_uart.wifi_data_process_buf) + PROTOCOL_HEAD) + { + offset += 3; + continue; + } + + if ((rx_in - offset) < rx_value_len) + { + break; + } + + //数据接收完成 + if (tuya_tools.get_check_sum((unsigned char *)tuya_uart.wifi_data_process_buf + offset, rx_value_len - 1) != tuya_uart.wifi_data_process_buf[offset + rx_value_len - 1]) + { + //校验出错 + //printf("crc error (crc:0x%X but data:0x%X)\r\n",get_check_sum((unsigned char *)wifi_data_process_buf + offset,rx_value_len - 1),wifi_data_process_buf[offset + rx_value_len - 1]); + offset += 3; + continue; + } + + data_handle(offset); + offset += rx_value_len; + } //end while + + rx_in -= offset; + if (rx_in > 0) + { + tuya_tools.my_memcpy((char *)tuya_uart.wifi_data_process_buf, (const char *)tuya_uart.wifi_data_process_buf + offset, rx_in); + } + +} + +/** + * @description: Data frame processing + * @param {unsigned short} offset : Data start position + * @return {*} + */ +void TuyaWifi::data_handle(unsigned short offset) +{ +#ifdef SUPPORT_MCU_FIRM_UPDATE + unsigned char *firmware_addr = NULL; + static unsigned short firm_size; //Upgrade package size + static unsigned long firm_length; //MCU upgrade file length + static unsigned char firm_update_flag = 0; //MCU upgrade flag + unsigned long dp_len; + unsigned char firm_flag; //Upgrade package size flag +#else + unsigned short dp_len; +#endif + + unsigned char ret; + unsigned short i, total_len; + unsigned char cmd_type = tuya_uart.wifi_data_process_buf[offset + FRAME_TYPE]; + +#if ((defined VOICE_MODULE_PROTOCOL_ENABLE) || (defined BLE_RELATED_FUNCTION_ENABLE) || (defined MODULE_EXPANDING_SERVICE_ENABLE) || \ + (defined IR_TX_RX_TEST_ENABLE) || (defined GET_IR_STATUS_ENABLE) || (defined MCU_DP_UPLOAD_SYN) || (defined GET_WIFI_STATUS_ENABLE) || \ + (defined WIFI_CONNECT_TEST_ENABLE) || (defined WIFI_STREAM_ENABLE) || (defined WIFI_TEST_ENABLE)) + unsigned char result; +#endif + +#ifdef WEATHER_ENABLE + static unsigned char isWoSend = 0; //Whether the weather data has been opened, 0:no 1:yes +#endif + +#ifdef WIFI_TEST_ENABLE + unsigned char rssi; +#endif + +#ifdef FILE_DOWNLOAD_ENABLE + unsigned char *file_data_addr = NULL; + static unsigned short file_package_size = 0; //File packet size + static unsigned char file_download_flag = 0; //File download flag + unsigned int file_download_size = 0; +#endif + + switch (cmd_type) + { + case HEAT_BEAT_CMD: //Heartbeat package + heat_beat_check(); + break; + + case PRODUCT_INFO_CMD: //Product information + product_info_update(); + break; + + case WORK_MODE_CMD: //Query the module working mode set by the MCU + get_mcu_wifi_mode(); + break; + +#ifndef WIFI_CONTROL_SELF_MODE + case WIFI_STATE_CMD: //Wifi working status + wifi_work_state = tuya_uart.wifi_data_process_buf[offset + DATA_START]; + tuya_uart.wifi_uart_write_frame(WIFI_STATE_CMD, MCU_TX_VER, 0); +#ifdef WEATHER_ENABLE + if (wifi_work_state == WIFI_CONNECTED && isWoSend == 0) //When the WIFI connection is successful, open the weather data only once + { + mcu_open_weather(); + isWoSend = 1; + } +#endif + break; + + case WIFI_RESET_CMD: //Reset wifi + reset_wifi_flag = RESET_WIFI_SUCCESS; + break; + + case WIFI_MODE_CMD: //Select smartconfig/AP mode + set_wifimode_flag = SET_WIFICONFIG_SUCCESS; + break; +#endif + + case DATA_QUERT_CMD: //Order send + total_len = (tuya_uart.wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | tuya_uart.wifi_data_process_buf[offset + LENGTH_LOW]; + + for (i = 0; i < total_len;) + { + dp_len = tuya_uart.wifi_data_process_buf[offset + DATA_START + i + 2] * 0x100; + dp_len += tuya_uart.wifi_data_process_buf[offset + DATA_START + i + 3]; + // + ret = data_point_handle((unsigned char *)tuya_uart.wifi_data_process_buf + offset + DATA_START + i); + + if (SUCCESS == ret) + { + //Send success + } + else + { + //Send fault + } + + i += (dp_len + 4); + } + break; + + case STATE_QUERY_CMD: //Status query + all_data_update(); + break; + +#ifdef SUPPORT_MCU_FIRM_UPDATE + case UPDATE_START_CMD: //Upgrade start + //Get global variable of upgrade package size + firm_flag = PACKAGE_SIZE; + if (firm_flag == 0) + { + firm_size = 256; + } + else if (firm_flag == 1) + { + firm_size = 512; + } + else if (firm_flag == 2) + { + firm_size = 1024; + } + + firm_length = wifi_data_process_buf[offset + DATA_START]; + firm_length <<= 8; + firm_length |= wifi_data_process_buf[offset + DATA_START + 1]; + firm_length <<= 8; + firm_length |= wifi_data_process_buf[offset + DATA_START + 2]; + firm_length <<= 8; + firm_length |= wifi_data_process_buf[offset + DATA_START + 3]; + + upgrade_package_choose(PACKAGE_SIZE); + firm_update_flag = UPDATE_START_CMD; + break; + + case UPDATE_TRANS_CMD: //Upgrade transfer + if (firm_update_flag == UPDATE_START_CMD) + { + //Stop all data reporting + stop_update_flag = ENABLE; + + total_len = (wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | wifi_data_process_buf[offset + LENGTH_LOW]; + + dp_len = wifi_data_process_buf[offset + DATA_START]; + dp_len <<= 8; + dp_len |= wifi_data_process_buf[offset + DATA_START + 1]; + dp_len <<= 8; + dp_len |= wifi_data_process_buf[offset + DATA_START + 2]; + dp_len <<= 8; + dp_len |= wifi_data_process_buf[offset + DATA_START + 3]; + + firmware_addr = (unsigned char *)wifi_data_process_buf; + firmware_addr += (offset + DATA_START + 4); + + if ((total_len == 4) && (dp_len == firm_length)) + { + //Last pack + ret = mcu_firm_update_handle(firmware_addr, dp_len, 0); + firm_update_flag = 0; + } + else if ((total_len - 4) <= firm_size) + { + ret = mcu_firm_update_handle(firmware_addr, dp_len, total_len - 4); + } + else + { + firm_update_flag = 0; + ret = ERROR; + } + + if (ret == SUCCESS) + { + wifi_uart_write_frame(UPDATE_TRANS_CMD, MCU_TX_VER, 0); + } + //Restore all data reported + stop_update_flag = DISABLE; + } + break; +#endif + +#ifdef SUPPORT_GREEN_TIME + case GET_ONLINE_TIME_CMD: //Get system time (Greenwich Mean Time) + mcu_get_greentime((unsigned char *)(wifi_data_process_buf + offset + DATA_START)); + break; +#endif + +#ifdef SUPPORT_MCU_RTC_CHECK + case GET_LOCAL_TIME_CMD: //Get local time + mcu_write_rtctime((unsigned char *)(wifi_data_process_buf + offset + DATA_START)); + break; +#endif + +#ifdef WIFI_TEST_ENABLE + case WIFI_TEST_CMD: //Wifi function test + result = wifi_data_process_buf[offset + DATA_START]; + rssi = wifi_data_process_buf[offset + DATA_START + 1]; + wifi_test_result(result, rssi); + break; +#endif + +#ifdef WEATHER_ENABLE + case WEATHER_OPEN_CMD: //Turn on the weather + weather_open_return_handle(wifi_data_process_buf[offset + DATA_START], wifi_data_process_buf[offset + DATA_START + 1]); + break; + + case WEATHER_DATA_CMD: //Weather data + total_len = (wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | wifi_data_process_buf[offset + LENGTH_LOW]; + weather_data_raw_handle((unsigned char *)wifi_data_process_buf + offset + DATA_START, total_len); + break; +#endif + +#ifdef WIFI_STREAM_ENABLE + case STREAM_TRANS_CMD: //Stream data transmission + stream_status = wifi_data_process_buf[offset + DATA_START]; //Service transmission back to reception + stream_trans_send_result(stream_status); + break; + + case MAPS_STREAM_TRANS_CMD: //streams trans(Support for multiple maps) + maps_stream_status = wifi_data_process_buf[offset + DATA_START]; //Service transmission back to reception + maps_stream_trans_send_result(maps_stream_status); + break; +#endif + +#ifdef WIFI_CONNECT_TEST_ENABLE + case WIFI_CONNECT_TEST_CMD: //Wifi function test(connection designated route) + result = wifi_data_process_buf[offset + DATA_START]; + wifi_connect_test_result(result); + break; +#endif + +#ifdef GET_MODULE_MAC_ENABLE + case GET_MAC_CMD: //Get module mac + mcu_get_mac((unsigned char *)(wifi_data_process_buf + offset + DATA_START)); + break; +#endif + +#ifdef GET_WIFI_STATUS_ENABLE + case GET_WIFI_STATUS_CMD: //Gets the wifi networking status + result = wifi_data_process_buf[offset + DATA_START]; + get_wifi_status(result); + break; +#endif + +#ifdef MCU_DP_UPLOAD_SYN + case STATE_UPLOAD_SYN_RECV_CMD: //Status upload results(synchronization) + result = wifi_data_process_buf[offset + DATA_START]; + get_upload_syn_result(result); + break; +#endif + +#ifdef GET_IR_STATUS_ENABLE + case GET_IR_STATUS_CMD: //IR status notification + result = wifi_data_process_buf[offset + DATA_START]; + get_ir_status(result); + break; +#endif + +#ifdef IR_TX_RX_TEST_ENABLE + case IR_TX_RX_TEST_CMD: //IR into send-receive test + result = wifi_data_process_buf[offset + DATA_START]; + ir_tx_rx_test_result(result); + break; +#endif + +#ifdef FILE_DOWNLOAD_ENABLE + case FILE_DOWNLOAD_START_CMD: //File download startup + //Get file package size selection + if (FILE_DOWNLOAD_PACKAGE_SIZE == 0) + { + file_package_size = 256; + } + else if (FILE_DOWNLOAD_PACKAGE_SIZE == 1) + { + file_package_size = 512; + } + else if (FILE_DOWNLOAD_PACKAGE_SIZE == 2) + { + file_package_size = 1024; + } + + file_download_size = wifi_data_process_buf[offset + DATA_START]; + file_download_size = (file_download_size << 8) | wifi_data_process_buf[offset + DATA_START + 1]; + file_download_size = (file_download_size << 8) | wifi_data_process_buf[offset + DATA_START + 2]; + file_download_size = (file_download_size << 8) | wifi_data_process_buf[offset + DATA_START + 3]; + + file_download_package_choose(FILE_DOWNLOAD_PACKAGE_SIZE); + file_download_flag = FILE_DOWNLOAD_START_CMD; + break; + + case FILE_DOWNLOAD_TRANS_CMD: //File download data transfer + if (file_download_flag == FILE_DOWNLOAD_START_CMD) + { + total_len = (wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | wifi_data_process_buf[offset + LENGTH_LOW]; + + dp_len = wifi_data_process_buf[offset + DATA_START]; + dp_len <<= 8; + dp_len |= wifi_data_process_buf[offset + DATA_START + 1]; + dp_len <<= 8; + dp_len |= wifi_data_process_buf[offset + DATA_START + 2]; + dp_len <<= 8; + dp_len |= wifi_data_process_buf[offset + DATA_START + 3]; + + file_data_addr = (unsigned char *)wifi_data_process_buf; + file_data_addr += (offset + DATA_START + 4); + + if ((total_len == 4) && (dp_len == file_download_size)) + { + //Last pack + ret = file_download_handle(file_data_addr, dp_len, 0); + file_download_flag = 0; + } + else if ((total_len - 4) <= file_package_size) + { + ret = file_download_handle(file_data_addr, dp_len, total_len - 4); + } + else + { + file_download_flag = 0; + ret = ERROR; + } + + if (ret == SUCCESS) + { + wifi_uart_write_frame(FILE_DOWNLOAD_TRANS_CMD, MCU_TX_VER, 0); + } + } + break; +#endif + +#ifdef MODULE_EXPANDING_SERVICE_ENABLE + case MODULE_EXTEND_FUN_CMD: //Module expansion service + total_len = (wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | wifi_data_process_buf[offset + LENGTH_LOW]; + open_module_time_serve_result((unsigned char *)(wifi_data_process_buf + offset + DATA_START), total_len); + break; +#endif + +#ifdef BLE_RELATED_FUNCTION_ENABLE + case BLE_TEST_CMD: //Bluetooth functional test(Scan designated bluetooth beacon) + total_len = (wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | wifi_data_process_buf[offset + LENGTH_LOW]; + BLE_test_result((unsigned char *)(wifi_data_process_buf + offset + DATA_START), total_len); + break; +#endif + +#ifdef VOICE_MODULE_PROTOCOL_ENABLE + case GET_VOICE_STATE_CMD: //Gets the voice status code + result = wifi_data_process_buf[offset + DATA_START]; + get_voice_state_result(result); + break; + case MIC_SILENCE_CMD: //MIC mute Settings + result = wifi_data_process_buf[offset + DATA_START]; + set_voice_MIC_silence_result(result); + break; + case SET_SPEAKER_VOLUME_CMD: //speaker volume set + result = wifi_data_process_buf[offset + DATA_START]; + set_speaker_voice_result(result); + break; + case VOICE_TEST_CMD: //Audio production test + result = wifi_data_process_buf[offset + DATA_START]; + voice_test_result(result); + break; + case VOICE_AWAKEN_TEST_CMD: //Wake up production test + result = wifi_data_process_buf[offset + DATA_START]; + voice_awaken_test_result(result); + break; + case VOICE_EXTEND_FUN_CMD: //Voice module extension function + total_len = (wifi_data_process_buf[offset + LENGTH_HIGH] << 8) | wifi_data_process_buf[offset + LENGTH_LOW]; + voice_module_extend_fun((unsigned char *)(wifi_data_process_buf + offset + DATA_START), total_len); + break; +#endif + + default: + break; + } +} + + +/** + * @description: Input product All DP ID, Type, total number of DPs + * @param {unsigned char} dp_cmd_array : DP array. array[][0] : DP ID, + * array[][1] : DP Type(DP_TYPE_RAW, DP_TYPE_BOOL, DP_TYPE_VALUE, DP_TYPE_STRING, DP_TYPE_ENUM, DP_TYPE_BITMAP) + * @param {unsigned char} dp_cmd_num : total number of DPs + * @return {*} + */ +void TuyaWifi::set_dp_cmd_total(unsigned char dp_cmd_array[][2], unsigned char dp_cmd_num) +{ + download_dp_number = dp_cmd_num; + download_cmd = dp_cmd_array; +} + +/** + * @description: Get the serial number of the DPID in the array. + * @param {unsigned char} dpid + * @return {unsigned char} index : The index of the input dpid in the array + */ +unsigned char TuyaWifi::get_dowmload_dpid_index(unsigned char dpid) +{ + unsigned char index; + + for (index = 0; index < download_dp_number; index++) + { + if (download_cmd[index][0] == dpid) + { + break; + } + } + return index; +} + +/** + * @description: Delivery data processing + * @param {const unsigned char} value : Send data source pointer + * @return Return data processing result + */ +unsigned char TuyaWifi::data_point_handle(const unsigned char value[]) +{ + unsigned char dp_id, index; + unsigned char dp_type; + unsigned char ret; + unsigned short dp_len; + + dp_id = value[0]; + dp_type = value[1]; + dp_len = value[2] * 0x100; + dp_len += value[3]; + + index = get_dowmload_dpid_index(dp_id); + + if (dp_type != download_cmd[index][1]) + { + //Error message + return FALSE; + } + else + { + ret = dp_download_handle(dp_id, value + 4, dp_len); + } + + return ret; +} + +/** + * @description: DP command processing callback function + * @param {tuya_callback_dp_download} _func + * @return {*} + */ +void TuyaWifi::dp_process_func_register(tuya_callback_dp_download _func) +{ + dp_download_handle = _func; +} + +/** + * @description: Reply to the current device status callback function + * @param {tuya_callback_dp_update_all} _func + * @return {*} + */ +void TuyaWifi::dp_update_all_func_register(tuya_callback_dp_update_all _func) +{ + all_data_update = _func; +} + +/** + * @description: Heartbeat packet detection + * @param {*} + * @return {*} + */ +void TuyaWifi::heat_beat_check(void) +{ + unsigned char length = 0; + static unsigned char mcu_reset_state = FALSE; + + if (FALSE == mcu_reset_state) + { + length = tuya_uart.set_wifi_uart_byte(length, FALSE); + mcu_reset_state = TRUE; + } + else + { + length = tuya_uart.set_wifi_uart_byte(length, TRUE); + } + + tuya_uart.wifi_uart_write_frame(HEAT_BEAT_CMD, MCU_TX_VER, length); +} + +/** + * @description: Product information upload + * @param {*} + * @return {*} + */ +void TuyaWifi::product_info_update(void) +{ + unsigned char length = 0; + +#if ((defined CONFIG_MODE_DELAY_TIME) || (defined CONFIG_MODE_CHOOSE) || (defined ENABLE_MODULE_IR_FUN) || (defined LONG_CONN_LOWPOWER)) + unsigned char str[10] = {0}; +#endif + + length = tuya_uart.set_wifi_uart_buffer(length, pid_key, (unsigned short)(tuya_tools.my_strlen(pid_key))); + length = tuya_uart.set_wifi_uart_buffer(length, product_id, PID_LEN); + length = tuya_uart.set_wifi_uart_buffer(length, mcu_ver_key, (unsigned short)(tuya_tools.my_strlen(mcu_ver_key))); + length = tuya_uart.set_wifi_uart_buffer(length, mcu_ver_value, VER_LEN); + length = tuya_uart.set_wifi_uart_buffer(length, mode_key, (unsigned short)(tuya_tools.my_strlen(mode_key))); + length = tuya_uart.set_wifi_uart_buffer(length, (const unsigned char *)CONFIG_MODE, (unsigned short)(tuya_tools.my_strlen((unsigned char *)CONFIG_MODE))); + +#ifdef CONFIG_MODE_DELAY_TIME + sprintf((char *)str, ",\"mt\":%d", CONFIG_MODE_DELAY_TIME); + length = tuya_uart.set_wifi_uart_buffer(length, str, tuya_tools.my_strlen(str)); +#endif +#ifdef CONFIG_MODE_CHOOSE + sprintf((char *)str, ",\"n\":%d", CONFIG_MODE_CHOOSE); + length = tuya_uart.set_wifi_uart_buffer(length, str, tuya_tools.my_strlen(str)); +#endif +#ifdef ENABLE_MODULE_IR_FUN + sprintf((char *)str, ",\"ir\":\"%d.%d\"", MODULE_IR_PIN_TX, MODULE_IR_PIN_RX); + length = tuya_uart.set_wifi_uart_buffer(length, str, tuya_tools.my_strlen(str)); +#endif +#ifdef LONG_CONN_LOWPOWER + sprintf((char *)str, ",\"low\":%d", LONG_CONN_LOWPOWER); + length = tuya_uart.set_wifi_uart_buffer(length, str, tuya_tools.my_strlen(str)); +#endif + + length = tuya_uart.set_wifi_uart_buffer(length, product_info_end, tuya_tools.my_strlen(product_info_end)); + + tuya_uart.wifi_uart_write_frame(PRODUCT_INFO_CMD, MCU_TX_VER, length); +} + +/** + * @description: Query the working mode of mcu and wifi + * @param {*} + * @return {*} + */ +void TuyaWifi::get_mcu_wifi_mode(void) +{ + unsigned char length = 0; + +#ifdef WIFI_CONTROL_SELF_MODE //Module self-processing + length = tuya_uart.set_wifi_uart_byte(length, WF_STATE_KEY); + length = tuya_uart.set_wifi_uart_byte(length, WF_RESERT_KEY); +#else + //No need to process data +#endif + + tuya_uart.wifi_uart_write_frame(WORK_MODE_CMD, MCU_TX_VER, length); +} + +/** + * @description: mcu gets bool,value,enum type to send dp value. (raw, string type needs to be handled at the user's discretion. fault only report) + * @param {unsigned char} dpid : data point ID + * @param {const unsigned char} value : dp data buffer address + * @param {unsigned short} len : data length + * @return {unsigned char} Parsed data + */ +unsigned long TuyaWifi::mcu_get_dp_download_data(unsigned char dpid, const unsigned char value[], unsigned short len) +{ + unsigned long ret; + switch (download_cmd[get_dowmload_dpid_index(dpid)][1]) + { + case DP_TYPE_BOOL: + ret = tuya_dp.mcu_get_dp_download_bool(value, len); + break; + + case DP_TYPE_VALUE: + ret = tuya_dp.mcu_get_dp_download_value(value, len); + break; + + case DP_TYPE_ENUM: + ret = tuya_dp.mcu_get_dp_download_enum(value, len); + break; + + default: + break; + } + return ret; +} + +/** + * @description: dp data upload + * @param {unsigned char} dpid + * @param {const unsigned char} value + * @param {unsigned short} len + * @return {*} + */ +unsigned char TuyaWifi::mcu_dp_update(unsigned char dpid, const unsigned char value[], unsigned short len) +{ + unsigned char ret; + switch (download_cmd[get_dowmload_dpid_index(dpid)][1]) + { + case DP_TYPE_RAW: + ret = tuya_dp.mcu_dp_raw_update(dpid, value, len); + break; + + case DP_TYPE_BOOL: + ret = tuya_dp.mcu_dp_bool_update(dpid, *value); + break; + + case DP_TYPE_VALUE: + ret = tuya_dp.mcu_dp_value_update(dpid, *value); + break; + + case DP_TYPE_STRING: + ret = tuya_dp.mcu_dp_string_update(dpid, value, len); + break; + + case DP_TYPE_ENUM: + ret = tuya_dp.mcu_dp_enum_update(dpid, *value); + break; + + case DP_TYPE_BITMAP: + ret = tuya_dp.mcu_dp_fault_update(dpid, *value); + break; + + + default: + break; + } + return ret; +} + +unsigned char TuyaWifi::mcu_dp_update(unsigned char dpid, unsigned char value, unsigned short len) +{ + unsigned char ret; + switch (download_cmd[get_dowmload_dpid_index(dpid)][1]) + { + case DP_TYPE_BOOL: + ret = tuya_dp.mcu_dp_bool_update(dpid, value); + break; + + case DP_TYPE_ENUM: + ret = tuya_dp.mcu_dp_enum_update(dpid, value); + break; + + case DP_TYPE_VALUE: + ret = tuya_dp.mcu_dp_value_update(dpid, value); + break; + + case DP_TYPE_BITMAP: + ret = tuya_dp.mcu_dp_fault_update(dpid, value); + break; + + default: + break; + } + return ret; +} + +unsigned char TuyaWifi::mcu_dp_update(unsigned char dpid, char value, unsigned short len) +{ + unsigned char ret; + switch (download_cmd[get_dowmload_dpid_index(dpid)][1]) + { + case DP_TYPE_BOOL: + ret = tuya_dp.mcu_dp_bool_update(dpid, value); + break; + + case DP_TYPE_ENUM: + ret = tuya_dp.mcu_dp_enum_update(dpid, value); + break; + + case DP_TYPE_VALUE: + ret = tuya_dp.mcu_dp_value_update(dpid, value); + break; + + case DP_TYPE_BITMAP: + ret = tuya_dp.mcu_dp_fault_update(dpid, value); + break; + + default: + break; + } + return ret; +} + +unsigned char TuyaWifi::mcu_dp_update(unsigned char dpid, unsigned long value, unsigned short len) +{ + unsigned char ret; + switch (download_cmd[get_dowmload_dpid_index(dpid)][1]) + { + case DP_TYPE_BOOL: + ret = tuya_dp.mcu_dp_bool_update(dpid, value); + break; + + case DP_TYPE_ENUM: + ret = tuya_dp.mcu_dp_enum_update(dpid, value); + break; + + case DP_TYPE_VALUE: + ret = tuya_dp.mcu_dp_value_update(dpid, value); + break; + + case DP_TYPE_BITMAP: + ret = tuya_dp.mcu_dp_fault_update(dpid, value); + break; + + default: + break; + } + return ret; +} + +unsigned char TuyaWifi::mcu_dp_update(unsigned char dpid, long value, unsigned short len) +{ + unsigned char ret; + switch (download_cmd[get_dowmload_dpid_index(dpid)][1]) + { + case DP_TYPE_BOOL: + ret = tuya_dp.mcu_dp_bool_update(dpid, value); + break; + + case DP_TYPE_ENUM: + ret = tuya_dp.mcu_dp_enum_update(dpid, value); + break; + + case DP_TYPE_VALUE: + ret = tuya_dp.mcu_dp_value_update(dpid, value); + break; + + case DP_TYPE_BITMAP: + ret = tuya_dp.mcu_dp_fault_update(dpid, value); + break; + + default: + break; + } + return ret; +} + +unsigned char TuyaWifi::mcu_dp_update(unsigned char dpid, unsigned int value, unsigned short len) +{ + unsigned char ret; + switch (download_cmd[get_dowmload_dpid_index(dpid)][1]) + { + case DP_TYPE_BOOL: + ret = tuya_dp.mcu_dp_bool_update(dpid, value); + break; + + case DP_TYPE_ENUM: + ret = tuya_dp.mcu_dp_enum_update(dpid, value); + break; + + case DP_TYPE_VALUE: + ret = tuya_dp.mcu_dp_value_update(dpid, value); + break; + + case DP_TYPE_BITMAP: + ret = tuya_dp.mcu_dp_fault_update(dpid, value); + break; + + default: + break; + } + return ret; +} + +unsigned char TuyaWifi::mcu_dp_update(unsigned char dpid, int value, unsigned short len) +{ + unsigned char ret; + switch (download_cmd[get_dowmload_dpid_index(dpid)][1]) + { + case DP_TYPE_BOOL: + ret = tuya_dp.mcu_dp_bool_update(dpid, value); + break; + + case DP_TYPE_ENUM: + ret = tuya_dp.mcu_dp_enum_update(dpid, value); + break; + + case DP_TYPE_VALUE: + ret = tuya_dp.mcu_dp_value_update(dpid, value); + break; + + case DP_TYPE_BITMAP: + ret = tuya_dp.mcu_dp_fault_update(dpid, value); + break; + + default: + break; + } + return ret; +} + + + +/** + * @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) +{ + unsigned char length = 0; + + set_wifimode_flag = SET_WIFICONFIG_ERROR; + + length = tuya_uart.set_wifi_uart_byte(length, mode); + + tuya_uart.wifi_uart_write_frame(WIFI_MODE_CMD, MCU_TX_VER, length); +} + +/** + * @description: The MCU actively obtains the current wifi working status. + * @param {*} + * @return {unsigned char} wifi work state + * SMART_CONFIG_STATE:smartconfig config status + * AP_STATE:AP config status + * WIFI_NOT_CONNECTED:WIFI configuration succeeded but not connected to the router + * WIFI_CONNECTED:WIFI configuration is successful and connected to the router + * WIFI_CONN_CLOUD:WIFI is connected to the cloud server + * WIFI_LOW_POWER:WIFI is in low power mode + * SMART_AND_AP_STATE: WIFI smartconfig&AP mode + * @note 1:If the module is in self-processing mode, the MCU does not need to call this function. + */ +unsigned char TuyaWifi::mcu_get_wifi_work_state(void) +{ + return wifi_work_state; +} + + +/** + * @description: MCU actively resets wifi working mode + * @param {*} + * @return {*} + * @note 1:The MCU actively calls to obtain whether the reset wifi is successful through the mcu_get_reset_wifi_flag() function. + * 2:If the module is in self-processing mode, the MCU does not need to call this function. + */ +void TuyaWifi::mcu_reset_wifi(void) +{ + reset_wifi_flag = RESET_WIFI_ERROR; + + tuya_uart.wifi_uart_write_frame(WIFI_RESET_CMD, MCU_TX_VER, 0); +} diff --git a/src/TuyaWifi.h b/src/TuyaWifi.h new file mode 100755 index 0000000..46a83a7 --- /dev/null +++ b/src/TuyaWifi.h @@ -0,0 +1,96 @@ +/* + * @FileName: Tuya.h + * @Author: Tuya + * @Email: + * @LastEditors: Tuya + * @Date: 2021-04-10 11:25:26 + * @LastEditTime: 2021-04-28 19:47:50 + * @Copyright: HANGZHOU TUYA INFORMATION TECHNOLOGY CO.,LTD + * @Company: http://www.tuya.com + * @Description: + */ +#ifndef __TUYA_H__ +#define __TUYA_H__ + +#include "../config.h" +#include "TuyaDefs.h" +#include "TuyaUart.h" + +#ifdef TUYA_GLOBAL +#define TUYA_GLOBAL_EXTERN +#else +#define TUYA_GLOBAL_EXTERN extern +#endif + +#ifndef TUYA_GLOBAL +extern TuyaUart tuya_uart; +#endif + +#define PID_LEN 16 +#define VER_LEN 5 + +TUYA_GLOBAL_EXTERN volatile unsigned char stop_update_flag; //ENABLE:Stop all data uploads DISABLE:Restore all data uploads + +#ifndef WIFI_CONTROL_SELF_MODE +TUYA_GLOBAL_EXTERN volatile unsigned char reset_wifi_flag; //Reset wifi flag (TRUE: successful / FALSE: failed) +TUYA_GLOBAL_EXTERN volatile unsigned char set_wifimode_flag; //Set the WIFI working mode flag (TRUE: Success / FALSE: Failed) +TUYA_GLOBAL_EXTERN volatile unsigned char wifi_work_state; //Wifi module current working status +#endif + +extern "C" +{ + typedef void (*tuya_callback_dp_update_all)(void); + typedef unsigned char (*tuya_callback_dp_download)(unsigned char dpid, const unsigned char value[], unsigned short length); +} + +class TuyaWifi +{ +public: + TuyaWifi(void); + TuyaWifi(HardwareSerial *serial); + TuyaWifi(SoftwareSerial *serial); + + unsigned char init(unsigned char *pid, unsigned char *mcu_ver); + void uart_service(void); + + void dp_process_func_register(tuya_callback_dp_download _func); + void dp_update_all_func_register(tuya_callback_dp_update_all _func); + + void set_dp_cmd_total(unsigned char download_cmd_array[][2], unsigned char download_cmd_num); + + unsigned long mcu_get_dp_download_data(unsigned char dpid, const unsigned char value[], unsigned short len); + + /* 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); + + void mcu_set_wifi_mode(unsigned char mode); + unsigned char mcu_get_wifi_work_state(void); + void mcu_reset_wifi(void); + +private: + unsigned char product_id[PID_LEN]; + unsigned char mcu_ver_value[VER_LEN]; + + unsigned char download_dp_number; + unsigned char (*download_cmd)[2]; + + tuya_callback_dp_download dp_download_handle; + tuya_callback_dp_update_all all_data_update; + void data_handle(unsigned short offset); + void heat_beat_check(void); + void product_info_update(void); + void get_mcu_wifi_mode(void); + unsigned char data_point_handle(const unsigned char value[]); + unsigned char get_dowmload_dpid_index(unsigned char dpid); +}; + +#endif /* __TUYA_H__ */