远程开门

更新时间:2023-07-17 09:01:08下载pdf

获取门锁支持的远程开门方式

支持的门锁类型

  • Zigbee 门锁
  • 蓝牙门锁

接口地址

GET /v1.0/devices/{device_id}/door-lock/remote-unlocks

请求参数

参数名 类型 参数类型 说明 必填
device_id String URI 设备 ID。

请求示例

GET /v1.0/devices/vdevo153459260090544/door-lock/remote-unlocks

返回参数

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

result

参数名 类型 说明
remote_unlock_type String 开门方式。
  • remoteUnlockWithoutPwd:免密开门。
  • remoteUnlockWithPwd:含密开门。
open Boolean 功能是否开启。

请求成功返回示例

{
    "result": {
        "remote_unlock_type": "remoteUnlockWithPwd",
        "open": true
    },
    "success": true,
    "t": 1592899848757
}

请求失败返回示例

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

设置门锁远程开门方式的开关

支持的门锁类型

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

接口地址

POST /v1.0/devices/{device_id}/door-lock/remote-unlock/config

请求参数

参数名 类型 参数类型 说明 必填
device_id String URI 设备 ID。
remote_unlock_type String BODY 开门方式。
  • remoteUnlockWithoutPwd:免密开门。
  • remoteUnlockWithPwd:含密开门。
open Boolean BODY 功能是否开启。

请求示例

POST /v1.0/devices/vdevo153459260090544/door-lock/remote-unlock/config
{
    "remote_unlock_type": "remoteUnlockWithPwd",
    "open": true
}

返回参数

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

请求成功返回示例

{
    "result": true,
    "success": true,
    "t": 1592899848757
}

请求失败返回示例

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

门锁含密开门

支持的门锁类型

  • Zigbee 门锁

接口地址

POST /v1.0/devices/{device_id}/door-lock/open-door

请求参数

参数名 类型 参数类型 说明 必填
device_id String URI 设备 ID。
password String Body 密码原文长度为 6,密码传输加密算法使用 AES,模式:ECB PKCS7Padding。数据块为 128 位。秘钥为通过接口获取的临时 ticket_key,使用开发者 accessKey AES 解密后的原始秘钥。
password_type String BODY 密码加密类型:ticket
ticket_id String BODY 临时秘钥 ID。

请求示例

POST /v1.0/devices/6c362ac3c53fbd6f3ewqfa/door-lock/open-door

返回信息

参数名 类型 说明
code Integer 响应码。详情见错误码章节。
success Boolean 是否成功。
  • true:成功。
  • false:失败。
msg String 请求失败的信息,成功为空
result Boolean 返回结果

返回示例

{
    "success": true,
    "t": 1542626129429,
    "result": true
}

门锁免密开门

支持的门锁类型

  • 公版 Wi-Fi 门锁
  • 公版 Zigbee 门锁
  • 酒店 Zigbee 门锁
  • 蓝牙门锁
  • 常保活 Wi-Fi 门锁
  • 可视对讲 Wi-Fi

接口地址

POST /v1.0/devices/{device_id}/door-lock/password-free/open-door

请求参数

参数名 类型 参数类型 说明 必填
device_id String URI 设备 ID。
ticket_id String Body 临时秘钥 ID。

请求示例

POST /v1.0/devices/vdevo153459260090544/door-lock/password-free/open-door
{
    "ticket_id":"xxxxx"
}

返回参数

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

请求成功返回示例

{
    "result": true,
    "success": true,
    "t": 1592899848757
}

请求失败返回示例

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

门锁免密开门(v1.1)

该接口支持对特定通道执行开门动作。

支持的门锁类型

  • Wi-Fi 门禁

接口地址

POST /v1.1/devices/{device_id}/door-lock/password-free/open-door

请求参数

