可视化挖耳勺(BK7231U SDK 对接 )

更新时间:2022-01-13 07:33:40

产品的创建

登录IOT平台(https://iot.tuya.com/)选择“可视挖耳勺”产品并创建产品。如图所示:
可视化挖耳勺(BK7231U SDK 对接 )
可视化挖耳勺(BK7231U SDK 对接 )
创建产品过后需要选择产品对应的面板(目前只有该面板支持拉流,如果有其他定制需求可以找对接人员提定制需求)
可视化挖耳勺(BK7231U SDK 对接 )
创建产品选完对应DP点和面板后进入硬件开发。再硬件开发页面中选择对应的芯片平台后,可以下载对应SDK,如图所示:
可视化挖耳勺(BK7231U SDK 对接 )

固件的创建

新增自定义固件

可视化挖耳勺(BK7231U SDK 对接 )

  1. 固件标识名:这里定义的标识名一定要和编译出来的固件名称是一样,否则后续无法授权。
  2. 新增自定义固件是开发者一定要走的步骤。设备配网时云端会做对应校验,如果没有生成对应固件KEY,后续产品是没办法配网成功的。
  3. 其余可以按照图片定义,定义完毕后点击 “生成固件KEY”

应用开发

SDK架构

ty_iot_wf_rtos_sdk_2.3.1
├─ apps #Demo
│  ├─ tuya_demo_elp_1plug
│  ├─ tuya_demo_light_pwm
│  └─ tuya_demo_template
├─ platforms #芯片平台相关文件
└─ sdk #涂鸦Wi-Fi SDK
│  ├─ include #头文件
│  └─ lib #lib库
├─ build_app.h #编译脚本
├─ CHANGELOG.md #迭代说明
├─ README.md #注意事项

开发环境搭建

目前SDK需要在 Linux 系统下编译,具体的环境搭建可以参考 开发环境

修改SDK对应信息

  1. 环境搭建完毕后,在 Linux 下,解压SDK包。输入:tar -zxvf b6c36suogf0g.tar.gz
    可视化挖耳勺(BK7231U SDK 对接 )
  2. 打开对应工程,目前工程里面有两个demo,这两个demo目前都没有实现 RTSP 拉流功能,拉流功能需要开发者自己参考SDK里面的 RTSP 功能组件接口,自行移植和添加。(可以看文章最下面的移植例程)
    可视化挖耳勺(BK7231U SDK 对接 )
  3. 修改PID,在宏定义 PRODUCT_KEY 填入平台产品的PID信息,如图:可视化挖耳勺(BK7231U SDK 对接 )
    可视化挖耳勺(BK7231U SDK 对接 )

固件编译

目前固件编译的脚本已经写好,直接运行即可。如: sh build_app.sh apps/Bk731u_Video_Test Bk731u_Video_Test 1.0.0
可视化挖耳勺(BK7231U SDK 对接 )

建议编译之前先 clean 一下,清除之前的编译信息。如:sh build_app.sh apps/Bk731u_Video_Test Bk731u_Video_Test 1.0.0 clean 如图:
可视化挖耳勺(BK7231U SDK 对接 )

固件上传

编译成功后,需要把编译出来的固件上传到IOT平台,上传的目的是获取对应授权码。
编译后的固件生成在\ty_iot_sdk_bk7231u_bk7231t_unencrypted-2.3.4-beta.1\apps\Bk731u_Video_Test\output\1.0.0 目录下

文件名 说明
Bk731u_Video_Test_QIO_1.0.0.bin 生产固件,用于模组Flash工作方式为QIO的模组
Bk731u_Video_Test_UA_1.0.0.bin 用户区固件,用于芯片烧录工具使用
Bk731u_Video_Test_UG_1.0.0.bin 升级固件,用于上传涂鸦 IoT 平台用户区固件和 OTA 固件
在硬件开发处上传编译出来的对应固件,保存并上架。如图:
可视化挖耳勺(BK7231U SDK 对接 )
可视化挖耳勺(BK7231U SDK 对接 )
可视化挖耳勺(BK7231U SDK 对接 )

激活码获取

可视化挖耳勺(BK7231U SDK 对接 )
固件上传完成后即可获取授权码,涂鸦的授权码分为以下三种类型,您可以根据自己使用的烧录授权方案选择合适的授权码目前该SDK仅支持 生产凭证-仅授权生产凭证
可视化挖耳勺(BK7231U SDK 对接 )
(目前每个账号只可以免费申请2个激活码。后续需要下单购买)

授权码名称 适用方案 说明
生产凭证 适用于烧录授权一体方案 加密后的授权码信息,使用涂鸦上位机通过授权协议烧录到设备内,常用于固件烧录和授权一体方案,会对固件 Key 包含的固件标识名、固件版本等信息进行校验,防止出现固件烧录错误、版本错误等现象,是涂鸦标准模组使用的烧录方式 ,也是涂鸦最推荐的烧录方式,不过需要涂鸦生产系统支持相应芯片的烧录,不适用于非涂鸦标准芯片。
生产凭证-仅授权 适用于烧录授权分立方案 加密后的授权码信息,使用涂鸦上位机通过授权协议烧录到设备内,用于固件烧录和授权分立方案,不对固件 Key 包含的信息做校验,适用于非涂鸦标准芯片的授权。
授权码清单 不建议使用,如有需求,可以先通过工单与涂鸦进行沟通 授权码明文信息,由开发者自行开发上位机烧录到设备内,通常不建议使用。

固件烧录

目前如果是新得BK7231U芯片或者开发板需要先用 SPI 烧录 QIO 文件之后才能正常用串口烧录 UA 文件。(如果没有用SPI烧录,芯片是没有 bootloader 的,无法正常使用)

SPI烧录软件配置

可视化挖耳勺(BK7231U SDK 对接 )

擦除状态一定要选择擦除程序空间,如果选择擦除全部空间会把RF标志位擦掉,固件需要重新做RF校验。

SPI烧录工具

可视化挖耳勺(BK7231U SDK 对接 )

该工具可以直接从原厂获取,或者联系涂鸦对接人员购买。

SPI烧录接线

可视化挖耳勺(BK7231U SDK 对接 )
(除以上5个IO以外,还需连VCC和GND)

串口烧录

在用SPI烧录之后,芯片已有 bootloader ,后续开发者在调试时,只需通过串口1烧录对应用户区固件即可。
可视化挖耳勺(BK7231U SDK 对接 )

对应烧录软件可直接从原厂获取或联系涂鸦FAE获取。

固件授权

目前固件授权有两种方式:1.下单时选择生产凭证授权,此授权方法会检测PID是否和固件匹配,优点是比较简单,不需要走工单。2.下单时选择生产凭证授权-仅授权,此方法一般是针对不同PID的产品授权,生产凭证(Token)中不含固件信息,只用于授权激活;

生产凭证授权

  1. 平台下单购买授权码时,选择的时生产凭证。下单完毕后会下载到授权码。拿到授权码,一般要先再涂鸦的生产管理系统确认一下授权码:生产系统 (如果没有账号的要先注册)
    可视化挖耳勺(BK7231U SDK 对接 )

如果没有生产凭证确定的选项,联系涂鸦的对接人员开通白名单

  1. 下载授权软件
    可视化挖耳勺(BK7231U SDK 对接 )
  2. 下载安装完之后,登录(用生产管理系统申请的账号登陆,不要用IOT平台账号登陆,目前这两个平台账号是分离的),选择云模组
    可视化挖耳勺(BK7231U SDK 对接 )
  3. 烧录平台打开之后,点击输入生产凭证——点击生产凭证——写入平台购买的授权码,烧录工位选择烧录授权,点击确定。如图所示:
    可视化挖耳勺(BK7231U SDK 对接 )
    点击文件,选择设置,授权波特率选择9600,因为不需要上位机烧录固件,所以下面选择仅授权,点击确定。如图:
    可视化挖耳勺(BK7231U SDK 对接 )
    目前 BK7231U UART1 做授权。所以用串口工具连接UART1,再烧录软件上选择对应COM口。点击运行。然后给开发板或者芯片重新上电,烧录成功如图所示:
    可视化挖耳勺(BK7231U SDK 对接 )
    如果遇到烧录失败,请看FAQ。

生产凭证-仅授权

文档可以参考该文档,按照该文档流程进行即可:
可视化挖耳勺(BK7231U SDK 对接 )

SDK拉流部分API说明

读图

Sensor 初始化

struct video_pix_format v_format;
struct vbq_config video_buff_q_config;
struct sensor_reg_config reg_cfg;
VIDEO_FPS_TYPE fps;

sw_i2c_pin_config(1, 0);   //设置I2C引脚, 如果不调用,默认sda---1,  scl----0

OPERATE_RET tuya_soc_camera_init(soc_camera_link *tuya_camera_link, BYTE_T num, video_mem_handler *p_video_mem_handler);
ty_video_mem_handler.mem_malloc = tuya_hal_system_malloc;
ty_video_mem_handler.mem_free = tuya_hal_system_free;
tuya_soc_camera_init(tuya_camera_link,1,&ty_video_mem_handler);

soc_video_device = tuya_video_dev_find("ty_video");
if(soc_video_device == NULL){
    PR_DEBUG("soc_video_device is null");
    return OPRT_COM_ERROR;
}

/*初始化video_device*/
tuya_video_dev_open(soc_video_device);

/*设置格式*/
v_format.p_type = VGA_640_480;
v_format.pixelformat = V4L2_PIX_FMT_JPEG;
v_format.field = V4L2_FIELD_ANY;
v_format.colorspace = V4L2_COLORSPACE_JPEG;
ret = tuya_video_dev_ctl(soc_video_device,CMD_SET_FMT,&v_format);
if(ret != 0) {
	PR_NOTICE("CMD_SET_FMT :%d",ret);
}

video_buff_q_config.video_pkg_buffer_len = 1 * 1024;    //设置读图一个缓存bug大小
video_buff_q_config.video_pkg_num = 12;     // 设置读图缓存个数
ret = tuya_video_dev_ctl(soc_video_device,CMD_STREAM_SET_BUFF,&video_buff_q_config);
if(ret != 0) {
    PR_NOTICE("CMD_STREAM_SET_BUFF: %d",ret);
}

启动读图功能

/*启动*/
tuya_video_dev_ctl(soc_video_device,CMD_STREAM_START,NULL);

读图片数据

/**
 * @brief:  tuya_video_dev_read  读取数据
 * @param   用户配置
 * @retval: none
 */
OPERATE_RET tuya_video_dev_read(video_device *video_dev, struct video_pkg **pkg);

释放读图缓存区

/*释放 buf */
tuya_video_dev_ctl(soc_video_device, CMD_STREAM_DEQUEEU_BUFF,NULL);

拉图

rtsp初始化

INT_T ret;
rtsp_stream_src_t src = {0};

NW_IP_S ip_str;

wf_get_ip(WF_STATION, &ip_str);
PR_NOTICE("ip_str :%x, %s",ip_str.ip, ip_str.ip);

src.get_codec = __get_codec;
src.get_frame = __get_frame_jpeg;
src.get_frame_fragment = __get_frame_fragment_jpeg;
src.get_sample_rate = __get_sample_rate;
src.start = __start;
src.stop = __stop;
src.get_name = __get_name;

tuya_svc_lan_reg_rtsp_stream_src(src);

rtsp需要注册的函数回调

STATIC INT_T __get_frame_fragment_jpeg(INT_T user_id, rtsp_frame_fragment_t* pframe)
{
  	//rtsp 拉图回调
    return 0;
}

/*  rtsp 拉图回调 */
STATIC INT_T __get_frame_jpeg(INT_T user_id, RTSP_MEDIA_TYPE_E type, CHAR_T** buf, INT_T *plen, UINT64_T *pts)
{
    //rtsp 拉图回调
    return -1;
}
STATIC RTP_CODEC_E __get_codec(RTSP_MEDIA_TYPE_E type)
{
    switch (type){
    case RTSP_MEDIA_TYPE_VIDEO:
        return RTP_CODEC_JPEG;
    case RTSP_MEDIA_TYPE_AUDIO:
        return RTP_CODEC_INVALID;
    default:
        return 0;
    }
}

STATIC INT_T __get_sample_rate(RTSP_MEDIA_TYPE_E type)
{
    switch (type){
    case RTSP_MEDIA_TYPE_VIDEO:
        return 90000;
    case RTSP_MEDIA_TYPE_AUDIO:
        return 8000;
    default:
        return 8000;
    }
}
STATIC INT_T __start()
{
    int i;
    for(i = 0; i < 5; i++){
        if (NULL == users[i]){
            users[i] = Malloc(sizeof(user_info_s));
            users[i]->last_pts[RTSP_MEDIA_TYPE_VIDEO] = 0;
            users[i]->last_pts[RTSP_MEDIA_TYPE_AUDIO] = 0;
            users[i]->pos[RTSP_MEDIA_TYPE_VIDEO] = 0;
            users[i]->pos[RTSP_MEDIA_TYPE_AUDIO] = 0;
            return i;
        }
    }
    return -1;
}
STATIC INT_T __stop(INT_T user_id)
{
    if (users[user_id]){
        Free(users[user_id]);
        users[user_id] = NULL;
    }
    return 0;
}

STATIC INT_T __get_name(CHAR_T* buf, INT_T* buf_len)
{
    char name[] = "stream_0";
    memcpy(buf, name, sizeof(name));

    *buf_len = sizeof(name);

    return 0;
}

摄像头驱动型号设置

有两种方式, 一种是自动识别sensor 驱动, 另一种是应用指定。 在初始化时候输入。

/*自动识别sensor*/
#define  AUTO_RECOGNIT_SENSOR 1


#if AUTO_RECOGNIT_SENSOR
static struct resource sensor_chip_sourece[]={
        {
            .name = (BYTE_T *)"i2c",    /*未知的sensor 使用 第 0 个I2C去连接*/        
            .type = 6,
            .port = 0,       
        },
};  

/*构建视频系统的参数,支持同时存在多个video_device*/
static soc_camera_link  tuya_camera_link[] = 
{
    {
        .name = (BYTE_T *)"ty_video",

        /*用于配置sensor_chip驱动所用到的硬件资源*/
        .sensor_device = {
                .name  = (BYTE_T *)SENSOR_ANY,        /*不指定哪一款sensor 去自动识别*/                                  
                .num_resource = 1,                    //资源数目
                .resource = sensor_chip_sourece,      //资源
        },
        
        .host_nr = 0,
    },

};

#else

static struct resource sensor_chip_sourece[]={
        {
            .name = (BYTE_T *)"i2c",            
            .type = 6,   /*对应 tuya_driver的 TUYA_DRV_I2C*/
            .port = 0,   /*使用第0个I2C*/
        },

        {
            .name = (BYTE_T *)"i2c_addr",            
            .type = 0,
            .port = 0x21, /*I2C地址0x21*/      
        },
};  

/*构建视频系统的参数,支持同时存在多个video_device*/
static soc_camera_link  tuya_camera_link[] = 
{
    {
        .name = (BYTE_T *)"ty_video",

        /*用于配置sensor_chip驱动所用到的硬件资源*/
        .sensor_device = {
                .name  = (BYTE_T *)SENSOR_GC0308,                                      
                .num_resource = 2,                    //资源数目
                .resource = sensor_chip_sourece,      //资源
        },
        
        .host_nr = 0, /*SENSOR_GC0328 与 第0个host总线接着*/
    },

};
#endif

video_mem_handler ty_video_mem_handler;

// 初始化接口
 OPERATE_RET tuya_soc_camera_init(soc_camera_link *tuya_camera_link, BYTE_T num, video_mem_handler *p_video_mem_handler);
ty_video_mem_handler.mem_malloc = tuya_hal_system_malloc;
ty_video_mem_handler.mem_free = tuya_hal_system_free;
tuya_soc_camera_init(tuya_camera_link,1,&ty_video_mem_handler);

udp 分片拉图, 分片的时间片需要相同。
bk 平台读图数据最后有5个字节数据是多余的。

SDK其他接口说明

请参考API说明

完整DEMO

#include "ty_video_lib.h"
#include "tuya_hal_network.h"
#include "tuya_hal_semaphore.h"
#include "tuya_svc_lan_rtsp.h"
#include "rtsp_server.h"

typedef struct {
    int pos[RTSP_MEDIA_TYPE_NUM];
    uint64_t last_pts[RTSP_MEDIA_TYPE_NUM];
} user_info_s;

user_info_s* users[5] = {0};

SEM_HANDLE sem_handle;
SEM_HANDLE sem_handle_rtsp;
struct video_pkg *vb_pkg;
UCHAR_T test_tmp_buf[1025];
UCHAR_T *pstr = NULL;
static UCHAR_T cnt_max = 0;


#include "BkDriverGpio.h"

video_device *soc_video_device = NULL;

STATIC INT_T __get_frame_fragment_jpeg(INT_T user_id, rtsp_frame_fragment_t* pframe)
{
    user_info_s* pinfo = users[user_id];
	RTSP_MEDIA_TYPE_E type = pframe->type;
    INT_T pos = pinfo->pos[type];
    INT_T start = -1, end = -1;
    INT_T media_len;
	UINT_T time_now;
    STATIC UINT_T curr_time_now;
    STATIC UCHAR_T jpeg_eof = 1;

	time_now = rtos_get_time();//uni_time_get_posix_ms();
	if(jpeg_eof) {
        jpeg_eof = 0;
        curr_time_now = time_now;
    }
  
	if (pframe == NULL || user_id >=5 || user_id < 0) {
		PR_ERR("param invalid");
		return -1;
	}

    static fist_flag = 0;
    if(fist_flag == 0) {
        fist_flag = 1;
    	/*启动*/
        tuya_video_dev_ctl(soc_video_device,CMD_STREAM_START,NULL);

    }
  
    tuya_video_dev_read(soc_video_device,&vb_pkg);
    //bk_printf("is_last:%d,no:%d \r\n",vb_pkg->is_last,vb_pkg->pkg_no);

    memset(test_tmp_buf, 0, sizeof(test_tmp_buf));
    memcpy(test_tmp_buf, vb_pkg->pkg_bufs, vb_pkg->actual_len);
    if(vb_pkg->is_last == 1) { 
        jpeg_eof = 1;

        if(vb_pkg->actual_len <= 5) {
            tuya_video_dev_ctl(soc_video_device, CMD_STREAM_DEQUEEU_BUFF,NULL);
            return -1;
        }
        
        media_len = vb_pkg->actual_len - 5;
        //tuya_video_dev_ctl(soc_video_device,CMD_STREAM_STOP,NULL);
        //tuya_video_dev_ctl(soc_video_device,CMD_STREAM_STOP,NULL);
        //fist_flag = 0;
    } else {
        media_len = vb_pkg->actual_len;

    }

    tuya_video_dev_ctl(soc_video_device, CMD_STREAM_DEQUEEU_BUFF,NULL);
 
    pframe->buf = test_tmp_buf ;

	pframe->len = media_len;
    pframe->pts = curr_time_now;
  
    pframe->is_eof = 1;
    
    pinfo->last_pts[type] = curr_time_now;    
    
    pinfo->pos[type] = media_len;

    if (pinfo->pos[type] > 0){
        pinfo->pos[type] = 0;
    }

    return 0;

}


STATIC INT_T __get_frame_jpeg(INT_T user_id, RTSP_MEDIA_TYPE_E type, CHAR_T** buf, INT_T *plen, UINT64_T *pts)
{
    return -1;
}

STATIC RTP_CODEC_E __get_codec(RTSP_MEDIA_TYPE_E type)
{
    switch (type){
    case RTSP_MEDIA_TYPE_VIDEO:
        return RTP_CODEC_JPEG;
    case RTSP_MEDIA_TYPE_AUDIO:
        return RTP_CODEC_INVALID;
    default:
        return 0;
    }
}

STATIC INT_T __get_sample_rate(RTSP_MEDIA_TYPE_E type)
{
    switch (type){
    case RTSP_MEDIA_TYPE_VIDEO:
        return 90000;
    case RTSP_MEDIA_TYPE_AUDIO:
        return 8000;
    default:
        return 8000;
    }
}


STATIC INT_T __start()
{
    int i;
    for(i = 0; i < 5; i++){
        if (NULL == users[i]){
            users[i] = Malloc(sizeof(user_info_s));
            users[i]->last_pts[RTSP_MEDIA_TYPE_VIDEO] = 0;
            users[i]->last_pts[RTSP_MEDIA_TYPE_AUDIO] = 0;
            users[i]->pos[RTSP_MEDIA_TYPE_VIDEO] = 0;
            users[i]->pos[RTSP_MEDIA_TYPE_AUDIO] = 0;
            return i;
        }
    }
    return -1;
}

STATIC INT_T __stop(INT_T user_id)
{
    if (users[user_id]){
        Free(users[user_id]);
        users[user_id] = NULL;
    }
    return 0;
}

STATIC INT_T __get_name(CHAR_T* buf, INT_T* buf_len)
{
    char name[] = "stream_0";
    memcpy(buf, name, sizeof(name));

    *buf_len = sizeof(name);

    return 0;
}


/*自动识别sensor*/
#define  AUTO_RECOGNIT_SENSOR 0
#if AUTO_RECOGNIT_SENSOR
static struct resource sensor_chip_sourece[]={
        {
            .name = (BYTE_T *)"i2c",    /*未知的sensor 使用 第 0 个I2C去连接*/        
            .type = 6,
            .port = 0,       
        },
};  

/*构建视频系统的参数,支持同时存在多个video_device*/
static soc_camera_link  tuya_camera_link[] = 
{
    {
        .name = (BYTE_T *)"ty_video",

        /*用于配置sensor_chip驱动所用到的硬件资源*/
        .sensor_device = {
                .name  = (BYTE_T *)SENSOR_ANY,        /*不指定哪一款sensor 去自动识别*/                                  
                .num_resource = 1,                    //资源数目
                .resource = sensor_chip_sourece,      //资源
        },
        
        .host_nr = 0,
    },

};

#else

static struct resource sensor_chip_sourece[]={
        {
            .name = (BYTE_T *)"i2c",            
            .type = 6,   /*对应 tuya_driver的 TUYA_DRV_I2C*/
            .port = 0,   /*使用第0个I2C*/
        },

        {
            .name = (BYTE_T *)"i2c_addr",            
            .type = 0,
            .port = 0x21, /*I2C地址0x21*/      
        },
};  

/*构建视频系统的参数,支持同时存在多个video_device*/
static soc_camera_link  tuya_camera_link[] = 
{
    {
        .name = (BYTE_T *)"ty_video",

        /*用于配置sensor_chip驱动所用到的硬件资源*/
        .sensor_device = {
                .name  = (BYTE_T *)SENSOR_GC0308,                                      
                .num_resource = 2,                    //资源数目
                .resource = sensor_chip_sourece,      //资源
        },
        
        .host_nr = 0, /*SENSOR_GC0328 与 第0个host总线接着*/
    },

};
#endif

video_mem_handler ty_video_mem_handler;
VOID user_rtsp_init()
{
	INT_T ret;
    rtsp_stream_src_t src = {0};
	STREAM_SRC_ID id;
    CHAR_T url[256] = {0};
    int url_len = 256;

    NW_IP_S ip_str;

    wf_get_ip(WF_STATION, &ip_str);
    PR_NOTICE("ip_str :%x, %s",ip_str.ip, ip_str.ip);

    src.get_codec = __get_codec;
    src.get_frame = __get_frame_jpeg;
    src.get_frame_fragment = __get_frame_fragment_jpeg;
    src.get_sample_rate = __get_sample_rate;
    src.start = __start;
    src.stop = __stop;
    src.get_name = __get_name;

    tuya_svc_lan_reg_rtsp_stream_src(src);
  
    struct video_pix_format v_format;
    struct vbq_config video_buff_q_config;
    struct sensor_reg_config reg_cfg;
    VIDEO_FPS_TYPE fps;
    
	sw_i2c_pin_config(1, 0);   //设置I2C引脚, 如果不调用,默认sda---1,  scl----0

    /*配置tuya_config.h文件,然后调用tuya_soc_camera_init构建系统,建立设备节点*/
    OPERATE_RET tuya_soc_camera_init(soc_camera_link *tuya_camera_link, BYTE_T num, video_mem_handler *p_video_mem_handler);
    ty_video_mem_handler.mem_malloc = tuya_hal_system_malloc;
    ty_video_mem_handler.mem_free = tuya_hal_system_free;
    tuya_soc_camera_init(tuya_camera_link,1,&ty_video_mem_handler);
   
    soc_video_device = tuya_video_dev_find("ty_video");
    if(soc_video_device == NULL){
        PR_DEBUG("soc_video_device is null");
        return OPRT_COM_ERROR;
    }

    /*初始化video_device*/
    tuya_video_dev_open(soc_video_device);

    /*设置格式*/
    v_format.p_type = VGA_640_480;
    v_format.pixelformat = V4L2_PIX_FMT_JPEG;
    v_format.field = V4L2_FIELD_ANY;
    v_format.colorspace = V4L2_COLORSPACE_JPEG;
    ret = tuya_video_dev_ctl(soc_video_device,CMD_SET_FMT,&v_format);
    if(ret != 0) {
        PR_NOTICE("CMD_SET_FMT %d",ret);
    }
    
    /*设置缓存 12个缓存 一帧的大小为 1*1024*/
    video_buff_q_config.video_pkg_buffer_len = 1 * 1024;
    video_buff_q_config.video_pkg_num = 12;
    ret = tuya_video_dev_ctl(soc_video_device,CMD_STREAM_SET_BUFF,&video_buff_q_config);
    if(ret != 0) {
        PR_NOTICE("CMD_STREAM_SET_BUFF: %d",ret);
    }

}

FAQ

固件加密问题

目前平台下载的SDK都是未加密的,也就是需要配合未加密的芯片进行调试。如果编译出来的固件是未加密的,烧录到加密的开发板中,会导致芯片 boot 起不来,没有任何日志。
一般加密的板子配加密的固件,未加密的芯片配未加密的固件。

烧录授权问题

授权的时候显示写入获取固件指纹失败

该问题原因是上传到平台上的固件或者平台上创建的固件标识名和芯片实际烧录的固件名称不一样。所以编译固件的时候一定要和平台创建的固件标识名以及固件版本对的上。
可视化挖耳勺(BK7231U SDK 对接 )

获取RF标志位或者报写入MAC失败

可视化挖耳勺(BK7231U SDK 对接 )
可视化挖耳勺(BK7231U SDK 对接 )
报这种错误的原因是板子的RF没有进行校准。目前BK的芯片都是需要进行RF校准的,校准完成后会再固定的Flash区写入RF标志位,上位机再授权的时候会读一下是否有RF标志位,如果没有就会授权失败。目前写入RF标志位有两种方式:

  1. 使用使用极致汇议进行RF校准(原厂推荐,可以咨询原厂)
  2. 可以购买涂鸦出得校准工具,具体可以咨询涂鸦商务人员。