Wi-Fi 门锁音视频能力

更新时间:2023-06-07 02:35:24

本文档包含音视频相关接口、日志功能、成员管理以及临时密码相关功能。

音视频功能

Wi-Fi 门锁音视频能力接口支持可视门锁、拍照锁的实时视频查看、对讲等功能。

获取音视频能力入口及初始化

类名 说明
TuyaOptimusSdk 初始化 SDK 入口,用来获取门锁管理类
ITuyaLockManager 门锁管理类,可以获取不同类型的门锁类
IVideoLockManager Wi-Fi 门锁音视频功能入口

注册监听

监听门锁各种 DP 上报,包含实时视频请求、远程开关锁、告警等 DP 上报。

void registerLockReportListener(ILockReportListener iLockReportListener);

void unRegisterLockReportListener();

方法说明

ILockReportListener:

	 /**
     * 主动消息推送 ,主要包含抓拍的图片存储路径信息  即dpCode:initiative_message
     * @param devId 设备id
     * @param dpCode
     * @param fileBucketInfoBean  云存储中的图片信息
     */
    void onLockMessageArrived(String devId, String dpCode, FileBucketInfoBean fileBucketInfoBean);
    /**
     * 实时视频请求 dpCode:video_request_realtime
     * @param devId 设备id
     * @param dpCode
     * @param dpValue
     */
    void onVideoRequestRealtime(String devId, String dpCode,String dpValue);

    /**
     * 远程开门请求倒计时 dpCode:unlock_request
     * @param devId 设备id
     * @param dpCode
     * @param dpValue
     */
    void unlockRequestCountdown(String devId,String dpCode,Object dpValue);

    /**
     * 抓拍告警确认倒计时 dpCode:alarm_request
     * @param devId 设备id
     * @param dpCode
     * @param dpValue
     */
    void alarmRequestCountdown(String devId, String dpCode,Object dpValue);

    /**
     * 远程开锁上报 dpCode:remote_no_dp_key
     * @param devId 设备id
     * @param dpCode
     * @param dpValue
     */
    void onRemoteUnlockReport(String devId, String dpCode,Object dpValue);

    /**
     * 强制反锁 dp 上报,dpCode:reverse_lock
     * @param devId
     * @param dpCode
     */
    void onForceLockUpReport(String devId, String dpCode,Object dpValue);

    /**
     * 设备其他 dp 上报
     * @param devId
     * @param dpCode
     */
    void onLockDpUpdate(String devId, Map<String,Object> dpCode);

示例代码

// 初始化 SDK,仅需要调用一次
TuyaOptimusSdk.init(getApplicationContext());
// 获取 ITuyaLockManager
val iTuyaLockManager = TuyaOptimusSdk.getManager(ITuyaLockManager::class.java)
// 获取 IVideoLockManager
iTuyaVideoLockManager = iTuyaLockManager.newVideoLockManagerInstance(mDevId)
// 注册监听
iTuyaVideoLockManager?.registerLockReportListener(object:ILockReportListener{
            override fun onLockMessageArrived(
                devId: String?,
                dpCode: String?,
                fileBucketInfoBean: FileBucketInfoBean?
            ) {
                TODO("Not yet implemented")
            }

            override fun onVideoRequestRealtime(devId: String?, dpCode: String?, dpValue: String?) {
                TODO("Not yet implemented")
            }

            override fun unlockRequestCountdown(devId: String?, dpCode: String?, dpValue: Any?) {
                TODO("Not yet implemented")
            }

            override fun alarmRequestCountdown(devId: String?, dpCode: String?, dpValue: Any?) {
                TODO("Not yet implemented")
            }

            override fun onRemoteUnlockReport(devId: String?, dpCode: String?, dpValue: Any?) {
                TODO("Not yet implemented")
            }

            override fun onForceLockUpReport(devId: String?, dpCode: String?, dpValue: Any?) {
                TODO("Not yet implemented")
            }

            override fun onLockDpUpdate(devId: String?, dpCode: MutableMap<String, Any>?) {
                TODO("Not yet implemented")
            }

        })

远程开锁

接口说明

通过此接口可以实现远程开锁、关锁、拒绝开锁、拒绝关锁。

void remoteLock(boolean isOpen, boolean confirm, IResultCallback callback);

参数说明

