门锁图像和视频

更新时间:2023-06-15 05:15:19

查询当前设备已经观看视频次数

支持的门锁类型

  • Wi-Fi 门锁

接口地址

GET /v1.0/smart-lock/devices/{device_id}/media-view-times

请求参数

参数名 类型 参数类型 说明 是否必传
device_id String URI 设备 ID

请求示例

GET /v1.0/smart-lock/devices/vdevo124546565765/media-view-times

返回参数

参数名 类型 说明
code Integer 错误响应码,成功时为空(详情⻅见错误码)
success Boolean 是否成功:(true:成功,false:失败)
t Long 响应时间
msg String 请求失败的信息,成功为空
result Integer 次数

请求成功返回示例

{
  "result": 1,
  "success": true,
  "t": 1634712882506
}

请求失败返回示例

{
    "success": false,
    "code": 500, // 错误码,详细请见错误码文档
    "msg": "system error,please contact the admin"
}

当前设备已经观看视频次数+1

支持的门锁类型

  • Wi-Fi 门锁

接口地址

POST /v1.0/smart-lock/devices/{device_id}/media-view-times

请求参数

参数名 类型 参数类型 说明 是否必传
device_id String URI 设备 ID

请求示例

POST /v1.0/smart-lock/devices/vdevo124546565765/media-view-times

返回参数

参数名 类型 说明
code Integer 错误响应码,成功时为空(详情⻅见错误码)
success Boolean 是否成功:(true:成功,false:失败)
t Long 响应时间
msg String 请求失败的信息,成功为空
result Integer 次数

请求成功返回示例

{
  "result": 2,
  "success": true,
  "t": 1634713143910
}

请求失败返回示例

{
    "success": false,
    "code": 500, // 错误码,详细请见错误码文档
    "msg": "system error,please contact the admin"
}

远程开门带抓拍图片

  • 远程开门带抓拍图片流程:
    门锁图像和视频

  • 远程开门带抓拍图片-实时场景

    • 用户触发拍照锁开门操作,门锁抓拍图片并上报云服务
    • 云服务存储影像数据,并推送相对存储位置信息到用户端
    • 用户端调用云服务,获得影像存储全路径
    • 用户端获得加密影像数据并解密
    • 用户根据得到影像信息,判断是开门\撤销,并调用相应接口
    • 云服务下发到拍照锁,执行开门\撤销操作
  • 远程开门带抓拍图片-非实时场景

    • 用户端调用云服务查询最近一次90s内的开门\预警影像信息
    • 用户端获得加密影像数据并解密
    • 用户根据得到影像信息,判断是开门\撤销,并调用相应接口
    • 云服务下发到拍照锁,执行开门\撤销操作

影像信息通过AES/CBC/PKCS5Padding加密,规则如下所示:

4 16 44 视频内容
占位 iv 占位 视频内容

解密demo如下所示:

package xxxxxxx;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;
 
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
 
public class EncryptUtils {
 
    private static final String DEFAULT_ALGORITHM = "AES";
    private static final String DEFAULT_FULL_ALGORITHM = "AES/CBC/PKCS5Padding";
 
