安防网关能力

更新时间:2022-11-24 09:20:25下载pdf

本文介绍了在您通过 MCU 接入的方式开发安防网关设备时,安防相关串口协议的说明和对接开发的注意事项,助您高效完成开发。其他公共部分通用功能协议请参考 涂鸦网关 MCU 对接通信协议

开启网关模组的安防功能

涂鸦提供的网关模组默认安防能力是关闭的,需要 MCU 在回复模组查询产品信息时,带上 "s"=1 字段。

  • 模组下发数据举例:

    55 AA 01 01 00 00 01
    
  • MCU 应答数据举例:

    数据区内容:{"v":"1.0.0", "m":0, "cap":132, "p":"slyfs7pihpayxbho", "s":1}

    55 AA 00 01 00 3A 7B 22 76 22 3A 22 31 2E 30 2E 30 22 2C 22 6D 22 3A 30 2C 22 63 61 70 22 3A 31 33 32 2C 22 70 22 3A 22 73 6C 79 66 73 37 70 69 68 70 61 79 78 62 68 6F 22 2C 22 73 22 3A 31 7D 62 
    

设备触发报警

门窗磁、人体传感器为一些常用的普通设备,同时满足两个条件下,普通设备上报状态时才会触发报警。

  • 普通设备在HomeSecurity中被勾选为监控传感器。
  • 家庭处于在家或者离家布防状态。
  • 无论是否布防,环境设备状态都会触发报警。

安防网关能力
安防网关能力

安防信息同步0xC0/0x02

当用户在 App 端设置布防或撤防时,模组会下发 0xC0/0x02命令字,以同步给MCU。有关命令帧格式,请参考 网关 MCU 对接通信协议 命令下发章节。

模组下发数据举例:

55 AA 00 C0 00 22 02 7B 22 6D 6F 64 65 22 3A 22 32 22 2C 22 64 65 6C 61 79 22 3A 33 30 2C 22 73 6F 75 6E 64 22 3A 30 7D 93
  • 55 AA 00 C0 00 22 :帧头0x55AA + 版本0x00 + 命令字0xC0 + 数据域字节长度0x0022

  • 02 7B 22 6D 6F 64 65 22 3A 22 32 22 2C 22 64 65 6C 61 79 22 3A 33 30 2C 22 73 6F 75 6E 64 22 3A 30 7D:数据域,首字节为子命令字0x02,后面为真正的数据,转换ASCII 格式如下:

    {"mode":"2", "delay":30, "sound":0}
    
    • “mode”:当前所处模式,“0”:撤防、“1”:在家布防、“2”:离家布防。
    • “delay”:延时布防的时间,0:没有延时、>0:延时时间,单位为秒(s)。
    • “sound”:是否需要播放声音,0:需要播放、非0:不需要播放。

模组数据解析代码参考:

这里给出在gw_mcu_sdk中的代码位置,实际可参考gw_mcu_sdk

需要先在protocol.h文件中开启 \#define SECURITY_PROTECTION_ENABLE 的定义,才会编译安防相关代码。

void security_protect_infor_syn(const unsigned char p_data[], unsigned short data_len)

MCU 应答数据举例:

55 AA 00 C0 00 01 02 C2

设备安防事件同步0xC0/0x03

有关命令帧格式,请参考 网关 MCU 对接通信协议 命令下发章节。

此命令字在如下三种情况下模组会下发同步状态给 MCU:

  • App或MCU设置布防或撤防时,用于通知 MCU 当前的布防状态(无布防倒计时,也会下发)。
  • 有忽略事件发生,主要用于播放声音。
  • 当设置报警延时时,普通设备状态改变后,模组告知 MCU 报警延时开始,单位S。

模组下发数据举例:

55 AA 00 C0 00 18 03 7B 22 73 74 61 74 75 73 22 3A 31 2C 22 64 61 74 61 22 3A 22 30 22 7D DD
  • 55 AA 00 C0 00 18:帧头0x55AA + 版本0x00 + 命令字0xC0 + 数据域字节长度0x0018

  • 03 7B 22 73 74 61 74 75 73 22 3A 31 2C 22 64 61 74 61 22 3A 22 30 22 7D:数据域,首字节为子命令字0x03,后面为真正的数据,转换ASCII 格式如下:

{"status":1, "data":"0"}
  1. “status”:事件,0:撤防、1:进入布防、2:忽略事件、3:报警倒计时开始;
  2. “data”:此字段目前仅用于报警倒计时,“status” = 3时此数值有效

MCU 应答数据举例:

55 AA 00 C0 00 01 03 C3

设备报警信息同步0xC1/0x02

说明:设备状态改变达到触发报警条件时,模组会立刻下发此指令通知 MCU 报警设备的信息。

