快速入门

更新时间:2022-11-24 09:20:04下载pdf

本文档介绍了如何在涂鸦 IoT 开发平台上创建网关产品,并应用综合 SDK 构建一个最简版本的网关设备,把它接入到涂鸦生态。

创建产品

在涂鸦 IoT 开发平台创建网关产品是开发的第一步,是其他步骤的前置条件。本小节将会演示在涂鸦 IoT 开发平台上创建一个网关产品。

本小节我们将会在涂鸦 IoT 开发平台上创建一个网关产品。

  1. 登录 涂鸦 IoT 开发平台

    未注册的用户,需要先注册账户。

  2. 在平台首页,单击 创建产品

    快速入门

  3. 在产品品类中,单击 网关中控 品类,然后选择 网关

    快速入门

  4. 智能化方式选择 产品开发

    快速入门

  5. 根据实际需求选择产品方案,使用涂鸦模组选择 扩展SDK,不使用涂鸦模组选择 联网SDK

    快速入门

  6. 完善产品信息,填写产品名称和产品型号后,单击 创建产品

    快速入门

  7. 创建产品完成后,会弹框让我们添加标准功能点,后面步骤会介绍如何添加功能点,所以这里直接点击 确定 进入下一步。

    快速入门

  8. 进入产品主页,我们将会看到涂鸦平台已经给产品分配了一个 PID,也称产品 ID。

    快速入门

  9. 点击 功能定义 选项卡,在 功能定义 页面可以给产品添加标准功能或自定义功能,可以按需添加。关于功能点说明,请参考 标准功能说明自定义功能

    快速入门

  10. 点击 设备面板 选项卡,在 设备面板 页面选择 APP 面板,点击 公版面板,挑选合适的面板,点击 使用此模板。关于 APP 面板更多说明,请参考 配置 App 界面

    快速入门

  11. 点击 硬件开发 选项卡,在 硬件开发 页面选择云端接入硬件和获取授权码。

    这里以 Ubuntu 平台为例,云端接入硬件 选择 通用CPU,接着点击 免费领取2个激活码,下单后即可免费领取2个激活码用来调试。

    激活码必需是一机一对,不能重复使用。免费领取的激活码仅用于调试目的,正式产品的激活码需要联系涂鸦商务购买。

    快速入门

至此,网关产品已创建完成。

获取开发包

可以从涂鸦 GitHub 上获取 综合 SDK,如果没有您需要的工具链,请联系您的涂鸦技术支持工程师。

开发向导

本小节我们将会从零开始编码实现一个最简版本的网关设备,并且把它接入到涂鸦平台。

基础模型

最简模型是指基于 SDK 搭建一个最简版本的网关产品所需要的接口,也构成了应用代码主结构,接口的调用关系如下图所示。

快速入门

其中,service initservice start 可以是涂鸦公共业务,也可以是开发者私有业务。

新建工程

应用代码要求放在开发包的 apps 目录下,每个工程都是独立的文件夹,因此,我们在 <开发包路径>/apps 目录下新建一个名称为 tuyaos_demo_mini_gw 文件夹作为我们的示例工程。

编写Makefile

tuyaos_demo_mini_gw 目录下新建一个 Makefile 文件,以下是参考模板,直接拷贝到 Makefile 文件中。

ROOT_DIR        ?= $(abspath ../../)
COMPILE_PREX    ?=
USER_LINK_FLAGS ?=

-include ./build/build_param

AR         = $(COMPILE_PREX)ar
CC         = $(COMPILE_PREX)gcc
NM         = $(COMPILE_PREX)nm
CPP        = $(COMPILE_PREX)g++
OBJCOPY    = $(COMPILE_PREX)objcopy
OBJDUMP    = $(COMPILE_PREX)objdump
APP_PACK   = ./build/pack.sh

LINKFLAGS  = -L$(ROOT_DIR)/sdk/lib \
             -lty_iot_sdk \
             -lty_module_gw_base \
             -lpthread -lm
LINKFLAGS += $(USER_LINK_FLAGS)
LINKFLAGS := -Wl,--start-group $(LINKFLAGS) -Wl,--end-group

CCFLAGS    = -g -fPIC -Werror=unused-function

DEFINES    = -DAPP_BIN_NAME=\"$(APP_BIN_NAME)\" \
             -DUSER_SW_VER=\"$(USER_SW_VER)\"

