IPC设备迁移

本章节详细介绍在Android平台如何快速方便添加IPC SDK

1、拓扑图

IPC设备和Android设备连接拓扑图如下:

1、Android设备有一套自有的用户管理模块,有唯一ID识别机制。Android设备在管理用户时,需要保留一张用户人脸图片

2、IPC设备使用人脸图片作为识别预输入。

3、Android设备激活IPC设备后,通过局域网把用户人脸图片以及与用户唯一关联的ID传递给IPC设备

4、IPC设备从人脸图片提取人脸特征值,并把特征值与用户ID保存到数据库。

5、IPC设备监控到用户进入,查询注册的数据库,返回用户唯一ID的IPC设备。

6、Android设备获取到唯一ID值后,在用户管理模块根据该唯一ID进行查询,显示用户信息

2、IPC激活

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

2.1 SDK初始化

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

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

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

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

2.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热点
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);
}
// 设置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("配置失败");
                }
            });
}

2.3 激活

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

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

调用active接口既可以激活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");
        }
    });

2.4 画面调整

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

2.4.1 RTSP 播放

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

调用VideoStream.getInstance(context).getLiveStream接口可以获取到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();
    }

2.4.2 调焦、对焦

private 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;
            }
        }
    });
    ....
}

2.4.3 设置门线

设置门线主要是更精确地判断人流的方向(进门、出门、路过),提高人流统计的准确度。

调用接口PeopleFlowStats.getInstance(context).setDoorLine设置门线。代码如下:

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));
                    }
                }
            });
    ...
}

3、注册人脸

IPC激活好以后,向设备注册人脸信息。

Android设备端注册人脸时,需要同步向IPC设备注册人脸需要传递用户人脸照片、以及唯一标识用户的ID。

通过接口IPCameraManager.getInstance(context).addFaceRecord向IPC注册人脸。代码如下:

/*
 *传递人脸照片路径: picPath,
 * 用户唯一ID: uid
 */
IPCameraManager.getInstance(context).addFaceRecord(picPath, uid, new RPCCallback‹RPCResponse›() {
                        //IPC设备调用成功后会调用onComplete
                        @Override
                        public void onComplete(RPCResponse result) {
                            Log.i(TAG, "addFaceRecord, code:" + result.code());
                            if (result.code() != 0){
                                showToast(context, "添加人脸失败 code: " + result.code());
                            } else {
                                showToast(context, "添加人脸成功");
                            }
                        }
                        //IPC设备离线时,调用会调用onError
                        @Override
                        public void onError(Throwable t) {
                            super.onError(t);
                            Log.i(TAG, "addFaceRecord, Exception:" + t.getMessage());
                            showToaste(context, "添加人脸失败 ");
                        }
                    });

4、删除人脸

Android设备端删除用户时,需要同步删除IPC设备的人脸信息。Andorid端设备需要传递用户唯一ID。

调用接口 IPCameraManager.getInstance(context).addFaceRecord 向IPC删除人脸。代码如下:

//传递用户唯一ID:userId
IPCameraManager.getInstance(context).deleteFaceRecord(userId,new RPCCallback‹RPCResponse‹RPCResponse.FaceDeleteSubResult››() {
                @Override
                public void onComplete(RPCResponse‹RPCResponse.FaceDeleteSubResult› result) {
                    Log.i(TAG, "deleteFaceRecord, code:" + result.code());
                    if (result.code() != 0){
                        showToast(context, "删除人脸失败 code: " + result.code());
                    } else {
                        showToast(context, "删除人脸成功");
                    }
                }

                @Override
                public void onError(Throwable t) {
                    super.onError(t);
                    Log.i(TAG, "addFaceRecord, Exception:" + t.getMessage());
                }

            });

5、 监听人脸识别消息

Android设备注册好人脸信息后,即可以监听IPC设备人脸识别信息。通过IPC返回的ID信息,查询数据库,显示用户详细信息。

调用IPCameraManager.getInstance(context).setFaceDetectListener即可监听人脸信息,代码如下:

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