参数 能否为空 说明
isOpen 开门还是关门,开门=true,关门=false
confirm 允许还是拒绝,允许=true,拒绝=false
Callback 调用接口回调结果

Callback 的 onSuccess 回调只能表示接口调用成功,不能作为门锁设备执行指令判断标准。confirm = true 时,设备状态发生变化(开锁、关锁),设备执行成功后依赖监听方法 onRemoteUnlockReport回调结果。confirm=false时,设备状态没有产生变化,不会上报 DP。onSuccess 表示拒绝开锁或拒绝关锁执行成功。

示例代码

fun remoteUnLock(isOpen: Boolean, confirm: Boolean) {
        iTuyaVideoLockManager?.remoteLock(isOpen, confirm, object : IResultCallback {
            override fun onError(code: String?, error: String?) {
                Toast.makeText(mContext, error, Toast.LENGTH_SHORT).show()
            }

            override fun onSuccess() {
                Toast.makeText(mContext, "publish success", Toast.LENGTH_SHORT).show()
            }

        })
    }

重新拍照

接口说明

重新拍照。设备会把抓拍的图片传到云存储,并通过 onLockMessageArrived 上报图片路径信息。受设备限制,15 秒内只能下发一次。

void reTakePhoto(boolean isTakePhotoAgain, IResultCallback callback);

参数说明

参数 能否为空 说明
isTakePhotoAgain 是否重新拍照
callback 指令发送结果

示例代码

iTuyaVideoLockManager?.reTakePhoto(true,object :IResultCallback{
            override fun onError(code: String?, error: String?) {
                L.e(TAG,"RetakePhoto error:$error")
            }

            override fun onSuccess() {
                L.i(TAG,"Retake photo publish success")
            }

        })

强制反锁

接口说明

强制反锁。设备执行成功会通过 onForceLockUpReport 回调结果。

void forceLock(boolean isForceLock, IResultCallback callback);

参数说明

参数 能否为空 说明
isForceLock 是否强制反锁
callback 指令发送结果

示例代码

iTuyaVideoLockManager?.forceLock(true,object :IResultCallback{
            override fun onError(code: String?, error: String?) {
                L.e(TAG,"code $code error:$error")
                ToastUtil.shortToast(mContext,error)
            }

            override fun onSuccess() {
                L.i(TAG,"force anti-lock success")
                ToastUtil.shortToast(mContext,"force anti-lock success")
            }

        })

获取最新的图片地址信息

接口说明

获取云存储上最新的一张图片信息。需要配合使用接口 getPictureAndVideo

void getLatestPicture(FileTypeEnum fileTypeEnum, ITuyaResultCallback<FileBucketInfoBean> callback);

参数说明

参数 能否为空 说明
fileTypeEnum 图片类型:远程解锁抓拍图片、告警抓拍图片
callback 回调结果

FileBucketInfoBean: 图片的云存储信息

字段 说明
filePath 图片在云存储的路径
fileKey 解密 key
bucket 云存储 bucket

示例代码

iTuyaVideoLockManager?.getLatestPicture(FileTypeEnum.REMOTE_UNLOCK,
            object : ITuyaResultCallback<FileBucketInfoBean> {
                override fun onSuccess(result: FileBucketInfoBean?) {
                    L.i(TAG, "result filePath:${result?.toString()}")
                    result?.let {
                        requestPictureAndVideo(it.bucket, it.filePath, it.fileKey)
                    }

                }

                override fun onError(errorCode: String?, errorMessage: String?) {
                    Toast.makeText(mContext, errorMessage, Toast.LENGTH_SHORT).show()
                }

            })

获取抓拍图片地址

接口说明

设备抓拍的图片会上传到云存储,通过此接口获取图片的地址。此接口和监听回调 onLockMessageArrived 方法或 getLatestPicture 配合使用。

void getPictureAndVideo( String bucket, String filePath, ITuyaResultCallback<RemoteMediaBean> callback);

参数说明

参数 能否为空 说明
bucket 云存储 bucket
filePath 云存储加密 URL
callback 回调结果

RemoteMediaBean:

字段 说明
fileUrl 图片在云存储的路径
mediaUrl 视频在云存储的路径
angle 角度,在 IoT 开发平台配置的角度旋转,有效值:090180270

注意

fileUrl 仍然是加密链接,需要 onLockMessageArrivedgetLatestPicture 获取 fileKey 解密。我们提供控件 DecryptImageView 负责解密和显示图像。