CFLAGS     = $(CCFLAGS) $(DEFINES) $(USER_INCS) $(USER_CFLAGS)

# 输出变量
OUTPUT_DIR      = $(ROOT_DIR)/output/$(APP_BIN_NAME)_$(USER_SW_VER)
OUTPUT_DIR_OBJS = $(OUTPUT_DIR)/.objs

# 编译变量
USER_SRC_BASE_DIR  = src

USER_INC_BASE_DIR  = include
USER_INC_BASE_DIR += $(shell find $(ROOT_DIR)/sdk -name include -type d)

# 编译文件
USER_SRC_DIRS      = $(shell find $(USER_SRC_BASE_DIR) -type d)
USER_SRCS         += $(foreach dir, $(USER_SRC_DIRS), $(wildcard $(dir)/*.c)) 
USER_SRCS         += $(foreach dir, $(USER_SRC_DIRS), $(wildcard $(dir)/*.cpp)) 
USER_SRCS         += $(foreach dir, $(USER_SRC_DIRS), $(wildcard $(dir)/*.s)) 
USER_SRCS         += $(foreach dir, $(USER_SRC_DIRS), $(wildcard $(dir)/*.S)) 

USER_INCS          = $(addprefix -I ,  $(shell find $(USER_INC_BASE_DIR) -type d) )
USER_OBJS          = $(addsuffix .o, $(USER_SRCS))
USER_OBJS_OUT      = $(addprefix $(OUTPUT_DIR_OBJS)/, $(USER_OBJS))

all: pack

pack: build_app
ifeq ($(APP_PACK),$(wildcard $(APP_PACK)))
	sh $(APP_PACK) $(OUTPUT_DIR) $(ROOT_DIR) $(APP_BIN_NAME) $(USER_SW_VER) $(COMPILE_PREX)
endif

build_app: $(USER_OBJS_OUT)
	$(CC) $(USER_OBJS_OUT) $(CFLAGS) $(LINKFLAGS) -o $(OUTPUT_DIR)/$(APP_BIN_NAME)
	@echo "Build APP Finish"

$(OUTPUT_DIR_OBJS)/%.c.o: %.c
	@mkdir -p $(dir $@);
	$(CC) $(CFLAGS) -o $@ -c $<

$(OUTPUT_DIR_OBJS)/%.cpp.o: %.cpp
	@mkdir -p $(dir $@);
	$(CC) $(CFLAGS) -o $@ -c $<

$(OUTPUT_DIR_OBJS)/%.s.o: %.s
	@mkdir -p $(dir $@);
	$(CC) $(CFLAGS) -o $@ -c $<

$(OUTPUT_DIR_OBJS)/%.S.o: %.S
	@mkdir -p $(dir $@);
	$(CC) $(CFLAGS) -D__ASSEMBLER__ -o $@ -c $<


.PHONY: all clean SHOWARGS build_app pack
clean:
	rm -rf $(OUTPUT_DIR)

编码代码

tuyaos_demo_mini_gw 目录下新建一个 src 子文件夹,存放我们的源代码文件,并且在 src 目录下新建一个 main.c 文件。

  1. 引入必要的头文件。

    #include <unistd.h>
    
    #include "uni_log.h"
    #include "base_os_adapter.h"
    #include "tuya_iot_base_api.h"
    #include "tuya_iot_com_api.h"
    
    #include "tuya_iot_sdk_api.h"
    #include "tuya_iot_sdk_defs.h"
    
    #if defined(TY_BT_MOD) && (TY_BT_MOD == 1)
    #include "tuya_os_adapt_bt.h"
    #endif
    
  2. 我们把在 创建产品 章节创建的网关产品 ID 以及授权码定义成宏。

    #define PID       "fljmamufiym5fktz"                  // 替换成自己的产品 ID
    #define UUID      "tuya461dbc63aeeb991f"              // 替换成自己的 UUID
    #define AUTHKEY   "c8X4PR4wx1gMFaQlaZu5dfgVvVRwB8Ug"  // 替换成自己的 AUTHKEY
    
  3. 按照主程序代码结构框图,转化成代码,编写到 main 函数中。

    int main(int argc, char **argv)
    {
        /* 如果 SDK 支持蓝牙配网,必须最先调用蓝牙注册接口,否则启动失败 */
    #if defined(TY_BT_MOD) && (TY_BT_MOD == 1)
        tuya_os_adapt_reg_bt_intf();
    #endif
    
        /* OS层初始化 */
        tuya_os_intf_init();
    
        /* IoT层初始化 */
        tuya_iot_init("./");
    
        /* 设置授权信息 */
        prod_info.uuid     = UUID;
        prod_info.auth_key = AUTHKEY;
        tuya_iot_set_gw_prod_info(&prod_info));
    
        /* SDK预初始化 */
        tuya_iot_sdk_pre_init(TRUE);  
    
        /* 应用业务初始化 */
        TY_GW_INFRA_CBS_S gw_cbs = {
            .gw_reset_cb       = __gw_reset_cb,
            .gw_upgrade_cb     = __gw_upgrade_cb,
            .gw_active_stat_cb = __gw_active_stat_cb,
            .gw_reboot_cb      = __gw_reboot_cb,
        };
        tuya_user_svc_init(&gw_cbs);
    
        /* SDK初始化 */
    #if defined(GW_SUPPORT_WIRED_WIFI) && (GW_SUPPORT_WIRED_WIFI==1)
        tuya_iot_wired_wf_sdk_init(IOT_GW_NET_WIRED_WIFI, GWCM_OLD, WF_START_AP_ONLY, PID, USER_SW_VER, NULL, 0);
    #elif defined(WIFI_GW) && (WIFI_GW==1)
        tuya_iot_wf_sdk_init(GWCM_OLD, WF_START_AP_ONLY, PID, USER_SW_VER, NULL, 0);
    #else
        tuya_iot_sdk_init(PID, USER_SW_VER, NULL, 0); // USER_SW_VER 宏在编译时指定
    #endif
    
        /* 注册网络通知回调 */
        tuya_iot_sdk_reg_netstat_cb(__nw_stat_cb, __wired_stat_cb, NULL);
    
        /* 应用业务启动 */
        tuya_user_svc_start(NULL);
    
        /* loop */
        while (1) {
            sleep(10);
        }
    
        return 0;
    }
    
  4. 回调接口实现。

    /* 网关被删除或删除并清空数据的回调 */
    STATIC VOID __gw_reset_cb(GW_RESET_TYPE_E type) {}
    
    /* 网关OTA回调 */
    STATIC VOID __gw_upgrade_cb(CONST FW_UG_S *fw) {}
    
    /* 网关状态变化通知回调 */
    STATIC VOID __gw_active_stat_cb(GW_STATUS_E status) {}
    
    /* 应用重启通知回调 */
    STATIC VOID __gw_reboot_cb(VOID) {}
    
    /* 联网状态变化通知回调 */
    STATIC VOID __nw_stat_cb(IN CONST SDK_NW_STAT_T stat) {}
    
    /* 有线状态变化通知回调 */
    STATIC VOID __wired_stat_cb(IN CONST SDK_WIRED_NW_STAT_T stat) {}
    