    //加密
    public static File encryptFile(String key, File originFile, String destPath) {
        FileInputStream in = null;
        FileOutputStream out = null;
        File destFile = null;
        try {
            destFile = new File(destPath);
            if (originFile.exists() && originFile.isFile()) {
                if (!destFile.getParentFile().exists()) {
                    destFile.getParentFile().mkdirs();
                }
                destFile.createNewFile();
                in = new FileInputStream(originFile);
                out = new FileOutputStream(destFile, true);
                byte[] iv = getIv();
                Cipher cipher = initAESCipher(iv, key, Cipher.ENCRYPT_MODE);
                CipherInputStream cipherInputStream = new CipherInputStream(in, cipher);
                byte[] cache = new byte[1024];
                int nRead;
                out.write(new byte[4]);
                out.write(iv);
                out.write(new byte[4]);
                out.write(new byte[40]);
                out.flush();
                while ((nRead = cipherInputStream.read(cache)) != -1) {
                    out.write(cache, 0, nRead);
                    out.flush();
                }
                cipherInputStream.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return destFile;
    }
 
    //解密
    public static File decryptFile(String key, InputStream in, File destFile) {
        FileOutputStream out = null;
        try {
            if (!destFile.getParentFile().exists()) {
                destFile.getParentFile().mkdirs();
            }
            destFile.createNewFile();
            out = new FileOutputStream(destFile);
 
            byte[] iv = new byte[16];
            in.skip(4);
            int read = in.read(iv);
            if (read != 16) {
                throw new IOException("iv length error");
            }
            in.skip(44);
            Cipher cipher = initAESCipher(iv, key, Cipher.DECRYPT_MODE);
            CipherOutputStream cipherOutputStream = new CipherOutputStream(out, cipher);
            byte[] buffer = new byte[1024];
            int r;
            while ((r = in.read(buffer)) >= 0) {
                cipherOutputStream.write(buffer, 0, r);
            }
            cipherOutputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return destFile;
    }
 
    private static Cipher initAESCipher(byte[] iv, String sKey, int cipherMode) {
        try {
            IvParameterSpec zeroIv = new IvParameterSpec(iv);
            SecretKeySpec key = new SecretKeySpec(sKey.getBytes(), DEFAULT_ALGORITHM);
            Cipher cipher = Cipher.getInstance(DEFAULT_FULL_ALGORITHM);
            cipher.init(cipherMode, key, zeroIv);
            return cipher;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }
        return null;
    }
 
    public static byte[] getIv() {
        StringBuilder uid = new StringBuilder();
        //产生16位的强随机数
        Random rd = new SecureRandom();
        for (int i = 0; i < 16; i++) {
            //产生0-2的3位随机数
            int type = rd.nextInt(3);
            switch (type) {
                case 0:
                    //0-9的随机数
                    uid.append(rd.nextInt(10));
                    break;
                case 1:
                    //ASCII在65-90之间为大写,获取大写随机
                    uid.append((char) (rd.nextInt(25) + 65));
                    break;
                case 2:
                    //ASCII在97-122之间为小写,获取小写随机
                    uid.append((char) (rd.nextInt(25) + 97));
                    break;
                default:
                    break;
            }
        }
        return uid.toString().getBytes();
    }
 
}

获取最近一次的远程开门或告警封面图

支持的门锁类型

  • Wi-Fi 门锁
  • 酒店 Zigbee 门锁
  • 蓝牙门锁

接口地址

GET /v1.0/devices/{device_id}/door-lock/latest/media/url

请求参数

参数名 类型 参数类型 说明 是否必填
device_id String URI 设备 ID
file_type Integer URL 文件类型 1. 远程开门, 2. 告警

请求示例

GET /v1.0/devices/6cdb36b2e489885fa57lzm/door-lock/latest/media/url?file_type=1

返回参数

参数名 类型 说明
code Integer 返回的错误码,成功时为空,详情⻅返回的错误码
success Boolean 是否成功
true:成功
false:失败
t Long 响应时间
msg String 请求失败的信息,成功为空
result Object 返回结果

result

参数名 类型 说明
file_url String 封面图完整路径
file_key String 文件解密密钥
bucket String 封面图完整路径
file_path String 文件的相对路径

请求成功返回示例

{
    "result": {
        "bucket": "ty-cn-storage60-1254153901",
        "file_key": "u8kstrtjm7qun83q",
        "file_path": "/3039e1-30532026.jpg",
        "file_url": "https://ty-cn-storage60-1254153901.cos.tuyacn.com6"
    },
    "success": true,
    "t": 1614147303662
}

请求失败返回示例

{
    "success": false,
    "code": 500, // 错误码,详细请见错误码文档
    "msg": "system error, please contact the admin"
}

获取相册列表

支持的门锁类型

  • 可视对讲 Wi-Fi

接口地址

GET /v1.0/smart-lock/devices/{device_id}/albums-media

请求参数

参数名 类型 参数类型 说明 是否必传
device_id String URI 设备 ID

请求示例

GET /v1.0/smart-lock/devices/vdevo153459260090544/albums-media

返回参数

参数名 类型 说明
code Integer 错误响应码,成功时为空(详情⻅见错误码)
success Boolean 是否成功:(true:成功,false:失败)
t Long 响应时间
msg String 请求失败的信息,成功为空
result Object 返回结果

result

参数名 类型 说明
eventTypes array[int] 相册里封面图和视频的类型
albumList List 相册数据列表
orderCode Integer 当前相册查询所使用的套餐
  • doorlock_cloud_storage_7day 七天不限次数云存储
  • doorlock_cloud_storage_30day 30天不限次数云存储
  • cloud_free_storage_3day 3天免费云存储

albumList

参数名 类型 说明
eventType int 文件类型
fileUrl String 封面图地址
fileKey String 封面图密钥
mediaPath String 视频地址
mediaKey String 视频密钥
mediaBucket String 视频所在的仓库
uploadTime long 上报时间(秒)

eventType文件类型说明

类型值 类型 说明
0 int 防撬告警
1 int 远程开门请求
2 int 指纹开门试错
3 int 密码开门试错
4 int 卡片开门试错
5 int 人脸开门试错
6 int 掌纹开门试错
7 int 指静脉开门试错
8 int 指纹开门
9 int 密码开门
10 int 卡片开门
11 int 人脸开门
12 int 掌纹开门
13 int 指静脉开门
14 int 临时密码解锁
15 int 动态密码解锁
16 int 远程解锁
17 int 临时密码解锁上报
18 int 门铃解锁上报
19 int 劫持告警
20 int 低电报警
21 int 钥匙插入报警
22 int 高温报警
23 int 门铃+远程开门
24 int 有人停留(逗留)
25 int 门锁被破坏
26 int 特殊指纹开锁
27 int 布防模式下开锁
28 int 遥控开门

请求成功返回示例

{
    "success": true,
    "t": 1542626129429,
    "result": {
        "album_list": [
      {
        "event_type": 0,
        "file_id": 109167468,
        "file_key": "76679d2579c74eb7",
        "file_url": "https://ty-cn-storage30-1254153901.cos.tuyacn.com/d76182-35779292-dc706aecd4469145/unify/1630051338.jpeg?sign=q-sign-algorithm%3Dsha1%26q-ak%3DAKIDopcCYgw0qRoyV5qfKjvg2pPkqESnb5zI%26q-sign-time%3D1630137629%3B1630141229%26q-key-time%3D1630137629%3B1630141229%26q-header-list%3Dhost%26q-url-param-list%3D%26q-signature%3D29b40dd6ed4281b78321ec978ce1e56361fd7b57",
        "upload_time": 1630051337
      }
    ],
    "event_types": [
      0
    ],
    "order_code": "cloud_free_storage_3day"
    }
}

请求失败返回示例

{
    "success": false,
    "code": 500, // 错误码,详细请见错误码文档
    "msg": "system error,please contact the admin"
}