示例代码

override fun onLockMessageArrived(
        devId: String?,
        dpCode: String?,
        fileBucketInfoBean: FileBucketInfoBean?
    ) {
    	fileBucketInfoBean?.let {
    		requestPictureAndVideo(it.bucket,it.filePath,it.fileKey)
    	}
    }
...
fun requestPictureAndVideo(
        bucket: String?,
        filePath: String?,
        fileKey: String?
    ) {
        iTuyaVideoLockManager?.getPictureAndVideo(
            bucket,
            filePath,
            object : ITuyaResultCallback<RemoteMediaBean> {
                override fun onSuccess(result: RemoteMediaBean?) {
                    L.i(TAG, result?.toString())
                    if (fileKey != null) {
                        refreshImage(result?.fileUrl, fileKey)
                    }

                }

                override fun onError(errorCode: String?, errorMessage: String?) {
                    Toast.makeText(mContext, errorMessage, Toast.LENGTH_SHORT).show()
                }

            })
    }
    
    ...
    fun refreshImage(fileUrl:String?,fileKey:String){
      fileUrl?.let{
        val imageView:DecryptImageView = findViewById(R.id.div_picture)
        imageView.setImageURI(it,fileKey.toByteArray())
      }
    }

获取视频对象接口

接口说明

IIPCManager getIPCManager();

该接口包含 P2P 连接、视频渲染、对讲等功能,整体流程如下:

Wi-Fi 门锁音视频能力

页面布局文件中引入渲染视图容器

TuyaCameraView 是 SDK 提供的视频渲染视图。

<com.tuya.smart.camera.middleware.widget.TuyaCameraView
  android:id="@+id/camera_video_view"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  />

为渲染视图容器设置回调

接口说明

public void setViewCallback(AbsVideoViewCallback callback);

参数说明

参数 说明
callback 回调接口

示例代码

TuyaCameraView mVideoView = findViewById(R.id.camera_video_view);
mVideoView.setViewCallback(new AbsVideoViewCallback() {
	@Override
	public void onCreated(Object view) {
		super.onCreated(view);
        // 渲染视图构造完成时回调
	}
});

AbsVideoViewCallback

渲染视图回调抽象类。开发者只需要重写自己关心的回调,一般只需要重写 onCreated 方法。

构造渲染视图

接口说明

public void createVideoView(String devId);

参数说明

参数 说明
devId 设备 ID

示例代码

TuyaCameraView mVideoView = findViewById(R.id.camera_video_view);
mVideoView.createVideoView(devId);

绑定渲染视图

接口说明

void generateCameraView(T view);

示例代码

iIPCManager?.generateCameraView(mVideoView.createdView())

注册 P2P 监听

注册监听器,否则无法正常显示画面。
关于监听的详细解释,请参考 裸流数据

接口说明

void registerP2PCameraListener(AbsP2pCameraListener listener);

示例代码

// 1. 获取 IIPCManager
iIPCManager = iTuyaVideoLockManager?.ipcManager
TuyaCameraView cameraView = findViewById(R.id.camera_video_view)
// 2. 为渲染视图容器设置回调
cameraView.setViewCallback(object : AbsVideoViewCallback() {
            override fun onCreated(p0: Any?) {
                super.onCreated(p0)
                iIpcManager?.generateCameraView(p0)
            }
        })