参数名 类型 参数类型 说明 必填
device_id String URI 设备 ID。
ticket_id String Body 临时秘钥 ID。该值通过接口 POST:/v1.0/devices/{device_id}/door-lock/password-ticket 获取。
channel_id Integer Body 通道 ID。

请求示例

POST /v1.1/devices/vdevo15345926009****/door-lock/password-free/open-door
{
    "ticket_id":"WHmutLIq",
    "channel_id":1
}

返回参数

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

请求成功返回示例

{
    "result": true,
    "success": true,
    "t": 1592899848757
}

请求失败返回示例

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

门锁免密开门撤销

支持的门锁类型

类型 支持
门锁类型 Wi-Fi 门锁

接口地址

PUT /v1.0/devices/{device_id}/door-lock/password-free/open-door/cancel

请求参数

参数名 类型 参数类型 说明 必填
device_id String URI 设备 ID。
type Integer BODY 撤销远程开门的原因。
  • 1:拒绝
  • 2:取消

请求示例

PUT /v1.0/devices/vdevo153459260090544/door-lock/password-free/open-door/cancel
{
    "type":1
}

返回参数

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

请求成功返回示例

{
    "result": true,
    "success": true,
    "t": 1592899848757
}

请求失败返回示例

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

门锁免密开关门

支持的门锁类型

  • 公版 Wi-Fi 门锁
  • 公版 Zigbee 门锁
  • 酒店 Zigbee 门锁
  • 蓝牙门锁
  • 常保活 Wi-Fi 门锁
  • 可视对讲 Wi-Fi

远程开门必须有 remote_no_dp_key 或者 remote_no_dp_setkey 这两个 DP,且只有公版 Wi-Fi 门锁支持远程关门。

接口地址

POST /v1.0/smart-lock/devices/{device_id}/password-free/door-operate

请求参数

参数名 类型 参数类型 说明 必填
device_id String URI 设备 ID。
ticket_id String Body 临时秘钥 ID。
open Boolean Body 操作。
  • true:开门。默认开门。
  • false:关门

请求示例

POST /v1.0/smart-lock/devices/vdevo153459260090544/password-free/door-operate
{
    "ticket_id":"xxxxx",
    "open":false
}

返回参数

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

请求成功返回示例

{
    "result": true,
    "success": true,
    "t": 1592899848757
}

请求失败返回示例

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

获取密码加密的临时秘钥

本接口是由门锁免密开关门接口调用。

支持的门锁类型

  • Wi-Fi 门锁
  • Zigbee 门锁
  • 蓝牙门锁
  • 酒店 Zigbee 门锁
  • 可视对讲 Wi-Fi

接口地址

POST /v1.0/smart-lock/devices/{device_id}/password-ticket

请求参数

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

请求示例

POST /v1.0/smart-lock/devices/vdevo15345926009****/password-ticket

返回参数

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

result

参数名 类型 说明
ticket_id String 临时秘钥 ID。
ticket_key String 临时秘钥 Key,需要根据云开发者 accessKey 通过 AES 解密后方可使用。
expire_time Long 剩余有效时间。

请求成功返回示例

{
    "result": {
        "expire_time": 360,
        "ticket_id": "9wxxoLM",
        "ticket_key": "901CC35A67DA3429C38E9622xxxxx3EAE1CE333462356D257FD1D3E5C"
    },
    "success": true,
    "t": 1592899848757
}

请求失败返回示例

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

远程开门带抓拍图片

  • 远程开门带抓拍图片流程:

    用户云服务门锁实时告警、门锁影像信息上报实时告警、开门影像信息通知实时查询告警、开门影像全路径全路径信息返回获得图片信息并解码免密远程开门/撤销指令免密远程开门/撤销指令下发最近一次告警、开门影像信息查询影像信息返回获得图片信息并解码免密远程开门/撤销指令免密远程开门/撤销指令下发用户云服务门锁
  • 远程开门带抓拍图片-实时场景

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

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

影像信息通过 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"
}