HAL适配

不同的系统网络操作有差异,所以 SDK 定义了一套标准的接口来屏蔽系统差异,要求开发者根据自己的系统来做适配。

SDK 适配接口的定义:

文件 描述
tuya_os_adapt_wired.h 有线适配接口
tuya_os_adapt_wifi.h 无线适配接口
tuya_os_adapt_bt.h 蓝牙适配接口

本文以 Linux 平台为例,使用有线方式配网,提供了 Linux 平台的有线适配代码,并且在 Ubuntu 系统下测试,但绝大部分的 Linux 系统都适用。

  1. 如果是有线 SDK,实现有线适配接口。在 tuyaos_demo_mini_gw/src 目录下新建一个 hal_wired.c 文件,把附录 hal_wired.c 的代码拷贝到文件中。

    注意,需要把 hal_wired.c 中的 ETH_DEV 改成您系统的网络接口。这一步骤非常重要,网络接口错误会导致网关无法配网。

  2. 如果是无线 SDK,实现无线适配接口。无线的适配不在本文介绍的范围,这里仅使用有线配网,无线适配接口全部为空实现。在 tuyaos_demo_mini_gw/src 目录下新建一个 hal_wifi.c 文件,把附录 hal_wifi.c 的代码拷贝到文件中。

编译

编写完代码,接下来我们来编译 tuyaos_demo_mini_gw 工程。

在开发包的根目录下,执行命令:

$ ./build_app.sh apps/tuyaos_demo_mini_gw tuyaos_demo_mini_gw 1.0.0

参数1 是示例代码工程的路径。

参数2 是输出目录名称,为自定义字符串。

