Basic Configuration Interfaces

  1. Set Wireless Network Parameters
  2. 设置无线参数(无需签名校验)
  3. 获取无线参数
  4. 获取无线扫描AP列表
  5. 获取无线扫描AP列表 (无需签名校验)
  6. 获取IP参数
  7. 设置IP参数
  8. 调焦
  9. 手动聚焦
  10. 自动聚焦
  11. 调焦聚焦复位
  12. 获取调焦和聚焦参数
  13. 设置夜视模式
  14. 获取夜视模式
  15. 设置动态侦测
  16. 获取动态侦测参数
  17. 设置IPC名称
  18. 获取IPC名称
  19. 设置指示灯开关
  20. 获取指示灯开关
  21. 设置画面旋转角度
  22. 获取画面旋转角度
  23. 获取支持的画面旋转角度
  24. 格式化存储卡
  25. 获取存储卡状态
  26. 获取人脸算法参数
  27. 设置人脸算法参数
  28. 获取人流统计参数
  29. 设置人流统计参数

1. Set Wireless Network Parameters

Description

This interface is used to configure the SSID and the password used to connect an IPC and its AP.

Interface

public void setWifiConf(String deviceId, String ssid, String password, RpcCallback‹RpcResponse› callback);

Parameters

Parameter Description Example
deviceIdIPC SNC201D98T00094
ssid The name of the wireless AP to be connected (SSID), which shall not exceed 32 characters. WeWork
password The password of the AP to be connected. If there is no password, leave it empty (shall not exceed 64 characters, and it does not support WEP). 12345678
callback The calling result.

Response Parameter

Field Type Description
code int The return code indicating the operation result;
The return codes of this interface contain 0, 1, 2, 3, 5, 7, 100, 101. Please refer to RPCErrorCode Class for details.

2. Set Wireless Network Parameters (No Signature Authentication Required)

Description

After using this interface, you don’t have to verify (through signature authentication) the SSID and password used to connect an IPC and its AP before activation; an activation will invalidate this interface.

Interface

public void setWifiConfWithoutAuth(String deviceId, String ssid, String password, RpcCallback‹RpcResponse› callback);

Parameters

Parameter Description Example
deviceIdIPC SNC201D98T00094
ssidThe name of the wireless AP to be connected (SSID), which shall not exceed 32 characters. WeWork
passwordThe password of the AP to be connected. If there is no password, leave it empty (shall not exceed 64 characters, and it does not support WEPs). 12345678
callbackThe calling result.

Response Parameter

FieldType Description
codeintThe return code indicating the operation result;
The return codes of this interface contain 0, 1, 2, 3, 5, 7, 100, 101. Please refer to RPCErrorCode Class for details.

3. Get Wireless Network Parameters

Description

This interface is used to get the wireless network parameters of the IPC.

Interface

public void getWifiConf(String deviceId, RpcCallback‹RpcResponse‹WifiConfiguration›› callback);

Parameters

Parameter Description Example
deviceId IPC SN C201D98T00094
callback The calling result.

Response Parameters

Field Type Description
codeintThe return code indicating the operation result;
The return codes of this interface contain 0, 1, 2, 3, 5, 7, 100, 101. Please refer to RPCErrorCode Class for details.
dataWifiConfiguration This field shows only when the return code indicates a successful operation. Please refer to RPCResponse.WifiConfBean for details.

Sample Callback

The implementations of subsequent interface callbacks are similar to this one.

new RpcCallback‹RpcResponse‹WifiConfiguration››() {
    @Override
    public void onComplete(RpcResponse‹WifiConfiguration› result) {
        if (result.code() == RpcErrorCode.SUCCESS) {
            WifiConfiguration wifiConf = result.data();
        } else {
            shotToast("response.code: " + result.code());
        }
    }

    @Override
    public void onError(Throwable t) {
        shotToast("Exception: " + t.getMessage());
    }
});

4. Get the List of APs

Description

This interface is used to get the list of APs wirelessly scanned by the IPC.

Interface

public void getApList(String deviceId, RpcCallback‹RpcResponse‹ScanResultCollection›› callback);

Parameters

ParameterDescription Example
deviceIdIPC SNC201D98T00094
callbackThe calling result.

Response Parameters

Field Type Description
codeint The return code indicating the operation result;
The return codes of this interface contain 0, 1, 2, 3, 5, 7, 100, 101. Please refer to RPCErrorCode Class for details.
dataScanResultCollectionThis field shows only when the return code indicates a successful operation. Please refer to RpcResponse.ScanResultCollection for details.

5. Get the List of APs (No Signature Authentication Required)

Description

This interface is used to get the list of APs wirelessly scanned by the IPC without any signature authentication. An activation will invalidate this interface.

Interface

public void getApListWithoutAuth(String deviceId, RpcCallback‹RpcResponse‹ScanResultCollection›› callback);

Parameters

ParameterDescription Example
deviceIdIPC SNC201D98T00094
callbackThe calling result.

Response Parameters

FieldType Description
codeint The return code indicating the operation result;
The return codes of this interface contain 0, 1, 2, 3, 5, 7, 100, 101. Please refer to RPCErrorCode Class for details.
dataScanResultCollectionThis field shows only when the return code indicates a successful operation. Please refer to RpcResponse.ScanResultCollection for details

6. Get IP Parameters of IPC

Description

This interface is used to get the IP parameters of IPC

Interface

public void getIpConfiguration(String deviceId, RpcCallback‹RpcResponse‹IpConfiguration›› callback);

Parameters

ParameterDescriptionExample
deviceIdIPC SNC201D98T00094
callbackThe calling result.

Response Parameters

Field Type Description
code int The return code indicating the operation result;
The return codes of this interface contain 0, 1, 2, 3, 5, 7. Please refer to RPCErrorCode Class for details.
dataIpConfiguration This field shows only when the return code indicates a successful operation. Please refer to RpcResponse.IpConfiguration for details

7. Set IP Parameters of IPC

Description

This interface is used to set the IP parameters of IPC

Interface

public void setIpConfiguration(String deviceId, Map‹String, String› options, RpcCallback‹RpcResponse› callback);

参数说明

ParameterDescription Example
deviceIdIPC SNC201D98T00094
optionsConfigurable parameter set for dynamic detectionSee option description in the table below
callbackThe calling result.

option description

Name TypeDescriptionRequiredExample
protoStringDHCP or static Y static
ipaddrString IP address N192.168.1.102
netmaskString Subnet Mask N 255.255.255.0
gatewayString Gateway N 192.168.1.1
dns1 String dns1 server ip N 202.96.128.86
dns2String dns2 server ip N202.96.134.166

Response Parameter

FieldType Description
code int The return code indicating the operation result;
The return codes of this interface contain 0, 1, 2, 3, 5, 7. Please refer to RPCErrorCode Class for details.

8. Adjust Focal Length

Description

This interface is used to adjust the focal length according to the actual environment, in order to zoom in or zoom out. All interfaces such as focusing and focusing are only supported by zoom lens. At present, only SUNMI AI camera supports zoom lens.

Interface

public void setZoom(String deviceId, int zoom, RpcCallback‹RpcResponse› callback);

Parameters

Parameter DescriptionExample
deviceIdIPC SNC201D98T00094
zoomThe focal length. An appropriate one ranges [0, 500]. 200
callbackThe calling result.

Response Parameter

FieldTypeDescription
codeintThe return code indicating the operation result;
The return codes of this interface contain 0, 1, 2, 3, 5, 7, 110. Please refer to RPCErrorCode Class for details.

9. Manual Focus

Description

The lens will automatically focus after the focal length has been adjusted. However, you can adjust the focus manually with this interface when a slight modification is needed.

Interface

public void manualFocus(String deviceId, int focus, RpcCallback‹RpcResponse› callback);

Parameters

ParameterDescriptionExample
deviceIdIPC SNC201D98T00094
focusThe focus parameter (the value of manual adjustment). An appropriate one ranges [0, 780]. 200
callbackThe calling result.

Response Parameter

Field Type Description
code int The return code indicating the operation result;
The return codes of this interface contain 0, 1, 2, 3, 5, 7, 110. Please refer to RPCErrorCode Class for details.

10. Auto Focus

Description

IPC will automatically focus after the focal length has been set. This interface is used to set the autofocus point.

Interface

public void autoFocus(String deviceId, int focus_x, int focus_y, RpcCallback‹RpcResponse› callback);

Parameters

Parameter Description Example
deviceIdIPC SNC201D98T00094
focus_x The percentage indicating the pixel of the focus point in x axis. An appropriate one ranges [0, 100]. 50
focus_y The percentage indicating the pixel of the focus point in y axis. An appropriate one ranges [0, 100]. 50
callbackThe calling result.

Response Parameter

Field Type Description
code int The return code indicating the operation result;
The return codes of this interface contain 0, 1, 2, 3, 5, 7, 112. Please refer to RPCErrorCode Class for details.

11. 调焦聚焦复位

描述

用户可以通过此接口直接复位焦距和聚焦的参数。

接口

public void resetZoomFocus(String deviceId, RpcCallback‹RpcResponse› callback);

参数说明

参数名称描述示例
deviceIdIPC序列号C201D98T00094
callback调用结果

响应参数

字段名称 类型 描述
code int 返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7,见错误码的描述

12. 获取调焦和聚焦参数

描述

获取当前IPC镜头的调焦聚焦参数。

接口

public void getZoomFocusConf(String deviceId, RpcCallback‹RpcResponse‹LensConfiguration›› callback);

参数说明

参数名称描述示例
deviceIdIPC序列号C201D98T00094
callback调用结果

响应参数

参数名称类型 描述
code int 返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7,见错误码的描述
dataLensConfiguration返回码成功才会有此字段,详见RpcResponse.LensConfiguration

13. 设置夜视模式

描述

配置镜头的夜视模式。

接口

public void setIrMode(String deviceId, int irmode, RpcCallback‹RpcResponse› callback);

参数说明