// 3. 构造渲染视图
cameraView.createVideoView(devId)
// 4. 注册 P2P 监听
if (null != iIPCManager){
    iIPCManager.registerP2PCameraListener(object: AbsP2pCameraListener() {
        override fun onReceiveAudioBufferData(
                nSampleRate: Int,
                nChannelNum: Int,
                nBitWidth: Int,
                nTimeStamp: Long,
                progress: Long,
                duration: Long
            ) {
                super.onReceiveAudioBufferData(
                    nSampleRate,
                    nChannelNum,
                    nBitWidth,
                    nTimeStamp,
                    progress,
                    duration
                )
            }

            override fun onReceiveFrameYUVData(
                sessionId: Int,
                y: ByteBuffer?,
                u: ByteBuffer?,
                v: ByteBuffer?,
                videoFrameInfo: TuyaVideoFrameInfo?,
                camera: Any?
            ) {
                super.onReceiveFrameYUVData(sessionId, y, u, v, videoFrameInfo, camera)
            }

            override fun onReceiveFrameYUVData(
                sessionId: Int,
                y: ByteBuffer?,
                u: ByteBuffer?,
                v: ByteBuffer?,
                width: Int,
                height: Int,
                nFrameRate: Int,
                nIsKeyFrame: Int,
                timestamp: Long,
                nProgress: Long,
                nDuration: Long,
                camera: Any?
            ) {
                super.onReceiveFrameYUVData(
                    sessionId,
                    y,
                    u,
                    v,
                    width,
                    height,
                    nFrameRate,
                    nIsKeyFrame,
                    timestamp,
                    nProgress,
                    nDuration,
                    camera
                )
            }

            override fun onReceiveSpeakerEchoData(pcm: ByteBuffer?, sampleRate: Int) {
                super.onReceiveSpeakerEchoData(pcm, sampleRate)
            }

            override fun onSessionStatusChanged(camera: Any?, sessionId: Int, sessionStatus: Int) {
                super.onSessionStatusChanged(camera, sessionId, sessionStatus)
            }


        })
    });   
}

P2P 连接

在开始视频播放之前,需要先连接 P2P 通道。P2P 状态需要使用者自己维护,SDK 只负责下发指令和接收摄像机响应结果。

接口说明

连接 P2P 通道

void connect(IResultCallback callBack);

断开 P2P 通道

void disconnect(IResultCallback callBack);

参数说明

参数 说明
callBack 操作结果回调

是否已连上

boolean isConnected();

是否在连接中

boolean isConnecting();

实时播放视频

P2P 连接成功之后,即可进行实时视频播放。

接口说明

开始播放实时视频

void startPreview(int clarity, IResultCallback callBack);

停止播放实时视频

int stopPreview(IResultCallback callBack);

参数说明

参数 说明
clarity 清晰度模式
callBack 操作结果回调

清晰度模式

模式
标清 2
高清 4

示例代码

iIPCManager.startPreview(new IResultCallback() {
    @Override
    public void onSuccess() {
        // 开始播放实时视频成功
    }

    @Override
    public void onError(String code, String error) {
        // 开始播放实时视频失败
    }
});

startPreview 成功回调之后,onReceiveFrameYUVData 回调会开始接收视频数据,并抛给业务层。

本地录制

当视频成功开始播放以后(可以是视频直播,也可以是录像回放),可以将当前正在播放的视频录制到手机中。

在视频录制的过程中,请不要再切换视频清晰度,开关声音及对讲。

如果需要将录制的视频保存至系统相册,需要开发者自己实现。注意 Android10 开始采用 分区存储 机制(可禁用,但 Android11 强制使用),保存媒体文件至系统相册需使用 MediaStore API。

开启视频录制

接口说明

void startRecord(String folderPath, Context context, RotateModeEnum rotateMode, IResultCallback callback);

录制视频需要写存储卡权限。

参数说明

参数 说明
folderPath 保存视频的文件目录路径
context 上下文
rotateMode 旋转模式
callBack 操作回调

停止录制视频

接口说明

void stopRecord(ITuyaResultCallback<Map<String, String>> callback);

回调参数说明

停止录制会回调两条数据:视频路径和封面图路径,分别通过 key videocoverImage 获取对应 value。

是否在录制视频

接口说明

boolean isRecording();

示例代码

if(iIpcManager?.isRecording == true){
	stopRecorder()
}else{
	startRecord()
}

...
fun startRecord(){
	iIpcManager?.startRecord(
                path,
                mContext,
                rotateMode ?: RotateModeEnum.NORMAL,
                object : IResultCallback {
                    override fun onError(code: String?, error: String?) {
                        
                    }

                    override fun onSuccess() {
                        L.i(TAG, "recorder success")
                    }

                })
}
fun stopRecord(){
	iIpcManager?.stopRecord(object : ITuyaResultCallback<Map<String, String>> {
            override fun onSuccess(result: Map<String, String>?) {
                result?.let {
                    val videoPath = it.get("video")
                    val coverImagePath = it.get("coverImage")                    
                }
            }

            override fun onError(errorCode: String?, errorMessage: String?) {
                
            }

        })
}

视频截图

截取实时视频的影像图片存储到手机 SD 卡上。