参数3 是固件版本号,为自定义字符串,但格式必须为 x.x.x

编译过程会在终端输出编译信息,如果编译过程没有报错,将看到 “Build APP Finish” 打印,表示编译完成。

快速入门

运行

程序已经编译好,我们可以直接在 Ubuntu 平台上运行,把 Ubuntu 作为网关设备接入涂鸦平台。

编译成功生成的可执行程序位于 <开发包路径>/output/tuyaos_demo_mini_gw_<版本号> 目录下,版本号为编译时输入的版本号。

前面编译指定的版本号为 1.0.0,所以我们的程序位于 <开发板路径>/output/tuyaos_demo_mini_gw_1.0.0,进入到该目录运行程序。

$ cd output/tuyaos_demo_mini_gw_1.0.0
$ ./tuyaos_demo_mini_gw

最后,使用智慧生活 APP 激活网关,APP 详细教程请参考 使用指南,配网方式采用有线配网。

观察程序的日志打印,我们将会看到 main.c 的打印信息。

...
SDK 信息打印 ==>
[01-01 18:12:15 TUYA D][user_main.c:104] SDK INFO: < TUYA IOT SDK V:1.1.0 BS:40.00_PT:2.2_LAN:3.4_CAD:1.0.4_CD:1.0.0 >
< BUILD AT:2021_12_28_16_21_47 BY ci_manage FOR ty_integrated_sdk AT linux-ubuntu-6.2.0_64Bit >
IOT DEFS < WIFI_GW:1 DEBUG:1 KV_FILE:1 SHUTDOWN_MODE:1 LITTLE_END:1 TLS_MODE:4 ENABLE_CLOUD_OPERATION:1 OPERATING_SYSTEM:100 ENABLE_SYS_RPC:1 RELIABLE_TRANSFER:1 ENABLE_LAN_ENCRYPTION:1 ENABLE_LAN_LINKAGE:1 ENABLE_LAN_DEV:1 >

...
网关状态通知,第一次启动 ==>
[01-01 18:12:15 TUYA D][main.c:50] gw active stat callback, status: 2

...
网关状态通知,已激活 ==>
[01-01 18:12:30 TUYA D][main.c:50] gw active stat callback, status: 1

...
联网状态通知,已连接互联网 ==>
[01-01 18:12:30 TUYA D][main.c:66] network stat: 1

附录

main.c

#include <unistd.h>

#include "uni_log.h"
#include "base_os_adapter.h"
#include "tuya_iot_base_api.h"
#include "tuya_iot_com_api.h"

#include "tuya_iot_sdk_api.h"
#include "tuya_iot_sdk_defs.h"

#if defined(TY_BT_MOD) && (TY_BT_MOD == 1)
#include "tuya_os_adapt_bt.h"
#endif

#define PID       "fljmamufiym5fktz"                  // 替换成自己的产品 ID
#define UUID      "tuya461dbc63aeeb991f"              // 替换成自己的 UUID
#define AUTHKEY   "c8X4PR4wx1gMFaQlaZu5dfgVvVRwB8Ug"  // 替换成自己的 AUTHKEY

STATIC VOID __gw_reset_cb(GW_RESET_TYPE_E type)
{
    PR_DEBUG("gw reset callback, type: %d", type);

    if (GW_RESET_DATA_FACTORY != type) {
        exit(0);
    }

    return;
}

STATIC VOID __gw_upgrade_cb(CONST FW_UG_S *fw)
{
    PR_DEBUG("gw upgrade callback");

    if (fw == NULL) {
        PR_ERR("invalid param");
        return;
    }

    PR_DEBUG("        tp: %d", fw->tp);
    PR_DEBUG("    fw_url: %s", fw->fw_url);
    PR_DEBUG("    sw_ver: %s", fw->sw_ver);
    PR_DEBUG("   fw_hmac: %s", fw->fw_hmac);
    PR_DEBUG(" file_size: %u", fw->file_size);

    return;
}

STATIC VOID __gw_active_stat_cb(GW_STATUS_E status)
{
    PR_DEBUG("gw active stat callback, status: %d", status);

    return;
}

STATIC VOID __gw_reboot_cb(VOID)
{
    PR_DEBUG("gw reboot callback");

    exit(0);

    return;
}

STATIC VOID __nw_stat_cb(IN CONST SDK_NW_STAT_T stat)
{
    PR_DEBUG("network stat: %d", stat);

    return;
}