参数名称描述 示例
deviceIdIPC序列号C201D98T00094
irmode 0表示关闭,1表示开启,2表示自动。一般选2。 2
callback调用结果

响应参数

字段名称 类型 描述
code int 返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7、113,见错误码的描述

14. 获取夜视模式

描述

获取当前IPC的夜视模式。

接口

public void getIrMode(String deviceId, RpcCallback‹RpcResponse‹IrConfiguration›› callback);

参数说明

参数名称描述示例
deviceIdIPC序列号C201D98T00094
callback调用结果

响应参数

参数名称类型 描述
code int 返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7,见错误码的描述
dataIrConfiguration返回码成功才会有此字段,详见RpcResponse.IrConfiguration

15. 设置动态侦测

描述

IPC的动态侦测支持根据画面变化和声音变化灵敏度来检测和报警,通过本API可以设置相关灵敏度和动态侦测的时间。

接口

public void setMotionDetectConfig(String deviceId, Map‹String, String› options, RpcCallback‹RpcResponse› callback);

参数说明

参数名称描述示例
deviceIdIPC序列号C201D98T00094
options可设置的动态侦测的参数集合,option说明中的所有参数都需要转换成String类型传入。见下表option说明
callback调用结果

option说明

参数名称 类型 描述 是否必须 示例
motion_level int范围[0, 3],0表示关闭,数值越大,越灵敏。 Y 2
audio_level int 范围[0, 3],0表示关闭,数值越大,越灵敏。 Y 2
weekday int 以周为一个循环,用0xYY来表示选择哪一天,具体是0x80直接表示7×24小时,其余的,
以7bit来表示哪一天被选上,0x01表示选择周一,0x02表示选择周二,0x40表示选择
周天,0x7f表示选择一个礼拜的7天,与0x80的区别只是0x80直接默认724小时,而
0x7f选了7天后,还可以设置具体的开始时间和结束时间。
Y 128(0x80 的十进制)
start_time long用分钟来表示,以一天24小时为例,以分钟为最小粒度,总共24*60这样的时间数值,
60表示01:00,121表示02:01,依次类推。范围[0,1440]
Y 200
stop_time long 用分钟来表示,以一天24小时为例,以分钟为最小粒度,总共24*60这样的时间数值,
60表示01:00,121表示02:01,依次类推。范围[0,1440]
Y 400

响应参数

字段名称 类型 描述
code int 返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7,见错误码的描述

16. 获取动态侦测参数

描述

获取当前IPC镜头的动态侦测参数。

接口

public void getMotionDetectConfig(String deviceId, RpcCallback‹RpcResponse‹MotionDetectConfig›› callback);

参数说明

本接口没有私有参数,公共参数见HTTP接口调用

参数名称描述示例
deviceIdIPC序列号C201D98T00094
callback调用结果

响应参数

参数名称类型 描述
code int 返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7,见错误码的描述
dataMotionDetectConfig返回码成功才会有此字段,详见RpcResponse.MotionDetectConfig

17. 设置IPC名称

描述

用户可以设置IPC的名称,以便区分不同的IPC设备。

接口

public void updateName(String deviceId, String name, RpcCallback‹RpcResponse› callback);

参数说明

参数名称描述 示例
deviceIdIPC序列号C201D98T00094
name 36个字符以内,12汉字以内 示例名称
callback调用结果

响应参数

字段名称 类型 描述
code int 返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7、118,见错误码的描述

18. 获取IPC名称

描述

获取当前IPC的名称。

接口

public void getName(String deviceId, RpcCallback‹RpcResponse‹IpcName›› callback);

参数说明

本接口没有私有参数,公共参数见HTTP接口调用

参数名称描述示例
deviceIdIPC序列号C201D98T00094
callback调用结果

响应参数

参数名称类型 描述
code int 返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7,见错误码的描述
dataIpcName 返回码成功才会有此字段,详见RpcResponse.IpcName

19. 设置指示灯开关

描述

设置指示灯是否需要关闭。

接口

public void setLedSwitch(String deviceId, int ledSwitch, RpcCallback‹RpcResponse› callback);

参数说明

参数名称描述 示例
deviceIdIPC序列号C201D98T00094
led_switch 0表示关闭指示灯,1表示开启指示灯,即可以亮 1
callback调用结果

响应参数

字段名称 类型 描述
code int 返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7、119, 见错误码的描述

20. 获取指示灯开关

描述

获取当前IPC的指示灯状态。

接口

public void getLedSwitch(String deviceId, RpcCallback‹RpcResponse‹LedConfiguration›› callback);

参数说明

本接口没有私有参数,公共参数见HTTP接口调用

参数名称描述示例
deviceIdIPC序列号C201D98T00094
callback调用结果

响应参数

参数名称类型 描述
code int 返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7, 见错误码的描述
dataLedConfiguration返回码成功才会有此字段,详见RpcResponse.LedConfiguration

21. 设置画面旋转角度

描述

设置拍摄的画面是否需要旋转一定角度,可用的旋转角度可通过获取支持的画面旋转角度获取到。

接口

public void setRotation(String deviceId, int rotation, RpcCallback‹RpcResponse› callback);

参数说明

这里只列出接口的私有参数,公共参数见HTTP接口调用

参数名称描述 示例
deviceIdIPC序列号C201D98T00094
rotation 画面旋转角度
对于FM010,支持的参数有0,90,180,270;
对于FM020,支持的参数有0,180
180
callback调用结果

响应参数

字段名称 类型 描述
code int 返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7、120, 见错误码的描述

22. 获取画面旋转角度

描述

获取当前IPC当前的画面旋转角度。

接口

public void getRotation(String deviceId, RpcCallback‹RpcResponse‹Rotation›› callback);

参数说明

参数名称描述示例
deviceIdIPC序列号C201D98T00094
callback调用结果

响应参数

参数名称类型 描述
code int 返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7, 见错误码的描述
dataRotation返回码成功才会有此字段,详见RpcResponse.Rotation
对于FM010,支持的参数有0,90,180,270;
对于FM020,支持的参数有0,180

23. 获取支持的画面旋转角度

描述

获取当前IPC设备支持的画面旋转角度。

接口

public void getSupportRotationAngles(String deviceId, RpcCallback‹RpcResponse‹SupportRotations›› callback);

参数说明

参数名称描述示例
deviceIdIPC序列号C201D98T00094
callback调用结果

响应参数

参数名称类型 描述
code int 返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7, 见错误码的描述
dataSupportRotations返回码成功才会有此字段,详见RpcResponse.SupportRotations
对于FM010,支持的参数有0,90,180,270;
对于FM020,支持的参数有0,180

24. 格式化存储卡

描述

格式化插入IPC里面的存储卡。

接口

public void formatMemoryCard(String deviceId, RpcCallback‹RpcResponse› callback);

参数说明

参数名称描述示例
deviceIdIPC序列号C201D98T00094
callback调用结果

响应参数

参数名称类型 描述
code int 返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7、220、221, 见错误码的描述

25. 获取存储卡状态

描述

获取IPC上存储卡状态

接口

public void getMemoryCardStatus(String deviceId, RpcCallback‹RpcResponse‹ExternalStorage›› callback);

参数说明

参数名称描述示例
deviceIdIPC序列号C201D98T00094
callback调用结果

响应参数

类型 描述
int返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7, 见错误码的描述
ExternalStorage返回码成功才会有此字段,详见RpcResponse.ExternalStorage

26. 获取人脸算法参数

描述

获取人脸算法参数,目前仅支持人脸图像优选时间参数。

接口

public void getAiFaceConfig(String deviceId, RpcCallback‹RpcResponse‹AiFaceConfig›› callback);

参数说明

参数名称描述示例
deviceIdIPC序列号C201D98T00094
callback调用结果

响应参数

类型 描述
int返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7, 见错误码的描述
AiFaceConfig返回码成功才会有此字段,详见RpcResponse.AiFaceConfig

27. 设置人脸算法参数

描述

设置人脸算法参数,目前仅支持人脸图像优选时间参数。

接口

public void setAiFaceConfig(String deviceId, Map‹String, String› options, RpcCallback‹RpcResponse› callback);

参数说明

参数名称描述示例
deviceIdIPC序列号C201D98T00094
options人脸算法相关参数,option说明中的所有参数都需要转换成String类型传入。见下表option说明。
callback调用结果

option说明

参数名称类型描述是否必须示例
optimize_secondsint人脸图像优选时间,人脸算法从人脸出现后在指定的时间范围内选取人脸图像质量较好的进行识别,单位:秒,取值范围[1,6]。Y6

响应参数

类型 描述
int返回码,表示操作的结果;
本接口返回码有:0、1、3、5、7, 见错误码的描述

28. 获取人流统计参数

描述

获取IPC的人流统计参数,目前包含人脸识别去重间隔和人脸识别模式两个参数。

接口

public void getPeopleFlowStatConfig(String deviceId, RpcCallback‹RpcResponse‹PeopleFlowStatConfig›› callback);

参数说明

参数名称描述示例
deviceIdIPC序列号C201D98T00094
callback调用结果

响应参数

字段名称类型描述
codeint返回码,表示操作的结果;
本接口返回码有:0、1、2、3、5、7,见错误码的描述
dataPeopleFlowStatConfig返回码成功才会有此字段,详见RpcResponse.PeopleFlowStatConfig

29. 设置人流统计参数

描述

设置IPC的人流统计参数,目前包含人脸识别去重间隔和人脸识别模式两个参数。

接口

public void setPeopleFlowStatConfig(String deviceId, Map‹String, String› options, RpcCallback‹RpcResponse› callback);

参数说明

参数名称描述示例
deviceIdIPC序列号C201D98T00094
options人流统计参数,option说明中的所有参数都需要转换成String类型传入。见下表option说明
callback调用结果

option说明

名称类型描述是否必须示例
facerecog_intervalint人脸识别去重间隔,取值[0,86400]。N60
customer_judgemodeint人脸识别模式,0-抓拍模式,1-正常模式,2-未划线。N0