如果需要将截图保存至系统相册,需要开发者自己实现。注意,Android10 开始采用 分区存储 机制(可禁用,但 Android11 强制使用),保存媒体文件至系统相册需使用 MediaStore API。

接口说明

void snapshot(String folderPath, Context context, ICameraP2P.PLAYMODE playmode, RotateModeEnum rotateMode, ITuyaResultCallback<String> callback);

参数说明

参数 说明
folderPath 图片存储路径
context 上下文
playmode 视频播放模式,当前仅支持 PLAYMODE.LIVE
rotateMode 旋转模式,支持的角度:090180270
callBack 操作回调。onSuccess 返回截图完整路径

示例代码

iIpcManager?.snapshot(
                path,
                mContext,
                ICameraP2P.PLAYMODE.LIVE,
                rotateMode ?: RotateModeEnum.NORMAL,
                object : ITuyaResultCallback<String> {
                    override fun onSuccess(result: String?) {
                        L.i(TAG, "snapshot success :$result")
                    }

                    override fun onError(errorCode: String?, errorMessage: String?) {
                        
                    }

                })

视频声音

当视频成功开始播放以后,可以开启视频声音。声音默认是关闭状态。

接口说明

开启、关闭视频声音。

void enableMute(boolean isMute,IResultCallback callback);
音频模式
静音 true
非静音 false

是否开启声音

boolean isMuting();

示例代码

iIpcManager?.enableMute(mute, object : IResultCallback {
            override fun onError(code: String?, error: String?) {
                
            }

            override fun onSuccess() {
                L.i(TAG, "set mute $mute success ")
            }

        })

实时对讲

在 P2P 连接成功后,可以开启与设备的实时通话功能。在开始对讲前,需要确保 App 已获得手机麦克风的访问权限。

开启对讲/关闭对讲

打开、关闭手机声音传输给摄像机操作。

void startTalk(IResultCallback callback);
void stopTalk(IResultCallback callback);

是否支持对讲/是否已开启对讲

boolean isSupportTalk();
boolean isTalkBacking();

示例代码

iIpcManager?.startTalk(object : IResultCallback {
                override fun onError(code: String?, error: String?) {
                    
                }

                override fun onSuccess() {
                    L.i(TAG, "startTalk success")
                }

            })
iIpcManager?.stopTalk(object : IResultCallback {
            override fun onError(code: String?, error: String?) {
                
            }

            override fun onSuccess() {

            }

        })

其他

接口说明

设备是否有拾音器。若设备配置有拾音器,表示设备的视频有声音。

boolean isSupportSound();

接口说明

获取默认的对讲方式。

int supportAudioMode();

裸流数据

SDK 提供访问视频裸流数据的回调方法。此方法返回视频帧的 YUV 数据,颜色编码格式为 YUV 420SP。

接口说明

接收视频帧回调需要注册监听器,开发者只需要重写自己关心的回调。

void registerP2PCameraListener(AbsP2pCameraListener listener);

AbsP2pCameraListener 主要方法:

接口说明

回调视频 YUV 数据。

public void onReceiveFrameYUVData(int sessionId, ByteBuffer y, ByteBuffer u, ByteBuffer v, int width, int height, int nFrameRate, int nIsKeyFrame, long timestamp, long nProgress, long nDuration, Object camera)

参数说明

参数 说明
sessionId session ID
Y 视频 Y 数据
u 视频 U 数据
v 视频 V 数据
width 视频画面的宽
height 视频画面的高
nFrameRate 帧率
nIsKeyFrame 是否 I 帧
timestamp 时间戳
nProgress 时间进度,即 消息中心视频播放的进度
nDuration 时长,即 消息中心视频播放时长

接口说明

P2P 的链接状态回调。

public void onSessionStatusChanged(Object camera, int sessionId, int sessionStatus)

参数说明

参数 说明
sessionId session ID
sessionStatus session 状态
session 状态码 说明
0 连接成功
-3 连接超时
-12 连接被设备关闭
-13 连接无响应超时关闭

销毁

IIPCManager 销毁

不再使用 camera 功能时,必须注销 P2P 监听器、销毁 P2P 对象。

void onDestroy();

IVideoLockManger 销毁

不再使用可视门锁、拍照锁相关功能时,销毁整个 IVideoLockManger 对象,IIPCManager 对象也会同步销毁。

void onDestroy();