STATIC VOID __wired_stat_cb(IN CONST SDK_WIRED_NW_STAT_T stat)
{
    PR_DEBUG("wired stat: %d", stat);

    return;
}

int main(int argc, char **argv)
{
    OPERATE_RET rt = OPRT_OK;
    GW_PROD_INFO_S prod_info = {0};

    /* gw base callback */
    TY_GW_INFRA_CBS_S gw_cbs = {
        .gw_reset_cb       = __gw_reset_cb,
        .gw_upgrade_cb     = __gw_upgrade_cb,
        .gw_active_stat_cb = __gw_active_stat_cb,
        .gw_reboot_cb      = __gw_reboot_cb,
    };

#if defined(TY_BT_MOD) && (TY_BT_MOD == 1)
    tuya_os_adapt_reg_bt_intf();
#endif

    /* initiate os-layer service*/
    tuya_os_intf_init();

    /* initiate iot-layer service */
    TUYA_CALL_ERR_RETURN(tuya_iot_init("./"));

    /* set the logging level to debug */
    SET_PR_DEBUG_LEVEL(TY_LOG_LEVEL_DEBUG);

    PR_DEBUG("SDK INFO: %s", tuya_iot_get_sdk_info());

    /* set uuid and authkey */
    prod_info.uuid     = UUID;
    prod_info.auth_key = AUTHKEY;
    TUYA_CALL_ERR_RETURN(tuya_iot_set_gw_prod_info(&prod_info));

    /* pre-initiate sdk service */
    TUYA_CALL_ERR_RETURN(tuya_iot_sdk_pre_init(TRUE));  

    /* initiate application service, more service in here */
    TUYA_CALL_ERR_RETURN(tuya_user_svc_init(&gw_cbs));

    /* initiate sdk service */
#if defined(GW_SUPPORT_WIRED_WIFI) && (GW_SUPPORT_WIRED_WIFI==1)
    TUYA_CALL_ERR_RETURN(tuya_iot_wired_wf_sdk_init(IOT_GW_NET_WIRED_WIFI, GWCM_OLD, WF_START_AP_ONLY, PID, USER_SW_VER, NULL, 0));
#elif defined(WIFI_GW) && (WIFI_GW==1)
    TUYA_CALL_ERR_RETURN(tuya_iot_wf_sdk_init(GWCM_OLD, WF_START_AP_ONLY, PID, USER_SW_VER, NULL, 0));
#else
    TUYA_CALL_ERR_RETURN(tuya_iot_sdk_init(PID, USER_SW_VER, NULL, 0));
#endif

    /* register net stat notification callback */
    TUYA_CALL_ERR_RETURN(tuya_iot_sdk_reg_netstat_cb(__nw_stat_cb, __wired_stat_cb, NULL));

    /* start application service, more service in here */
    TUYA_CALL_ERR_RETURN(tuya_user_svc_start(NULL));

    while (1) {
        sleep(10);
    }

    return 0;
}

hal_wired.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>

#include "uni_log.h"
#include "tuya_os_adapt_wired.h"

#define ETH_DEV "enp0s3"

OPERATE_RET tuya_adapter_wired_get_ip(OUT NW_IP_S *ip)
{
    int sock = 0;
    char ipaddr[50] = {0};

    struct sockaddr_in *sin;
    struct ifreq ifr;

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
         PR_ERR("socket create failed");
         return OPRT_COM_ERROR;
    }

    memset(&ifr, 0, sizeof(ifr));
    strncpy(ifr.ifr_name, ETH_DEV, sizeof(ifr.ifr_name) - 1);

    if (ioctl(sock, SIOCGIFADDR, &ifr) < 0 ) {
         PR_ERR("ioctl failed");
         close(sock);
         return OPRT_COM_ERROR;
    }

    sin = (struct sockaddr_in *)&ifr.ifr_addr;
    strcpy(ip->ip,inet_ntoa(sin->sin_addr)); 
    close(sock);

    return OPRT_OK;
}

BOOL_T tuya_adapter_wired_station_conn(VOID)
{
    int sock;
    struct sockaddr_in *sin;
    struct ifreq ifr;

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
         PR_ERR("socket failed");
         return OPRT_COM_ERROR;
    }

    memset(&ifr, 0, sizeof(ifr));
    strncpy(ifr.ifr_name, ETH_DEV, sizeof(ifr.ifr_name) - 1);

    if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
        PR_ERR("ioctl failed");
        close(sock);
        return FALSE;
    }

    close(sock);

    if ((ifr.ifr_flags & IFF_UP) == 0)
        return FALSE;

    return TRUE;
}