响应参数

字段名称类型描述
codeint返回码,表示操作的结果;
本接口返回码有:0、1、2、3、5、7,见错误码的描述

增值服务-巡店服务 接口

1 概述

为了方便Saas合作伙伴可以直接在其平台上使用商米提供的巡店服务业务数据,平台提供了巡店统计数据接口。Saas合作伙伴可以通过接口调用获取巡店业务的统计数据。

2 接口规范

2.1 协议说明

对接的openAPI接口目前只开放HTTPS方式,所有的消息一律采用POST方式。

注:消息体大小不得超过1M,超过1M的请求,直接拒绝!

Content-Typeapplication/x-www-form-urlencoded
数据格式返回为JSON格式
字符编码UTF-8字符编码
签名算法MD5
签名规则参考2.2 签名规则

2.2 签名规则

参考《鉴权认证》文档。

2.3 公共参数

参数名必填类型说明
app_idstring唯一标识接入身份,联系商米数字店铺提供
randomstring随机字符串,由数字和字母组成,长度范围为6-10位
timestampint当前的unix timestamp,精度到秒级,10位数字
signstring签名信息,详见2.2

3 巡店数据统计接口

3.1 接口描述

巡店数据统计接口用于Saas合作方获取巡店服务的各种数据统计。

3.2 接口列表

接口名称接口描述
/service/patrol/stat/groupByInspector获取巡检人巡查工作情况统计
/service/patrol/stat/groupByShop 获取门店下巡查工作数据统计
/service/patrol/stat/groupByTemplate获取模板使用情况数据统计
/service/patrol/stat/groupByCheckItem获取模板-检查项使用情况数据统计

3.3 接口详情

3.3.1 获取巡检人巡查工作数据统计

接口描述:通过本接口调用,可以获取到指定门店下基于巡检人统计的巡检人工作数据统计

接口链接:/service/patrol/stat/groupByInspector

接口版本:v2.0

接口参数:

参数名称是否必须类型说明示例
sunmi_shop_no string商米数字店铺平台的门店组织编号560279010307
periodint统计周期1

period参数说明:

参数取值说明
1近7天数据统计
2近30天数据统计
3近90天数据统计
4近180天数据统计
5近365天数据统计

请求示例:

  "method": "POST",
  "url": "https://store.uat.sunmi.com/openapi/service/patrol/stat/groupByInspector",
  "headers": {
    "Content-Type": "application/x-www-form-urlencoded"
  },
  formData: {
    "sunmi_shop_no": "560279010307",
    "app_id": "LMWWQVTW4QGCC",
    "timestamp": 1581383983,
    "random": "5dsf6698",
    "sign": "33C18A18282733A71F998BB5A5E4319D"
  }

返回值:

{
    "data": {
        "patrol_inspector_summary_list": [
            {
                "inspection_user_name": "小明",
                "plan_task_undone_count": 0,
                "plan_task_done_count": 7,
                "plan_task_doing_count": 0,
                "plan_task_total_count": 28,
                "check_total_count": 349,
                "check_done_count": 2,
                "total_time_duration": 295645,
                "task_normal_count": 7,
                "task_non_count": 1602,
                "task_total_count": 1609,
                "task_realtime_count": 699,
                "task_snapshot_count": 523,
                "task_evaluate_count": 40,
                "last_inspection_time": 1600867095
            },
            {
                "inspection_user_name": "xiaohong",
                "plan_task_undone_count": 0,
                "plan_task_done_count": 3,
                "plan_task_doing_count": 0,
                "plan_task_total_count": 12,
                "check_total_count": 9,
                "check_done_count": 4,
                "total_time_duration": 2101,
                "task_normal_count": 3,
                "task_non_count": 81,
                "task_total_count": 84,
                "task_realtime_count": 26,
                "task_snapshot_count": 42,
                "task_evaluate_count": 7,
                "last_inspection_time": 1599535469
            },
            {
                "inspection_user_name": "kunkun",
                "plan_task_undone_count": 0,
                "plan_task_done_count": 0,
                "plan_task_doing_count": 0,
                "plan_task_total_count": 0,
                "check_total_count": 0,
                "check_done_count": 0,
                "total_time_duration": 21,
                "task_normal_count": 0,
                "task_non_count": 2,
                "task_total_count": 2,
                "task_realtime_count": 0,
                "task_snapshot_count": 0,
                "task_evaluate_count": 2,
                "last_inspection_time": 1597661382
            },
            {
                "inspection_user_name": "小白",
                "plan_task_undone_count": 0,
                "plan_task_done_count": 0,
                "plan_task_doing_count": 0,
                "plan_task_total_count": 0,
                "check_total_count": 14,
                "check_done_count": 0,
                "total_time_duration": 13994,
                "task_normal_count": 0,
                "task_non_count": 48,
                "task_total_count": 48,
                "task_realtime_count": 0,
                "task_snapshot_count": 0,
                "task_evaluate_count": 48,
                "last_inspection_time": 1599542974
            }
        ]
    },
    "code": 0,
    "msg": "succeed"
}

返回参数说明:

参数名类型说明
inspection_user_namestring巡检人姓名
plan_task_undone_countint计划任务过期未执行数
plan_task_done_countint计划任务已完成数
plan_task_doing_count int计划任务待执行数
plan_task_total_count int计划任务总数
check_total_countint应审核问题总数
check_done_countint 审核完成数
total_time_durationint 巡检时长(秒)
task_normal_countint任务巡店次数
task_non_countint非任务巡店次数
task_total_countint巡店总次数
task_realtime_countint实时巡店次数
task_snapshot_countint抓拍巡店次数
task_evaluate_countint门店考评次数
last_inspection_timeint最后一次巡检时间(秒)

错误码:

错误码说明

3.3.2 获取门店下巡查工作数据统计

接口描述:通过本接口调用,可以获取到指定门店下基于门店统计的巡检工作数据统计

接口链接: /service/patrol/stat/groupByShop

接口版本:v2.0

接口参数:

参数名称是否必须类型说明示例
sunmi_shop_no string商米数字店铺平台的门店组织编号列表560279010307
periodint统计周期1

period参数:

参数取值说明
1近7天数据统计
2近30天数据统计
3近90天数据统计
4近180天数据统计
5近365天数据统计

请求示例:

  "method": "POST",
  "url": "https://store.uat.sunmi.com/openapi/service/patrol/stat/groupByShop",
  "headers": {
    "Content-Type": "application/x-www-form-urlencoded"
  },
  formData: {
    "sunmi_shop_no": "560279010307",
    "app_id": "LMWWQVTW4QGCC",
    "timestamp": 1581383983,
    "random": "5dsf6698",
    "sign": "33C18A18282733A71F998BB5A5E4319D"
  }

返回值:

{
    "data": {
        "patrol_shop_summary_list": [
            {
                "check_total_count": 0,
                "scoreless_total_count": 0,
                "avg_score": 5.58,
                "rectify_count": 438,
                "rectify_done_count": 398,
                "realtime_need_count": 393,
                "realtime_total_count": 777,
                "snapshot_problem_count": 286,
                "snapshot_total_count": 645,
                "evaluate_need_count": 45,
                "evaluate_total_count": 126
            }
        ]
    },
    "code": 0,
    "msg": "succeed"
}

返回参数说明:

参数名类型说明
check_total_countint考评检查项总数
scoreless_total_countint有问题检查项数
avg_scorefloat考评得分,百分制
rectify_countint应整改问题数
rectify_done_countint整改完成数
realtime_need_countint 实时巡店需整改数
realtime_total_countint 实时巡店总次数
snapshot_problem_countint抓拍巡检有问题数
snapshot_total_countint抓拍巡检总次数
evaluate_need_countint门店考评需整改数
evaluate_total_countint门店考评总次数

错误码:

错误码说明

3.3.3 获取模板使用情况数据统计

接口描述: 通过本接口调用,可以获取到指定门店下基于门店统计的巡检工作数据统计

接口链接: /service/patrol/stat/groupByTemplate

接口版本:v2.0

接口参数:

参数名称是否必须类型说明示例
sunmi_shop_no string商米数字店铺平台的门店组织编号列表560279010307
periodint统计周期1

period参数说明:

参数取值说明
1近7天数据统计
2近30天数据统计
3近90天数据统计
4近180天数据统计
5近365天数据统计

请求示例:

  "method": "POST",
  "url": "https://store.uat.sunmi.com/openapi/service/patrol/stat/groupByTemplate",
  "headers": {
    "Content-Type": "application/x-www-form-urlencoded"
  },
  formData: {
    "sunmi_shop_no": "560279010307",
    "app_id": "LMWWQVTW4QGCC",
    "timestamp": 1581383983,
    "random": "5dsf6698",
    "sign": "33C18A18282733A71F998BB5A5E4319D"
  }

返回值:

{
    "data": {
        "patrol_template_summary_list": [
            {
                "template_id": "549755813846",
                "template_name": "你好世界",
                "total_score": 3925,
                "total_full_score": 5240,
                "total_count": 126
            }
        ]
    },
    "code": 0,
    "msg": "succeed"
}
参数名类型说明
template_idint模板id
template_namestring模板名称
total_scoreint门店下模板累计得分
total_full_scoreint 门店下模板累计总分
total_countint总共使用次数

错误码:

错误码说明

3.3.4 获取模板-检查项使用情况数据统计

接口描述: 通过本接口调用,可以获取到指定门店下基于模板统计的巡检工作数据统计

接口链接: /service/patrol/stat/groupByCheckItem

接口版本:v2.0

接口参数:

参数名称是否必须类型说明示例
sunmi_shop_no string商米数字店铺平台的门店组织编号列表560279010307
periodint统计周期1

period参数说明:

参数取值说明
1近7天数据统计
2近30天数据统计
3近90天数据统计
4近180天数据统计
5近365天数据统计

