Wi-Fi 门锁音视频能力

更新时间:2024-03-04 08:55:32

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

音视频功能

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

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

类名 说明
ThingOptimusSdk 初始化 SDK 入口,用来获取门锁管理类
IThingLockManager 门锁管理类,可以获取不同类型的门锁类
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,仅需要调用一次
ThingOptimusSdk.init(getApplicationContext());
// 获取 IThingLockManager
val iThingLockManager = ThingOptimusSdk.getManager(IThingLockManager::class.java)
// 获取 IVideoLockManager
iThingVideoLockManager = iThingLockManager.newVideoLockManagerInstance(mDevId)
// 注册监听
iThingVideoLockManager?.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) {
iThingVideoLockManager?.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 指令发送结果

示例代码

iThingVideoLockManager?.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 指令发送结果

示例代码

iThingVideoLockManager?.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, IThingResultCallback<FileBucketInfoBean> callback);

参数说明

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

FileBucketInfoBean: 图片的云存储信息

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

示例代码

iThingVideoLockManager?.getLatestPicture(FileTypeEnum.REMOTE_UNLOCK,
    object : IThingResultCallback<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, IThingResultCallback<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?
) {
iThingVideoLockManager?.getPictureAndVideo(
    bucket,
    filePath,
    object : IThingResultCallback<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 门锁音视频能力

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

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

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

为渲染视图容器设置回调

接口说明

public void setViewCallback(AbsVideoViewCallback callback);

参数说明

参数 说明
callback 回调接口

示例代码

ThingCameraView 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

示例代码

ThingCameraView 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 = iThingVideoLockManager?.ipcManager
ThingCameraView 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: ThingVideoFrameInfo?,
        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)
    }


})
});   
}

onReceiveFrameYUVData 裸流数据

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

onSessionStatusChanged P2P 链接状态回调

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

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(IThingResultCallback<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 : IThingResultCallback<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, IThingResultCallback<String> callback);

参数说明

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

示例代码

iIpcManager?.snapshot(
        path,
        mContext,
        ICameraP2P.PLAYMODE.LIVE,
        rotateMode ?: RotateModeEnum.NORMAL,
        object : IThingResultCallback<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();

销毁

IIPCManager 销毁

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

void onDestroy();

IVideoLockManger 销毁

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

void onDestroy();