OPERATE_RET tuya_adapter_wired_get_mac(OUT NW_MAC_S *mac)
{
    int sock;
    struct sockaddr_in *sin;
    struct ifreq ifr;

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
         PR_ERR("socket failed");
         return OPRT_COM_ERROR;
    }

    memset(&ifr, 0, sizeof(ifr));
    strncpy(ifr.ifr_name, ETH_DEV, sizeof(ifr.ifr_name) - 1);

    if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
        PR_ERR("ioctl failed");
        close(sock);
        return FALSE;
    }

    memcpy(mac->mac, ifr.ifr_hwaddr.sa_data, sizeof(mac->mac));

    PR_DEBUG("WIFI MAC: %02X-%02X-%02X-%02X-%02X-%02X\r\n",
             mac->mac[0],mac->mac[1],mac->mac[2],mac->mac[3],mac->mac[4],mac->mac[5]);
    
    close(sock);

    return OPRT_OK;
}

/* 无需实现 */
OPERATE_RET tuya_adapter_wired_set_mac(IN CONST NW_MAC_S *mac)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wired_if_connect_internet(BOOL_T *status)
{
    *status = TRUE;

    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wired_wifi_set_station_connect(IN CONST CHAR_T *ssid,IN CONST CHAR_T *passwd)
{
    /* return hal_wifi_connect_station(ssid, passwd); */
    return OPRT_OK;
}

BOOL_T tuya_adapter_wired_wifi_need_cfg(VOID)
{
    return FALSE;
}

OPERATE_RET tuya_adapter_wired_wifi_station_get_conn_ap_rssi(OUT SCHAR_T *rssi)
{
    /* return hal_wifi_get_station_rssi(rssi); */
    *rssi = 99;
    
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wired_get_nw_stat(GW_BASE_NW_STAT_T *stat)
{
    *stat = 0;

    return OPRT_OK;
}

hal_wifi.c

#include "tuya_os_adapt_wifi.h"

OPERATE_RET tuya_adapter_wifi_all_ap_scan(AP_IF_S **aps, UINT_T *num)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_assign_ap_scan(CONST SCHAR_T *ssid, AP_IF_S **ap)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_release_ap(AP_IF_S *ap)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_set_cur_channel(CONST UCHAR_T channel)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_get_cur_channel(UCHAR_T *chan)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_sniffer_set(CONST BOOL_T en, CONST SNIFFER_CALLBACK cb)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_get_ip(CONST WF_IF_E wf, NW_IP_S *ip)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_set_mac(CONST WF_IF_E wf, CONST NW_MAC_S *mac)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_get_mac(CONST WF_IF_E wf, NW_MAC_S *mac)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_set_work_mode(CONST WF_WK_MD_E mode)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_get_work_mode(WF_WK_MD_E *mode)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_ap_start(CONST WF_AP_CFG_IF_S *cfg)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_ap_stop(VOID_T)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_station_connect(CONST SCHAR_T *ssid, CONST SCHAR_T *passwd)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_station_disconnect(VOID_T)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_station_get_conn_ap_rssi(SCHAR_T *rssi)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_get_bssid(UCHAR_T *mac)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_station_get_status(WF_STATION_STAT_E *stat)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_set_country_code(CONST COUNTRY_CODE_E code)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_send_mgnt(CONST UCHAR_T *buf, CONST UINT_T len)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_register_recv_mgnt_callback(CONST BOOL_T enable, CONST WIFI_REV_MGNT_CB recv_cb)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_set_lp_mode(CONST BOOL_T en, CONST UCHAR_T dtim)
{
    return OPRT_OK;
}

OPERATE_RET tuya_adapter_wifi_get_connected_ap_info_v2(FAST_WF_CONNECTED_AP_INFO_V2_S **fast_ap_info)
{
    return OPRT_COM_ERROR;
}

OPERATE_RET tuya_adapter_wifi_fast_station_connect_v2(CONST FAST_WF_CONNECTED_AP_INFO_V2_S *fast_ap_info)
{
    return OPRT_COM_ERROR;
}

BOOL_T tuya_adapter_wifi_rf_calibrated(VOID_T)
{
    return FALSE;
}