请求示例:

  "method": "POST",
  "url": "https://store.uat.sunmi.com/openapi/service/patrol/stat/groupByCheckItem",
  "headers": {
    "Content-Type": "application/x-www-form-urlencoded"
  },
  formData: {
    "sunmi_shop_no": "560279010307",
    "app_id": "LMWWQVTW4QGCC",
    "timestamp": 1581383983,
    "random": "5dsf6698",
    "sign": "33C18A18282733A71F998BB5A5E4319D"
  }

返回值:

{
    "data": {
        "patrol_check_item_summary_list": [
            {
                "template_id": "549755813846",
                "check_item_name": "1",
                "check_score_count": 9,
                "check_total_count": 12
            },
            {
                "template_id": "549755813846",
                "check_item_name": "2dada方式方法将老豆腐江东父老的肌肤豆腐煎豆腐",
                "check_score_count": 1,
                "check_total_count": 1
            },
            {
                "template_id": "549755813846",
                "check_item_name": "调料归类正确",
                "check_score_count": 3,
                "check_total_count": 5
            },
            {
                "template_id": "549755813846",
                "check_item_name": "食品归类正确",
                "check_score_count": 4,
                "check_total_count": 5
            },
            {
                "template_id": "549755813846",
                "check_item_name": "食品细菌含量未超标",
                "check_score_count": 3,
                "check_total_count": 5
            },
            {
                "template_id": "549755813846",
                "check_item_name": "食材未过期",
                "check_score_count": 5,
                "check_total_count": 5
            },
            {
                "template_id": "549755813846",
                "check_item_name": "食材清洗干净",
                "check_score_count": 4,
                "check_total_count": 5
            }
        ]
    },
    "code": 0,
    "msg": "succeed"
}

返回参数说明:

参数名类型说明
template_idint模板id
check_item_namestring检查项名称
check_score_countint检查得分次数
check_total_countint 检查次数

错误码:

错误码说明

商品管理接口

3.1 接口描述

商品管理接口包括两部分:

一部分是商品新增修改删除接口,这是数字店铺的通用基础功能,很多设备和服务都会用到,参考单独的商品对接的文档。

另一部分是价签业务相关的功能,包括商品与价签的绑定解绑等,在本文中进行描述。

3.2 接口列表

接口名称接口
商品绑定价签/product/bindEsl
商品解绑价签/product/unbindEsl
获取商品绑定价签/product/getBindEslList
修改商品绑定价签的模板/product/updateTemplate
获取商品列表/product/getList
获取商品详情/product/getInfo

3.3 接口详情

3.3.1 商品绑定价签

接口描述:通过本接口调用,用户可以将商品与指定价签进行绑定,同时指定对应模板。绑定之后价签将开始刷图。

请求链接:/product/bindEsl

接口参数

参数名称是否必须类型说明
sunmi_shop_nostring商米数字店铺平台的门店组织编号
shop_idstring第三方对接软件中门店的标识,对接的软件提供 (作为门店唯一标识即可,shop_id与sunmi_shop_no可互为替代,使用时传输任意一个即可)
product_idstring商品数据库ID,如果进行了对接,和数据对接传过来的id一致
esl_code否(esl_code与esl_id至少提供一个)string电子价签8位ID(价签正面的条码)
esl_id否(esl_code与esl_id至少提供一个)string电子价签数据库ID转码
template_idstring模板数据库ID

返回值: 

{
    code:0,       /* 其他错误参考错误列表 */
    msg: "succeed",
    data: { }
}

错误码:

错误码说明
5000数据库错误
5020参数错误
5015非法商品
5343非法模板
5300非法基站
5301非法价签
5338价签已被其他店铺绑定   
5342非法价签图片
5006OSS错误
5041非法对接软件店铺


3.3.2 商品解绑价签

接口描述:通过本接口调用,用户可以将商品与指定价签解除绑定。解绑之后价签将刷新显示解绑模板对应的内容。

请求链接:/product/unbindEsl

接口参数

参数名称是否必须类型说明
sunmi_shop_nostring商米数字店铺平台的门店组织编号
shop_idstring第三方对接软件中门店的标识,对接的软件提供 (作为门店唯一标识即可,shop_id与sunmi_shop_no可互为替代,使用时传输任意一个即可)
esl_code否(esl_code与esl_id至少提供一个)string电子价签8位ID (价签正面的条码)
esl_id否(esl_code与esl_id至少提供一个)string电子价签数据库ID转码

返回值: 

{
    code:0,       /* 其他错误参考错误列表 */
    msg: "succeed",
    data: { }
}

错误码:

错误码说明
5000数据库错误
5020参数错误
5301非法价签
5320价签未绑定
5338价签已被其他店铺绑定    
5342非法价签图片
5006OSS错误
5041非法对接软件店铺

3.3.3 获取商品绑定价签

接口描述:通过本接口调用,用户可以获取商品绑定的价签列表。

请求链接:/product/getBindEslList

接口参数

参数名称是否必须类型说明
sunmi_shop_nostring商米数字店铺平台的门店组织编号
shop_idstring第三方对接软件中门店的标识,对接的软件提供 (作为门店唯一标识即可,shop_id与sunmi_shop_no可互为替代,使用时传输任意一个即可)
product_idstring商品数据库ID,如果进行了对接,和数据对接传过来的id一致

返回值: 

{
    code:0,       /* 其他错误参考错误列表 */
    msg: "succeed",
    data: { 
       "esl_list": [{
            "esl_id": ”1000“,
            "esl_code": "DJKS90EN",
            "template_id": ”10002“,
            "status": 1,
     } ...   
    ]}
}

错误码:

错误码说明
5000数据库错误
5020参数错误
5301非法价签
5015非法商品
5041非法对接软件店铺

3.3.4 修改商品绑定价签的模板

接口描述:通过本接口调用,用户可以更新商品对应的模板。

请求链接:/product/updateTemplate

接口参数

参数名称是否必须类型说明
sunmi_shop_nostring商米数字店铺平台的门店组织编号
shop_idstring第三方对接软件中门店的标识,对接的软件提供 (作为门店唯一标识即可,shop_id与sunmi_shop_no可互为替代,使用时传输任意一个即可)
product_idstring商品数据库ID,如果进行了对接,和数据对接传过来的id一致
template_idstring模板数据库ID


返回值
: 

{
    code:0,       /* 其他错误参考错误列表 */
    msg: "succeed",
    data: { }
}

错误码:

错误码说明
5000数据库错误
5020参数错误
5005文件错误
5006OSS错误
5343非法模板
5015非法商品
5342非法价签图片
5041非法对接软件店铺

3.3.5 获取商品列表

接口描述:通过本接口调用,用户可以使用关键字搜索商品。

请求链接:/product/getList

接口参数

参数名称是否必须类型说明
sunmi_shop_nostring商米数字店铺平台的门店组织编号
shop_idstring第三方对接软件中门店的标识,对接的软件提供 (作为门店唯一标识即可,shop_id与sunmi_shop_no可互为替代,使用时传输任意一个即可)
keywordstring关键字
page_numint页码
page_sizeint每页记录数

返回值: 

{
    "code": 0,       /* 其他错误参考错误列表 */
    "msg": "succeed"
    "data": {
        "total_count": 1,
        "product_list": [
            {
                "id": ,
                "name": ,
                "seq_num": ,
                "bar_code": ,
                "category_id": ,
                "price": ,
                "modified_time":
            }
        ],
    },
 }

错误码:(历史原因,成功为0,失败为1)

3.3.6 获取商品信息

接口描述:通过本接口调用,用户可以获取商品信息。

请求链接:/product/getInfo

接口参数

参数名称是否必须类型说明
sunmi_shop_nostring商米数字店铺平台的门店组织编号
shop_idstring第三方对接软件中门店的标识,对接的软件提供 (作为门店唯一标识即可,shop_id与sunmi_shop_no可互为替代,使用时传输任意一个即可)
product_idstring商品数据库ID,如果进行了对接,和数据对接传过来的id一致

返回值: 

{
    code:0,       /* 其他错误参考错误列表 */
    msg: "succeed",
    data: {
        "id":,
        "name":,
        "alias":,
        "seq_num":,
        "bar_code":,
        "qr_code":,
        "unit":,
        "spec":,
        "area":,
        "level":,
        "brand":,
        "expire_time":,
        "price":,
        "promote_price":,
        "member_price":,
    }
}

错误码:(历史原因,成功为0,失败为1)

特殊代码说明

一、获取商米设备标识

商米建议通过获取到以下内容来判断是否商米设备:

1.设备的品牌名 brand(如:SUNMI)

    商米的品牌名统一为 SUNMI

2.设备的系统型号 model(如:V1-B18)

    系统型号组成为 产品型号+硬件特性+‘-’+软件特性

    其中以V、M、P、L开头为手持设备,以T、D、S开头为横屏设备(截至2017年12月) 

3.设备的ROM版本号(如:1.1.0)。

4.设备的ROM顺序号(如:128)。

可以下载Demo,仿照Demo在自己项目src下面新建android.os包(固定写法),将SystemProperties.java放入该包下,按以下方法获取指定的值:

获取brand的代码为:

    String brand = SystemProperties.get(“ro.product.brand”);

获取model的方法为:

    String model = SystemProperties.get(“ro.product.model”);

获取ROM版本号的代码为:

    String versionname = SystemProperties.get(“ro.version.sunmi_versionname”);

获取ROM顺序号的方法为:

    String versioncode = SystemProperties.get(“ro.version.sunmi_versioncode”);

 二、获取设备的SN号

1.在AndroidManifest.xml中添加如下权限。

2.在需要的地方用以下代码获取商米SN号。

public static String getSN() {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

            return Build.getSerial();

        } else

            return Build.SERIAL;

    }

三、隐藏及恢复底部导航栏