有关命令帧格式,请参考 网关 MCU 对接通信协议 命令下发章节。

模组下发数据举例:

55 AA 00 C1 00 3B 02 7B 22 74 79 70 65 22 3A 30 2C 22 73 75 62 5F 69 64 22 3A 22 6D 6F 74 69 6F 6E 5F 73 65 6E 73 6F 72 5F 30 30 31 22 2C 22 64 70 5F 69 6E 66 22 3A 22 5C 22 70 69 72 5C 22 22 7D ED 
  • 55 AA 00 C1 00 3B:帧头0x55AA + 版本0x00 + 命令字0xC0 + 数据域字节长度0x003B

  • 02 7B 22 74 79 70 65 22 3A 30 2C 22 73 75 62 5F 69 64 22 3A 22 6D 6F 74 69 6F 6E 5F 73 65 6E 73 6F 72 5F 30 30 31 22 2C 22 64 70 5F 69 6E 66 22 3A 22 5C 22 70 69 72 5C 22 22 7D

    数据域,首字节为子命令字0x02,后面为真正的数据,转换ASCII 格式如下:

    {"type":0, "sub_id":"motion_sensor_001", "dp_inf":{"1":"pir"}}
    
  • “type”: 设备类型,0:普通设备,1:环境设备

  • “sub_id”: 设备id,

  • “dp_inf”: 报警设备的功能点信息,{“dpid”:value}

    • MCU收到后要先缓存设备报警信息,并以如下json格式组包,等到报警触发时,用dp26上报所有报警设备信息

      [{"nodeId":"motion_sensor_001", "dps":{"1":"pir"}}, ......]
      
    • nodeId字段为子设备id,dps字段为子设备报警的功能点信息

      MCU 应答数据举例:

      55 AA 00 C1 00 01 02 C3
      

设备报警延时状态同步0xC1/0x03

说明:设置报警延时>0时,设备状态触发报警时,模组会下发两次此指令:设备状态改变达到触发报警条件时,模组会立刻下发此指令通知 MCU 报警延时开始,数据为1;报警延时到后,模组会再次下发,数据为2(报警延时结束)

有关命令帧格式,请参考 网关 MCU 对接通信协议 命令下发章节。

模组下发数据举例:

55 AA 00 C1 00 02 03 01 C6 
  • 55 AA 00 C1 00 02:帧头0x55AA + 版本0x00 + 命令字0xC0 + 数据域字节长度0x0002

  • 03 01:数据域,首字节为子命令字0x03,后面为数据

0:报警延时未创建;

1:报警延时进行中;

2:报警延时结束;

MCU 应答数据举例:

55 AA 00 C1 00 01 03 C4

取消报警状态同步C1/01

说明:当通过App设置取消报警,模组以此条指令同步状态给mcu。

有关命令帧格式,请参考 网关 MCU 对接通信协议 命令下发章节。

模组下发数据举例:

55 AA 00 C1 00 02 01 00 C3 
  • 55 AA 00 C1 00 02:帧头0x55AA + 版本0x00 + 命令字0xC0 + 数据域字节长度0x0002

  • 01 00:数据域,首字节为子命令字0x01,后面为数据

0:取消报警;

MCU 应答数据举例:

55 AA 00 C1 00 01 01 C2

App 主动触发报警

安防网关能力

说明:如上图通过长按App上的按钮触发的设备报警,模组会通过dp45下发通知 MCU。

  • 长按求救按钮时,模组和MCU的串口数据交互包举例:
[2020-06-11, 17:37:04:657174]	模组发送:55 AA 00 0C 00 95 04 30 30 30 30 2D 03 00 8C 65 79 4A 7A 59 32 56 75 5A 53 49 36 49 6E 42 68 62 6D 6C 6A 49 69 77 69 64 47 6C 6B 49 6A 6F 69 59 54 5A 69 4F 57 45 31 4F 44 51 74 4D 44 56 6B 4E 53 30 30 4E 32 4D 35 4C 57 4A 6A 5A 47 49 74 4E 47 5A 69 4F 47 49 32 4E 6A 55 30 4E 54 49 30 49 69 77 69 64 48 6C 77 5A 53 49 36 49 6E 4E 76 63 79 49 73 49 6E 56 70 5A 43 49 36 49 6D 46 35 4D 54 55 34 4E 6A 67 32 4E 54 63 79 4E 7A 41 30 4F 54 5A 73 4D 56 49 30 49 6E 30 3D A4 
base64解码后的数据:{"scene":"panic", "tid":"a6b9a584-05d5-47c9-bcdb-4fb8b6654524", "type":"sos", "uid":"ay15868657270496l1R4"},MCU只需关注"scene"字段值即可
求救:"scene":"panic"
紧急:"scene":"emergency"
火警:"scene":"fire"
[2020-06-11, 17:37:04:663377]	MCU上报:55 AA 00 0D 00 0A 04 30 30 30 30 20 04 00 01 01 00 
[2020-06-11, 17:37:04:664011]    MCU上报:55 AA 00 C1 00 01 00 11 D2
[2020-06-11, 17:37:04:664307]	MCU上报:55 AA 00 0D 00 95 04 30 30 30 30 2D 03 00 8C 65 79 4A 7A 59 32 56 75 5A 53 49 36 49 6E 42 68 62 6D 6C 6A 49 69 77 69 64 47 6C 6B 49 6A 6F 69 59 54 5A 69 4F 57 45 31 4F 44 51 74 4D 44 56 6B 4E 53 30 30 4E 32 4D 35 4C 57 4A 6A 5A 47 49 74 4E 47 5A 69 4F 47 49 32 4E 6A 55 30 4E 54 49 30 49 69 77 69 64 48 6C 77 5A 53 49 36 49 6E 4E 76 63 79 49 73 49 6E 56 70 5A 43 49 36 49 6D 46 35 4D 54 55 34 4E 6A 67 32 4E 54 63 79 4E 7A 41 30 4F 54 5A 73 4D 56 49 30 49 6E 30 3D A5
[2020-06-11, 17:37:04:664307]   模组回复:55 AA 00 C1 00 01 00 00 C1
  • 模组下发的dp45数据内容为basse64编码,解码参考代码如下:

    int iot_base64_decode( const char *base64_data, unsigned int base64_len, unsigned char *rawdata, unsigned int data_len);
    
    const char base64_table[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};
    
    // 将base_table中的字符ASCII转化为索引号
    static unsigned char base64code_convert_index(const char base64)
    {
        unsigned char index = 0;
        //  [0:25]: A ~ Z = 65 ~ 90
        if ((base64 >= 65) && (base64 <= 90)){
            index = base64 - 65;
        }
        // [26:51]:a ~ z = 97 ~ 122
        else if ((base64 >= 97) && (base64 <= 122)){
            index = base64 - (97-26);
        }
        // [52:61]:0 ~ 9 = 48 ~ 57
        else if ((base64 >= 48) && (base64 <= 57)){
            index = base64 + (52-48);
        }
        else if( base64 == '+'){
            index = 62;
        }
        else if (base64 == '/'){
            index = 63;
        }
        else if (base64 == '='){
            return 0;
        }else{
            return 0xFF; // 非法
        }
        
        return index;
    }
    /*****************************************************************
     * @Function: iot_base64_encode
     * @Description: 将base64字符串数据编码为二进制数据
     * @Param: *base64_data, base64字符串
     * @Param: base64_len, base64字符串的长度
     * @Param: *rawdata, 解码后的二进制数据首地址
     * @Param: data_len, rawdata地址空间可写入的最大字节数
     * @Return: 小于零-失败,否则返回实际解码后的二进制数据长度
     *****************************************************************/
    int iot_base64_decode( const char *base64_data, unsigned int base64_len, unsigned char *rawdata, unsigned int data_len)
    {
        if (base64_len%4 != 0){
            // printf("base64 data length is error\n");
            return -1;
        }
        
        // 参数长度合法性判断,防止内存越界
        if(data_len < base64_len/4*3){
            // printf("data_len is too small\n");
            return -2;
        }
        
        unsigned int i,j;
        unsigned int temp = 0, actual_len = 0;
        unsigned char index[4] = {0};
         
        for ( i = 0, j = 0; i < base64_len; i += 4, j += 3)
        {
            index[0] = base64code_convert_index(base64_data[i]);
            index[1] = base64code_convert_index(base64_data[i+1]);
            index[2] = base64code_convert_index(base64_data[i+2]);
            index[3] = base64code_convert_index(base64_data[i+3]);
            if ((index[0] == 0xFF) || (index[1] == 0xFF) || 
                (index[2] == 0xFF) || (index[3] == 0xFF)){
                // printf("base have illegal char\n");
                return -3; // 有非法字符
            }
    
            // 4个base字符拼成3个字节放到temp变量
            temp = (index[0] << 18) | (index[1] << 12) | (index[2] << 6) | index[3];
            
            if ((base64_data[i+2] == '=') && (base64_data[i+3] == '=')){
                rawdata[j] = temp >> 16;
                actual_len = j+1;
            }else if(base64_data[i+3] == '='){
                rawdata[j] = temp >> 16;
                rawdata[j+1] = (temp >> 8)&0xFF;
                actual_len = j+2;
            }else{
                rawdata[j] = temp >> 16;
                rawdata[j+1] = (temp >> 8)&0xFF;
                rawdata[j+2] = temp & 0xFF;
                actual_len = j+3;
            }
        }
        
        return actual_len;
    }