(注:商米新开发了Kiosk霸屏模式,APP不用做任何修改,仅通过云端设置即可实现隐藏状态栏、导航栏并无法通过手势唤出。   该功能在T2、K1设备上已实现,其他设备上线进展请联系技术支持400-666-6509(00:00~24:00,7*24小时服务)。   建议合作伙伴使用商米Kiosk霸屏模式,已获得更好的体验)

Android系统默认提供了隐藏系统的导航栏的方法,但对于Dialog的支持较差,导致全屏对话框打开时先弹出导航栏再隐藏(闪屏),SunmiOS针对此问题进行了修复(V1系统固件版本252后支持,T1系统固件版本132后支持)

1.Activity的全屏化

——安卓默认支持

public class MainActivity extends AppCompatActivity {

    @Override

    public void onWindowFocusChanged(boolean hasFocus) {

        super.onWindowFocusChanged(hasFocus);

        SystemUIUtils.setStickFullScreen(getWindow().getDecorView());

    }

}

public class SystemUIUtils {

    public static void setStickFullScreen(View view) {

        int systemUiVisibility = view.getSystemUiVisibility();

        int flags = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE

                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar

                | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar

                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;

        systemUiVisibility |= flags;

        view.setSystemUiVisibility(systemUiVisibility);

    }

}

2.Dialog的全屏化

——原生系统下 AOSP 的Bug会导致全屏对话框打开时先弹出导航栏然后再隐藏导航栏(闪屏)。

public AlertDialog create(boolean fullscreen) {

    LayoutInflater inflater = LayoutInflater.from(context);

    final AlertDialog dialog = new AlertDialog(context,

            R.style.DialogStyle);

    if(fullscreen){

        SystemUIUtils.setStickFullScreen(dialog.getWindow().getDecorView());

    }

}

3.设置隐藏后显示导航栏

3.1.全局底部上划

——上划后底部导航栏显示4s,4s后底部导航栏隐藏

3.2.切换应用至其他APP(如APP内跳转至第三方应用、第三方APP弹窗等)

——切换至其他APP是否显示底部导航栏以第三方应用要求为准,切换至自己APP时底部导航栏消失

四、避免重复申请外设权限

当APP需要通过USB关联外设来实现业务时(比如连接USB打印机打印小票),安卓要求用户手动确认设备使用权限,来保障用户信息安全,防止木马非法入侵USB设备。

1.如何避免USB设备重新插拔同一个外设时,APP反复申请该外设权限

需要用户手动确认时,勾选“默认情况下用于该USB设备”,无法通过代码绕过该安全机制

验证DEMO

2.如何避免设备重启后,已勾选“默认情况下用于该USB设备”的APP仍反复申请同一个外设的使用权限

2.1.在APP的AndroidManifest中指定某个Activity部分中,添加如下代码

                

2.2.在该目录下创建xml文档

    

其中,class的值需要和要连接的外设类型一致,外设class参照表如下

    /**

     * USB class indicating that the class is determined on a per-interface basis.

     */

    public static final int USB_CLASS_PER_INTERFACE = 0;

    /**

     * USB class for audio devices.

     */

    public static final int USB_CLASS_AUDIO = 1;

    /**

     * USB class for communication devices.

     */

    public static final int USB_CLASS_COMM = 2;

    /**

     * USB class for human interface devices (for example, mice and keyboards).

     */

    public static final int USB_CLASS_HID = 3;

    /**

     * USB class for physical devices.

     */

    public static final int USB_CLASS_PHYSICA = 5;

    /**

     * USB class for still image devices (digital cameras).

     */

    public static final int USB_CLASS_STILL_IMAGE = 6;

    /**

     * USB class for printers.

     */

    public static final int USB_CLASS_PRINTER = 7;

    /**

     * USB class for mass storage devices.

     */

    public static final int USB_CLASS_MASS_STORAGE = 8;

    /**

     * USB class for USB hubs.

     */

    public static final int USB_CLASS_HUB = 9;

    /**

     * USB class for CDC devices (communications device class).

     */

    public static final int USB_CLASS_CDC_DATA = 0x0a;

    /**

     * USB class for content smart card devices.

     */

    public static final int USB_CLASS_CSCID = 0x0b;

    /**

     * USB class for content security devices.

     */

    public static final int USB_CLASS_CONTENT_SEC = 0x0d;

    /**

     * USB class for video devices.

     */

    public static final int USB_CLASS_VIDEO = 0x0e;

    /**

     * USB class for wireless controller devices.

     */

    public static final int USB_CLASS_WIRELESS_CONTROLLER = 0xe0;

    /**

     * USB class for wireless miscellaneous devices.

     */

    public static final int USB_CLASS_MISC = 0xef;

    /**

     * Application specific USB class.

     */

    public static final int USB_CLASS_APP_SPEC = 0xfe;

    /**

     * Vendor specific USB class.

     */

    public static final int USB_CLASS_VENDOR_SPEC = 0xff;

3.如何避免前两步后设置后,业务页面会因USB设备插入而刷新

安卓原生逻辑导致用户选择“默认情况下用于该USB设备”会导致USB设备插入时打开某个指定activity。如果要避免页面刷新导致业务中断,可以增加如下代码防止页面刷新。

 五、如何避免自己的应用数据被清除

应用数据默认是可以通过系统设置删除的,删除后应用将恢复刚安装的状态。但是可以通过配置APP来精细管理应用数据(比如按照业务分类或时间删除数据),也可以避免重要的应用数据被删除。

在程序的manifest文件的application中加上manageSpaceActivity属性,并且指定一个Activity,这个Activity就是点击管理空间之后会跳转的那个Activity了。

 

    

 

PS 如果要避免数据被删除,可以创建一个自动关闭的Activity。

public class ManageSpaceActivity extends Activity {  

    @Override  

    protected void onCreate(Bundle savedInstanceState) {  

        super.onCreate(savedInstanceState);  

        finish();  

    }// onCreate  

}  

六、如何避免插入usb外设导致app界面闪烁

在APP的AndroidManifest中,添加如下代码

android:configChanges=”navigation|keyboardHidden|keyboard”

七、如何避免扫描枪扫出内容与实际不一致

一般情况下,文本框输入的所有内容会提交给输入法进行转换(如拼音、联想等),有的输入法经过转换后会转义部分字词导致输入内容不一致。

除了更换系统输入法为合适的输入法外,还可以利用输入法通常不对密码框进行处理的规则,调整文本框类型为“可见密码”(inputType),并且约定好可输入规范(digits)也可以避免该问题

调试设备说明

关于商米设备调试

ADB权限申请流程:在FT1mini 在设置->开发者选项->开发者指南->输入渠道绑定的手机号->获取验证码->填入收到的验证码->授权后就可以adb调试了

(本教程仅适用于非金融设备,如需要开启Sunmi P系列设备的调试权限,请联系销售人员)

默认商米的设备插上USB线就可以调试,商米也提供了设备调试权限的控制功能,合作伙伴在后台开启调试权限控制后(如下图所示),则需要通过邮箱或手机号获取调试权限才能调试该设备。如果不能直接调试,请查看合作伙伴后台是否开启了该权限。

注:调试权限的控制只针对绑定了合作伙伴(渠道)的设备生效。

启用调试权限控制后如何调试设备

如果合作伙伴启用了’调试权限控制’,则开发者需要在旗下设备上通过邮箱和手机号获取调试权限才能调试设备,合作伙伴可以在商米合作伙伴平台添加调试员(开发者)的手机号或邮箱。以下为获取设备调试权限的歩骤:

1.添加调试员。

开发者调试设备之前请了解设备所属的渠道,可以找自己公司相关的管理人员询问。管理人员需要在商米的合作伙伴平台后台添加调试员的手机号或邮箱。

2

2.插入USB(V1s、V2、M2、L2建议暂时通过关闭云端调试保护开关来调试设备)

确保自己有调试权限的手机号或邮箱后,将设备连接电脑,建议开发者在windows下调试,如果手机能被电脑正确识别,通常会出现如下的弹窗提示:

3

如果设备没有被电脑识别,请确认是否因以下原因引起。

  • 接触不良,请多次插拔扭动USB接口确认。
  • 数据线故障,换条数据线看下能不能识别。
  • 电脑没有安装移动设备驱动,可以使用第三方工具软件安装。

3.获取验证码。

点击上面的“我要调试”项,将进入手机号或邮箱验证权限步骤,同时设备的USB调试模式将自定开启(这里是指基础的调试模式,不是权限);点击“知道了”将退出弹窗,不会开启USB调试模式。

4

4.验证权限

输入之前添加的手机号或邮箱后点击’获取验证码’,商米将向手机号或邮箱发送验证码,填入验证码点击’授权并开启调试’。

5

5.打开权限。

打开权限后,可以查看logcat中有无输出判断是否可以调试设备。

6

自测平台使用手册

我们希望软件商可以通过自测平台可以自助完成软件授权开户对接,自测平台提供以下功能:
1.自动生成开发者Key;
2.自助提交Test环境配置;
3.自助完成接口调试(自测用例);
4.自助完成正式环境配置提交。

使用说明

1.登录软件商自测平台

软件商确认对接后,商米工作人员会发送自测平台地址。

如果没有账号,请注册开发者账号。

2.申请开发者key,提交测试环境配置

1)自动生成开发者KEY,开发者KEY生成后不可修改。
2)需要填写应用名称,选择是否支持修改省市区,以及接口地址配置。
3)填写并确认无误后,点击导航【接口调试】进入调试流程。

3.接口调试

1)点击请求接口下拉列表,选择对应的接口进行调试。
2)可以通过手动填写或json参数填写业务参数。
3)根据接口测试用例进行测试。
4)目前接口调试只支v1.9版本新版接口,老接口通过【旧版接口调试】进行联调。

4.提交正式环境配置

1)联调完成后,可以提交正式环境配置。
2)正式环境的配置地址可以跟测试环境不一样,需要重新提交。
3)提交配置后,运营人员会进行购买测试(在商米UAT环境和软件商正式环境中进行购买测试)
4)购买测试通过后,商米运营人员会进行正式环境上线。

商米AI识客SDK代码示例

  1. SDK 初始化
  2. 获取摄像头预览信息
  3. 获取摄像头拍照数据
  4. 获取特征值
  5. 人脸特征值比较
  6. 删除特征记录
  7. 会员库添加
  8. 会员注册
  9. IPC 回调接口

1. SDK初始化

public boolean initFaceSdkInstance(Context context, String licencePath) {
         //初始化配置文件
        int ret = SunmiFaceSDK.init(confPath);
        if (licencePath == null) {
            Log.d(TAG, "Please input licence");
            return false;
        }
        File f = new File(licencePath);
        if (!f.exists()) {
            Log.d(TAG, "licence is not exist");
            return false;
        }
        String licence = readToString(licencePath);
        //验证Licence
        ret = SunmiFaceSDK.verifyLicence(context, licence);
        if (ret != 0) {
            Log.d(TAG, "Licence is not OK ErrorCode " + ret);
            return false;
        }
        //设置配置参数
        SunmiFaceConfigParam param = new SunmiFaceConfigParam();
        SunmiFaceSDK.getConfig(param);
        param.setDistance_threshold_(1.3f);
        param.setYaw_threshold_(50.0f);
        param.setPitch_threshold_(50.0f);
        param.setRoll_threshold_(50.0f);
        param.setMin_face_size(60);
        param.setImage_quality_threshold_(10);
        param.setMin_luminance_(10);
        param.setMax_luminance_(180);
        param.setLiveness_on_(false);
        param.setThread_num_(1);
        //设置配置参数
        ret = SunmiFaceSDK.setConfig(param);

        if (ret != 0) {
            Log.d(TAG, "param is not init");
            return false;
        }
        return true;
    }

public void init(Context context) {
      //设置licence_valid.txt为sd卡路径,也可以换成app运行工作目录。
      String licencePath = Environment.getExternalStorageDirectory() + File.separator + "licence_valid.txt";
      initFaceSdkInstance(context, licence_path);
     // 调用IPCameraManager静态类getInstance初始化IPCManger对象
     mIPCManager = IPCameraManager.getInstance(context);
}

2. 获取摄像头预览信息

//摄像头数据回调接口	
CameraDataCallback cameraDataCallback = new CameraDataCallback() {
    @Override
    public void onImageDataArrival(Bitmap bitmap, int width, int height) {
        if (mBackgroundHandler != null) {
            if (mClickAction == 1 && !faceDetectState.get()) {
                mBackgroundHandler.post(new MotionDetector(bitmap, width, height));
            } else {
                bitmap.recycle();
            }
        }

    }
};
//开启摄像头预览
FaceCameraManager.getInstance().startPreview(getApplicationContext(), this, FaceCameraManager.getInstance().getCurCamera(), cameraView, PREVIEW_WIDTH, PREVIEW_HEIGHT, cameraDataCallback);

3. 获取摄像头拍照数据

{
//根据摄像头是USB还是系统摄像头,调用不同的方法,获取bitmap数据
if (FaceCameraManager.getInstance().getCurCamera() == FaceCameraManager.CAMERA_USB)
    bitmap = mUVCCameraView.captureStillImage();
else
    bitmap = mTextureView.getBitmap();

}

4. 获取特征值

说明:通过bitmap获取特征值

    public ArrayList‹SunmiFaceFeature› getFeatures(Bitmap bitmap, int maxFace) {

        int ret = 0;
        //bitmap的RGB数据转化成BGR数据
        byte[] srcData = ImageUtils.getPixelsBGR(bitmap);
        //通过BGR数据构造SunmifaceImage对象
        SunmiFaceImage image = new SunmiFaceImage(srcData, bitmap.getHeight(), bitmap.getWidth(), maxFace);
        SunmiFaceImageFeatures features = new SunmiFaceImageFeatures();
        //从SunmifaceImage数据中提取人脸特征
        ret = SunmiFaceSDK.getImageFeatures(image, features);
        //返回人脸特征数组
        SunmiFaceFeature feature_ary = features.getFeatures_();
        ArrayList‹SunmiFaceFeature› arrayList = new ArrayList‹›();
        if (features.getFeatures_count_() == 0) {
            SunmiFaceSDK.releaseImageFeatures(features);
            return arrayList;
        }

        for (int i = 0; i ‹ features.getFeatures_count_(); i++) {
            SunmiFaceFeature sunmiFaceFeature = SunmiFaceLib.SunmiFaceFeatureArray_getitem(feature_ary, i);
            arrayList.add(sunmiFaceFeature);
        }
        SunmiFaceSDK.releaseImageFeatures(features);
        return arrayList;
        // return getFeature(srcData, bitmap.getWidth(),bitmap.getHeight(), 1);
    }

5. 人脸特征值比较

    public SunmiFaceCompareResult compareFeature1V1(float similar, float[] feature1, float[] feature2) {
        //构造SunmiFaceFeature对象
        SunmiFaceFeature feat1 = new SunmiFaceFeature();
        SunmiFaceFeature feat2 = new SunmiFaceFeature();
        feat1.setFeature_(feature1);
        feat2.setFeature_(feature2);
        SunmiFaceCompareResult result = new SunmiFaceCompareResult();
        //调用compare1v1进行比较
        int ret = SunmiFaceSDK.compare1v1(feat1, feat2, result);
        return result;
    }

6. 会员删除

说明: 删除会员信息时,需要把删除的人脸会员信息同步到IPC。向IPC传递用户的唯一识别ID

{
//删除人脸库记录
int result = SunmiFaceSDK.deleteDBRecord(user.getImageName());
//同步删除IPC人脸记录
if (mIPCManager != null) {
    mIPCManager.deleteFaceRecord("GVIP", userId, new RPCCallback‹RPCResponse‹RPCResponse.FaceDeleteSubResult››() {
         //IPC人脸删除记录完成后回调接口
        @Override
        public void onComplete(RPCResponse‹RPCResponse.FaceDeleteSubResult› result) {
            Log.i(TAG, "deleteFaceRecord, code:" + result.code());
        }
    });
}
}

7. 人脸会员库添加

说明: 添加人脸时,同时要向IPC注册人脸信息。向IPC传递信息包括:人脸会员库(GVIP),人脸照片、人脸会员唯一识别ID。

{
        //使用faceFeature构建record
        SunmiFaceDBRecord record =     SunmiFaceSDK.faceFeature2FaceDBRecord(faceFeature);
        record.setId_(user.getUserId());
        record.setName_(user.getUserName());
        //把record添加到人脸库
        int ret = SunmiFaceSDK.addDBRecord(record);
        //把人脸照片传递给IPC,向IPC添加人脸记录   
         if (mIPCManager != null) {
                    mIPCManager.addFaceRecord("GVIP", picPath, uid, new RPCCallback‹RPCResponse›() {
                        //IPC人脸添加记录完成后回调接口
                        @Override
                        public void onComplete(RPCResponse result) {
                            Log.i(TAG, "addFaceRecord, code:" + result.code());
                        }
                        //IPC人脸添加记录失败时回调接口
                        @Override
                        public void onAbort(int httpStatus) {
                            Log.i(TAG, "addFaceRecord, httpStatus:" + httpStatus);
                        }
                        //IPC人脸添加记录异常时回调接口
                        @Override
                        public void onException(Throwable t) {
                            Log.i(TAG, "addFaceRecord, Exception:" + t.getMessage());
                        }
                    });
                }

}

8 会员注册

/*
 *向系统注册会员信息
 *@groupname, 会员组
 *@userNanem, 会员名
 *@picPath,   会员照片存放路劲
 *@userInfo,  会员详情
 *@faceFeature, 会员照片提取的特征值
 */
public boolean registerUserIntoDBmanager(String groupName, String userName, String picPath, String userInfo, SunmiFaceFeature faceFeature) {
        boolean isSuccess = false;
        Group group = new Group();
        group.setGroupId(groupName);
        //创建会员
        User user = new User();
        user.setGroupId(groupName);
        //final String uid = UUID.randomUUID().toString();
        String uid = String.valueOf(System.currentTimeMillis());
        user.setUserId(uid);
        user.setUserName(userName);
        user.setFeature(faceFeature.getFeature_());
        //创建人脸库记录信息
        SunmiFaceDBRecord record = SunmiFaceSDK.faceFeature2FaceDBRecord(faceFeature);
        record.setId_(user.getUserId());
        record.setName_(user.getUserName());
        //像人脸库添加记录
        int ret = SunmiFaceSDK.addDBRecord(record);
        if (ret != 0) {
            Log.d(TAG, "addDBRecord failed " + SunmiFaceSDK.getErrorString(ret));
            return false;
        }
        //在会员数据库中记录,特征值对应的图片在人脸数据中的ID
        user.setImageName(record.getImg_id_());
        if (userInfo != null) {
            user.setUserInfo(userInfo);
        }
        // 添加用户信息到数据库
        boolean importUserSuccess = FaceManager.getInstance().userAdd(user);
        if (importUserSuccess) {
            // 如果添加到数据库成功,则添加用户组信息到数据库
            // 如果当前图片组名和上一张图片组名相同,则不添加数据库到组表
            if (FaceManager.getInstance().groupAdd(group)) {
                isSuccess = true;
                if (mIPCManager != null) {
                    Log.i(TAG, "picPath: " + picPath);
                    Log.i(TAG, "uid: " + uid);
                    //把会员照片同步发送到IPC,同步会员信息到IPC
                    mIPCManager.addFaceRecord("GVIP", picPath, uid, new RPCCallback‹RPCResponse›() {
                        @Override
                        public void onComplete(RPCResponse result) {
                            Log.i(TAG, "addFaceRecord, code:" + result.code());
                        }

                        @Override
                        public void onAbort(int httpStatus) {
                            Log.i(TAG, "addFaceRecord, httpStatus:" + httpStatus);
                        }

                        @Override
                        public void onException(Throwable t) {
                            Log.i(TAG, "addFaceRecord, Exception:" + t.getMessage());
                        }
                    });
                }
            } else {
                isSuccess = false;
            }

        } else {
            isSuccess = false;
        }
        return isSuccess;
    }

9. IPC 回调接口

说明:用户获取IPC的状态、返回信息等。

{
                    //获取IPC信息
                    IPCameraManager manager = IPCameraManager.getInstance(getApplicationContext());
                    //IPC初始化
                    manager.init("test", "123456", "123456");
                    //注册IPC回调
                    manager.registerListener(new IPCameraListener() {
                        //IPC设备在线时回调接口
                        @Override
                        public void onDeviceOnline(IPCameraInfo device) {
                            showToast("[ " + device.getDeviceid() + " ]上线");
                        }
                        //IPC设备离线时回调接口
                        @Override
                        public void onDeviceOffline(IPCameraInfo device) {
                            showToast("[ " + device.getDeviceid() + " ]离线");
                        }
                        //IPC设备获取到进店信息后回调接口
                        @Override
                        public void onFaceDetect(String userId) {
                            String userName = null;
                            List‹User› users = DBManager.getInstance().queryUserByUserId(userId);
                            if (users != null && users.size() › 0) {
                                userName = users.get(0).getUserName();
                            }
                            if (userName == null) {
                                showToast("未注册的用户进店");
                            } else {
                                User user = users.get(0);
                                UserEvent userEvent = new UserEvent();
                                userEvent.setUserId(user.getUserId());
                                userEvent.setEnterTime(System.currentTimeMillis());
                                userEvent.setDesc("Enter Store");
                                DBManager.getInstance().addUserEvent(userEvent);
                                showToast("用户[ " + userName + " ]进店");
                            }
                        }
             }
}

10、IPC扫描

// 获取IPC扫描的AP热点
private void getWifiList() {
    BasicConfig.getInstance(context).getApListWithoutAuth(sunmiDevice.getDeviceid(),
            new RPCCallback‹RPCResponse‹IpcApBean››() {
                @Override
                public void onComplete(RPCResponse‹IpcApBean› result) {
                    if (result.code() == RPCErrorCode.SUCCESS) {
                        wifiListGetSuccess(result.data());
                    } else {
                        Log.i(TAG, "getApListWithoutAuth failed, errcode: " + result.code());
                    }
                }
        });

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            if (wifiList.size() == 0) {
                setNoWifiVisible(View.VISIBLE);
            }
        }
    }, TIMEOUT_GET_WIFI);
}

11、IPC连接AP

private void setIpcWifi(String ssid, String psw) {
    showLoadingDialog();
    BasicConfig.getInstance(context).setWifiConfWithoutAuth(sunmiDevice.getDeviceid(),
            ssid, psw, new RPCCallback‹RPCResponse›() {
                @Override
                public void onComplete(RPCResponse result) {
                    if (result.code() == RPCErrorCode.SUCCESS) {
                        hideLoadingDialog();
                        shortTip("配置成功,请等待设备联网,联网后指示灯会变成蓝色");
                        createWaitDialog();
                    } else {
                        hideLoadingDialog();
                        shortTip("配置失败");
                    }
                }

                @Override
                public void onError(Throwable t) {
                    hideLoadingDialog();
                    shortTip("配置失败");
                }
            });
}

12、激活IPC

//激活ipc设备,并设置回调接口
DeviceManage.getInstance(context).activate(ipcList.get(postion).getDeviceid(),
    new RPCCallback‹RPCResponse›() {
        //IPC返回相关错误码。
        @Override
        public void onComplete(RPCResponse result) {
            if (result.code() == RPCErrorCode.SUCCESS || result.code() == RPCErrorCode.DEVICE_ACTIVATED) {
                Log.i(TAG, "activate ipc success");
            } else {
                Log.i(TAG, "activate ipc failed");
            }
        }
        //网络问题导致无法通信,会调用onError接口
        @Override
        public void onError(Throwable t) {
            Log.i(TAG, "activate ipc failed");
        }
    });

13、RTSP播放

    private void openMediaPlayer() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //获取播放流
                VideoStream.getInstance(context).getLiveStream(mDevice.getDeviceid(),
                        new RPCCallback‹RPCResponse‹RPCResponse.LiveAddressBean››() {
                            @Override
                            public void onComplete(RPCResponse‹RPCResponse.LiveAddressBean› result) {
                                if (result.code() == RPCErrorCode.SUCCESS) {
                                    Log.i(TAG, "live url: " + result.data().fhd_live_url);
                                    if (mPlayer == null) {
                                       //自定义的rtsp播放器
                                        mPlayer = new SunmiPlayer(context);
                                        mPlayer.setListener(new SunmiPlayerListener() {
                                            @Override
                                            public void onPrepared(IMediaPlayer iMediaPlayer) {
                                                iMediaPlayer.start();
                                            }
                                        });
                                        mPlayer.setSurface(mVideoView.getHolder().getSurface());
                                        //获取到ipc返回的播放流rtsp地址
                                        String liveUrl = result.data().fhd_live_url.replaceFirst("^rtsp://", "rtsp://admin:admin@");
                                        //自定义播放器开始播放rtsp视频流
                                        mPlayer.setUp(liveUrl);
                                    }
                                }
                            }
                });
            }
        }).start();
    }

14、IPC对焦、调焦

rivate BasicConfig mBasicConfig;

public void init() {
    ...
    mBasicConfig = BasicConfig.getInstance(context);
    ...
}

// 调焦
private void func1(){
    ...
    mBasicConfig.setZoom(mDevice.getDeviceid(), zfBean.zoom, new RPCCallback‹RPCResponse›() {
        @Override
        public void onComplete(RPCResponse result) {
            Log.i(TAG, "setZoom, code:" + result.code());
        }
    });
    ...
}

// 自动对焦
private void func2() {
    ...
    mBasicConfig.autoFocus(mDevice.getDeviceid(), xRelative, yRelative, new RPCCallback‹RPCResponse›() {
        @Override
        public void  onComplete(RPCResponse result) {
            Log.d(TAG, "autoFocus, code:" + result.code());
            if (result.code() == RPCErrorCode.SUCCESS) {
                mBasicConfig.getZoomFocusConf(mDevice.getDeviceid(), new RPCCallback‹RPCResponse‹RPCResponse.ZoomFocusBean››() {
                    @Override
                    public void onComplete(RPCResponse‹RPCResponse.ZoomFocusBean› result) {
                        if (result.code() == RPCErrorCode.SUCCESS) {
                            zfBean = result.data();
                            mSbZoom.setProgress(zfBean.zoom);
                        }
                    }
                });
            }
        }
    });
    ...
}

// 自动对焦如果不够清晰,可以手动对焦进行微调
private void func3() {
    ...
    mBasicConfig.manualFocus(mDevice.getDeviceid(), focus, new RPCCallback‹RPCResponse›() {
        @Override
        public void onComplete(RPCResponse result) {
            if (result.code() == RPCErrorCode.SUCCESS) {
                zfBean.focus = focus;
            }
        }
    });
    ....
}

15、设置IPC门线

private void func() {
    ...
    PeopleFlowStats.getInstance(context).setDoorLine(mDevice.getDeviceid(), 0, lineStart[0],
            lineStart[1], lineEnd[0], lineEnd[1], new RPCCallback‹RPCResponse›() {
                @Override
                public void onComplete(RPCResponse result) {
                    if (result.code() == RPCErrorCode.SUCCESS) {
                        stopPlay();
                        finish();
                        startActivity(new Intent(context, MainActivity.class));
                    }
                }
            });
    ...
}

16、IPC监听人脸消息

IPCameraManager.getInstance(context).setFaceDetectListener(new FaceDetectListener() {
    @Override
    public void onFaceDetect(String userId) {
        String userName = null;
        if (userName == null) {
            showToast(getApplicationContext(), "未注册的用户进店");
        } else {
            showToast(getApplicationContext(), "用户[ " + userName + " ]进店");
        }
    }
});

商米AI识客SDK开发指南

  1. 准备工作

1.1 申请SDK所需的材料

步骤一:联系商米售前技术团队,申请SDK需要向售前技术支持团队提供如下软件开发商信息

客户提供的信息说明
客户名称软件商公司名称

步骤二:售前技术团队根据客户的需求信息,返回软件商以下内容

返回给客户的信息说明
SDK开发包用于人脸识别以及AI识客设备开发的SDK(目前只支持安卓版本)

SDK开发包的内容如下:

序号文件/文件名说明
1FaceDemoDemo工程源码
2face-release.aar商米人脸识别SDK
3libipcsdk-release.aarIPC 联动版sdk
4asset商米人脸识别资源文件
5FaceDemo.apkFaceDemo程序

2. 申请Licence

拿到SDK后,联系商米售前人员,提供以下信息申请Licence

提供的信息说明
收银设备硬件指纹1、通过Demo APP查看硬件指纹信息。安装运行FaceDemo.apk,授权FaceDemo存储器权限,会在sdcard目录生成一个硬件指纹信息文件device_fingerprint.txt。
2、或者通过SDK API查看硬件指纹信息。

返回的信息:

信息说明
Licence 激活人脸识别的SDK的Licence
appid和secret_key 激活设备IPC设备

SaaS开发者获取到以上信息后,可以使用人脸识别SDK,并激活IPC设备。

3. 添加SDK到工程

3.1 导入SDK

右键点击app,选择New->Module->Import .JAR/.AAR Package

点击Finish即导入aar模块

3.2 权限申明

在AndroidManifest.xml文件里添加如下权限:

	‹uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/›
	‹uses-permission android:name="android.permission.INTERNET" /›
	‹uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /›
	‹uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /›
	‹uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" /›
	‹uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /›
	‹uses-permission android:name="android.permission.CAMERA" /›

3.3 导入asset资源

导入提供的assets资源

说明:资源文件需要APP启动的时候复制到APP的运行目录,以方便SDK后续初始化。

3.4 导入licence文件

获取到licence_valid.txt文件,可以放到assets资源目录,也可以放到sdcard目录。

1)放到assets资源目录,则需要把licence_valid.txt文件从资源文件复制到app的工作目录。

2)如果放到sdcard目录,则需要app申请sdcard读取权限。

无论哪一种情况,最后使用的时候,需要传递licence_valid.txt文件的路径,以激活人脸识别SDK。详细见SDK初始化代码

4. DEMO 工程目录结构

4.1 app Module

app Module是DEMO的入口。其中包含了各个模块的入口函数调用。

4.2 commonlib

commonlib Module包含了整个DEMO通用的接口。其中包含摄像头管理,工具类。如下图:

4.2.1 FaceCameraManager

FaceCameraManager统一管理设备自带摄像头和USB摄像头。设备自带摄像头的流程是使用Android系统提供的摄像头通用方法。USB摄像头则使用UVC库提供的操作摄像头的方法。FaceCameraManager对上层应用提供统一的方法:startPreview和 stopPreview。

4.2.2 NormalCameraManager

NormalCameraManager使用Android系统提供的摄像头方法,实现startPreview和stopPreview。并在内部实现回调接口用于返回每一帧摄像头获得的数据。

4.2.3 UVCCameraManager

UVCCameraManager使用第三方库UVClib提供的方法用于操作USB摄像头,实现startPreview和stopPreview。 并在内部实现回调接口用于返回每一帧摄像头获得的数据 。

4.2.4 ByteUtils

ByteUtils提供Byte操作的一些通用方法。

4.2.5 DBHelper

DBHelper提供创建数据的方法。

4.2.6 ImageUtils

ImageUtils提供图片操作的一些方法。

4.3 libuvccamera

libuvccamera Module采用第三方库开源库libuvccamera

4.4 facedemo

facedemo Module是DEMO实现功能的主要模块。其包含:配置IPC、会员注册、会员管理、会员查询等功能。

5. 配置IPC

IPC设备使用时,如果未激活,需要先激活IPC设备。激活步骤如下:

5.1 SDK初始化

APP_ID:激活与API调用校验使用的账号。

SECRET_KEY:API调用所需的签名密钥。

LICENSE:激活API所需的激活码。

IPCameraManager mIPCameraManager = IPCameraManager.getInstance(context);
mIPCameraManager.init(APP_ID, SECRET_KEY, LICENSE);

5.2 配网

IPC设备激活时需要连接到互联网。IPC连接互联网时,可以通过无线(wifi)或有线(以太网口)连接到路由器。无线连接时需要做配网设置。

有线接入:

有线接入只需要通过网线把IPC设备和集成SDK的Android设备接入到同一局域网即可,不需要其它设置。

无线接入:

无线配网方式相对要复杂点,步骤如下:

  1. 使用手机/PC的无线网卡扫描IPC的AP热点,一般AP热点的名称为SUNMI_XXXX,其中XXXX为MAC地址最后2个字节的16进制数字,MAC地址可以通过设备机身后背的标贴或者包装盒的标贴查到,AP热点本身是无加密的。
  2. 使用手机/PC的无线网卡连接IPC的AP热点,此时手机/PC就会获取到IPC分配的IP地址(按照设备发现描述的方法即可获取到),一般会是192.168.200.XXX,手机/PC的网关地址就是IPC的地址,一般会是192.168.200.1。
  3. 调用无线配置 API(见获取无线扫描AP列表 (无需签名校验)的描述)获取IPC扫描到的AP热点。
  4. 调用无线配置 API(见设置无线参数(无需签名校验)的描述)设置IPC要连接的无线网络(例如无线路由器的SSID和密码),使得IPC能够从网关处获取到IP地址。
  5. 如果网络是可以正常上网的话,IPC取到IP地址后很快就会亮蓝灯,此时表明IPC可以正常连接Internet了。

IPC扫描AP代码见 商米AI识客SDK示例代码->IPC扫描

IPC连接Wifi代码详细见 商米AI识客SDK示例代码->IPC连接AP

5.3 激活

通过 5.2配网 后,IPC通过无线连接到路由或者直接有线连接路由。

由于使用IPC的其它API时需要签名校验,所以在使用API之前需要激活IPC。激活只需要在第一次使用IPC时进行,后续都不再需要激活。

调用active接口既可以激活IPC设备。详细见 商米AI识客SDK示例代码-> 激活IPC

5.4 画面调整

由于IPC的人脸识别对于人脸图像质量有一定要求,因此在使用IPC前需要调整IPC的画面,以达到最好的体验效果。画面调整包括镜头的调焦、对焦。步骤如下:

5.4.1 RTSP 播放

首先需要通过预览视频查看IPC设备镜头是对焦,画面是否清晰。IPC设备是通过RTSP协议传递预览视频,所以需要自定义一款RTSP播放器才能看到视频流。

自定义的RTSP播放器调用VideoStream.getInstance(context).getLiveStream接口可以获取到RTSP播放流的地址。详细代码见 商米AI识客SDK示例代码-> RTSP播放

5.4.2 调焦、对焦

为了更好的人脸识别效果,需要对IPC设备进行调焦对焦。

调用接口BasicConfig.getInstance(context).setZoom调焦; BasicConfig.getInstance(context) .autoFoucus自动进行对焦调焦。

详细代码见 商米AI识客SDK示例代码-> IPC对焦、调焦

6. 会员注册

完成会员的注册功能。输入会员的ID、分组、备注信息,并采集用户的人脸,注册人脸特征信息。注册信息的同时,会通过摄像头采集人脸照片传递给IPC设备。

6.1 获取摄像头数据

详细代码见 商米AI识客SDK示例代码->获取摄像头信息

6.2 注册会员信息和人脸信息

详细代码见 商米AI识客SDK示例代码-> 会员注册

7. 会员管理

包括会员列表、会员删除、会员查看、会员注册。

会员删除详细代码见 会员删除

会员注册详细代码见  会员注册

8. 会员实时查询

主要功能实现了实时的获取摄像头预览数据,并且实时对获取的摄像头数据进行特征提取,根据人脸特征信息查询会员。做到通过人脸查询会员的目的。主要使用到的功能有:实时获取摄像头预览数据以及人脸特征提取两个功能

详细代码见 商米AI识客SDK示例代码->获取摄像头预览信息

详细代码见 商米AI识客SDK示例代码->人脸特征提取

商米AI识客SDK接口说明

1. 商米人脸识别接口

人脸识别详细API详见链接 商米人脸识别

2. IPC管理接口

详细见 设备端SDK

发布应用说明

发布应用

关于商米应用市场

每个商米合作伙伴都可以在商米官网 注册商米合作伙伴帐号,有一个自己的操作后台,原则上每一台商米的设备在卖出去的时候都会和一个合作伙伴账号绑定,商米会以合作伙伴为粒度提供部分功能和权限的控制服务。

SUNMIUI内部有一个应用市场,合作伙伴可以通过应用市场将自己的应用大规模分发到商米的设备上。默认旗下用户只能通过商米应用市场为设备安装应用。

应用市场规则

商米为部分合作伙伴分配了不同权限的应用市场,默认合作伙伴上传的应用不用商米审核就可以出现在自己的应用市场中。商米可以审核该应用,通过审核后该应用会出现在其他合作伙伴的应用市场中,当然部分合作伙伴可以选择自己的应用不出现在其他人的应用市场,也可以选择自己应用市场不出现其他人的应用,关于权限的授予可以咨询商米客服400-902-1168(每天9:00~21:00,节日除外)

应用分发流程

应用开发完成后,上传到应用市场,用户可以在设备上的应用市场搜索到应用,如果是渠道合作伙伴可以设置应用在旗下的设备自动安装。以下讲解应用首次上传分发的流程。

1.上传应用。

在 合作伙伴后台,进入”我的应用”选项,点击创建应用

2

2.填写相关内容

点击’上传安装包’,从文件夹中选择您要上传的apk,等待上传完成后,商米后台将自动分析安装包,下图绿色箭头指示部分将会自动填写好,开发者手动填写应用介绍,应用适配的设备,应用类型等信息。

  • 上传APK安装包时如果提示包名重复,则表示此APK已经在商米应用市场上架,如果此APK是贵公司所有,请联系商米客服400-902-1168(每天9:00~21:00,节日除外),进入认领。
3

3.提交应用。

合作伙伴将剩余部分内容补充完整后,下图的’提交’按钮将由灰色不可点击变成绿色可点击状态,点击’提交’将会完成应用的上传,

4

关于灰度部署

上图中’提交’按钮上方有一个’是否灰度部署’选项,勾选后提交按钮将变成’灰度部署’项,点击后将进入灰度部署配置项中。

灰度部署是商米针对合作伙伴的实际需求提供的一项功能,每台设备在使用的时候会有一个地理理位置信息,合作伙伴在开发好自己的应用适配商米的设备后,可以根据地理位置或者SN号在部分设备上部署,只有灰度部署范围内的设备的应用市场中才会出现该应用。在小范围的灰度部署后,开发者可以将应用部署到全范围设备上。

5

设置自动安装。

如果希望上传的应用自动在旗下所有设备上安装,可以在’我的应用市场’项中设置该应用为自动安装应用(如下图箭头所示),旗下设备在收到推送通知后会自动下载安装该应用,设置自动安装后还可以设置该应用是否作为默认启动应用(如下图箭头所示),设备开机后将自动启动该应用。

6

更新应用

在应用通过商米审核后,在我的应用中列表项中会有’更新’按钮,开发者可以发布该应用的升级包。点击后进入更新应用页,更新的流程和发布流程类似,请参照上面的发布流程。

  • 上传更新包的时候如果提示签名异常,请检查APK签名是否与原来的安装包不一致。如确认是需要变更签名,则请删除应用后再创建应用
  • 上传更新包的时候如果提示包名不一致,请检查APK包名是否有变动或有没有上传错误。如确认是需要变更包名,则请删除应用后再创建应用
7