Selaa lähdekoodia

增加接待模式

tags/A.1.0.1.0_20230725_release^2
tangmingjie 2 vuotta sitten
vanhempi
commit
f4e8fb9ecc
40 muutettua tiedostoa jossa 3395 lisäystä ja 827 poistoa
  1. +17
    -0
      .idea/deploymentTargetDropDown.xml
  2. BIN
      app/libs/commons-codec-1.9.jar
  3. BIN
      app/libs/fastjson-1.2.21.jar
  4. BIN
      app/src/main/assets/faces.db3
  5. +32
    -59
      app/src/main/java/com/aispeech/nativedemo/DDSService.java
  6. +1
    -1
      app/src/main/java/com/aispeech/nativedemo/DigiApplication.java
  7. +80
    -37
      app/src/main/java/com/aispeech/nativedemo/MainActivity.java
  8. +2
    -23
      app/src/main/java/com/aispeech/nativedemo/asr/observer/DuiMessageObserver.java
  9. +1
    -1
      app/src/main/java/com/aispeech/nativedemo/config/Config.java
  10. +58
    -2
      app/src/main/java/com/aispeech/nativedemo/config/ConfigManager.java
  11. +3
    -0
      app/src/main/java/com/aispeech/nativedemo/db/DatabaseImpl.java
  12. +57
    -0
      app/src/main/java/com/aispeech/nativedemo/db/ReceptionBuilder.java
  13. +112
    -0
      app/src/main/java/com/aispeech/nativedemo/db/ReceptionDbHelper.java
  14. +28
    -0
      app/src/main/java/com/aispeech/nativedemo/db/SettingBuilder.java
  15. +107
    -0
      app/src/main/java/com/aispeech/nativedemo/db/SettingDbHelper.java
  16. +37
    -0
      app/src/main/java/com/aispeech/nativedemo/db/StrangerBuilder.java
  17. +112
    -0
      app/src/main/java/com/aispeech/nativedemo/db/StrangerDbHelper.java
  18. +6
    -12
      app/src/main/java/com/aispeech/nativedemo/dds/DDSManager.java
  19. +3
    -0
      app/src/main/java/com/aispeech/nativedemo/entity/PersonInfo.java
  20. +60
    -0
      app/src/main/java/com/aispeech/nativedemo/entity/Reception.java
  21. +9
    -0
      app/src/main/java/com/aispeech/nativedemo/entity/Setting.java
  22. +35
    -0
      app/src/main/java/com/aispeech/nativedemo/entity/Stranger.java
  23. +67
    -0
      app/src/main/java/com/aispeech/nativedemo/entity/Vip.java
  24. +780
    -0
      app/src/main/java/com/aispeech/nativedemo/face/FaceChatMode.java
  25. +711
    -674
      app/src/main/java/com/aispeech/nativedemo/face/FaceManager.java
  26. +396
    -0
      app/src/main/java/com/aispeech/nativedemo/face/FaceReceptionMode.java
  27. +7
    -0
      app/src/main/java/com/aispeech/nativedemo/face/IdentityMode.java
  28. +26
    -0
      app/src/main/java/com/aispeech/nativedemo/log/LogFile.java
  29. +6
    -1
      app/src/main/java/com/aispeech/nativedemo/log/LoggerPrinter.java
  30. +24
    -7
      app/src/main/java/com/aispeech/nativedemo/network/ws/DigiWebSocketServer.java
  31. +62
    -3
      app/src/main/java/com/aispeech/nativedemo/network/ws/MessageUtils.java
  32. +31
    -0
      app/src/main/java/com/aispeech/nativedemo/rtasr/DraftWithOrigin.java
  33. +66
    -0
      app/src/main/java/com/aispeech/nativedemo/rtasr/EncryptUtil.java
  34. +228
    -0
      app/src/main/java/com/aispeech/nativedemo/rtasr/RTASRManager.java
  35. +219
    -0
      app/src/main/java/com/aispeech/nativedemo/rtasr/RTASRTest.java
  36. +5
    -0
      app/src/main/java/com/aispeech/nativedemo/upload/UploadManager.java
  37. +0
    -1
      app/src/main/java/com/aispeech/nativedemo/utils/Utils.java
  38. +7
    -6
      app/src/main/java/com/aispeech/nativedemo/widget/AlertWindowView.java
  39. BIN
      test/libs/lib-dds-2.9.2.1-release.aar
  40. BIN
      test/src/main/assets/sspe-aec-mann-70mm-6chan-2mic-2ref-v2.0.0.127-0926-nocross-dcrn-decoderadd_20230714_aecGain4_v1.bin

+ 17
- 0
.idea/deploymentTargetDropDown.xml Näytä tiedosto

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<runningDeviceTargetSelectedWithDropDown>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
<Key>
<type value="SERIAL_NUMBER" />
<value value="7d656601c9f0070f" />
</Key>
</deviceKey>
</Target>
</runningDeviceTargetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2023-07-23T06:07:31.789079600Z" />
</component>
</project>

BIN
app/libs/commons-codec-1.9.jar Näytä tiedosto


BIN
app/libs/fastjson-1.2.21.jar Näytä tiedosto


BIN
app/src/main/assets/faces.db3 Näytä tiedosto


+ 32
- 59
app/src/main/java/com/aispeech/nativedemo/DDSService.java Näytä tiedosto

@@ -7,7 +7,6 @@ import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
@@ -22,15 +21,14 @@ import android.widget.Toast;
import com.aispeech.dui.dds.DDS;
import com.aispeech.dui.dds.DDSAuthListener;
import com.aispeech.dui.dds.DDSConfig;
import com.aispeech.dui.dds.DDSConfigBuilder;
import com.aispeech.dui.dds.DDSInitListener;
import com.aispeech.dui.dds.DDSMode;
import com.aispeech.dui.dds.agent.AsrListener;
import com.aispeech.dui.dds.agent.tts.TTSEngine;
import com.aispeech.dui.dds.exceptions.DDSNotInitCompleteException;
import com.aispeech.nativedemo.face.FaceManager;
import com.aispeech.nativedemo.log.Logger;
import com.aispeech.nativedemo.mqtt.MqttManager;
import com.aispeech.nativedemo.network.ws.MessageUtils;
import com.aispeech.nativedemo.network.ws.WebSocketManager;
import com.aispeech.nativedemo.ui.LauncherActivity;
import com.aispeech.nativedemo.config.Config;
@@ -40,6 +38,7 @@ import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.UUID;

/**
@@ -121,7 +120,7 @@ public class DDSService extends Service {
if (isFull) {
// 发送一个init成功的广播
Logger.e("init face sdk");
FaceManager.getInstance(DuiApplication.getContext()).initEngine();
FaceManager.getInstance().initEngine();
Logger.e("init face sdk over");
sendBroadcast(new Intent("ddsdemo.intent.action.init_complete"));
initCompleted = 1;
@@ -130,6 +129,7 @@ public class DDSService extends Service {
// DDS.getInstance().getAgent().getTTSEngine().setMode(DDSMode.TTS_SILENCE);
// DDS.getInstance().getAgent().getTTSEngine().setSpeaker("zhilingfp");
DDS.getInstance().getAgent().getTTSEngine().setSpeaker("hqqiaf","hqqiaf_lstm_210909.bin");
startAsrListening();
} catch (DDSNotInitCompleteException e) {
throw new RuntimeException(e);
}
@@ -280,15 +280,15 @@ public class DDSService extends Service {
// config.addConfig(DDSConfig.K_RECORDER_MODE, "internal"); //(适配了hal之后选内部,或者不写这一条,SDK默认是内部---录音机模式:external(使用外置录音机,需主动调用拾音接口)、internal(使用内置录音机,DDS自动录音)
// config.addConfig(DDSConfig.K_MIC_TYPE, 2); // (根据麦克风实际类型进行配置)设置硬件采集模组的类型 0:无。默认值。 1:单麦回消 2:线性四麦 3:环形六麦 4:车载双麦 5:家具双麦 6: 环形四麦 7: 新车载双麦 8: 线性6麦
//
// config.addConfig(DDSConfig.K_USE_SSPE,"true");//如果资源是SSPE资源,则需要将此配置置为true
config.addConfig(DDSConfig.K_USE_SSPE,"true");//如果资源是SSPE资源,则需要将此配置置为true
// config.addConfig(DDSConfig.K_MIC_ARRAY_SSPE_BIN,"sspe_aec_ula_wkp_35mm_ch6_mic4_ref2_v2.0.0.130.bin");//SSPE资源(放在test/src/main/assert文件夹下,或放到机器上指定绝对路径)(已包含aec算法)绝对路径,请务必保证绝对路径有可读写权限
// //config.addConfig(DDSConfig.K_WAKEUP_BIN, "wakeup_s20_zhihuijingling_20230103.bin"); //商务定制版唤醒资源的路径。如果开发者对唤醒率有更高的要求,请联系商务申请定制唤醒资源。
// config.addConfig(DDSConfig.K_AEC_MODE, "internal");//AEC模式,HAL层未集成AEC算法时,选择"internal"。HAL已经集成AEC算法时,选择"external"
config.addConfig(DDSConfig.K_AEC_MODE, "internal");//AEC模式,HAL层未集成AEC算法时,选择"internal"。HAL已经集成AEC算法时,选择"external"

config.addConfig(DDSConfig.K_MIC_TYPE, 2);
config.addConfig(DDSConfig.K_MIC_ARRAY_SSPE_BIN, "sspe_aec_ula_wkp_35mm_ch6_mic4_ref2_v2.0.0.130.bin");
// config.addConfig(DDSConfig.K_MIC_ARRAY_SSPE_BIN, "sspe_aec_ula_wkp_35mm_ch6_mic4_ref2_v2.0.0.130.bin");
// config.addConfig(DDSConfig.K_MIC_ARRAY_SSPE_BIN, "sspe_aec_ula_wkp_35mm_ch6_mic4_ref2_v2.0.0.130_post_20230530.bin");
// config.addConfig(DDSConfig.K_MIC_ARRAY_SSPE_BIN, "sspe-aec-mann-70mm-6chan-2mic-2ref-v2.0.0.127-0926-nocross-dcrn-decoderadd_20221220_aecGain4_v1.bin");
config.addConfig(DDSConfig.K_MIC_ARRAY_SSPE_BIN, "sspe-aec-mann-70mm-6chan-2mic-2ref-v2.0.0.127-0926-nocross-dcrn-decoderadd_20230714_aecGain4_v1.bin");
config.addConfig(DDSConfig.K_MIC_ECHO_CHANNEL_NUM, 2);
config.addConfig(DDSConfig.K_AUDIO_SOURCE, 6);
config.addConfig(DDSConfig.K_AUDIO_CHANNEL_COUNT, 6);
@@ -338,64 +338,37 @@ public class DDSService extends Service {
}

private long mTime = 0;

public void startTtsListening() {
try {
DDS.getInstance().getAgent().getTTSEngine().setMode(DDSMode.TTS_SILENCE);
DDS.getInstance().getAgent().getTTSEngine().setListener(new TTSEngine.Callback() {
@Override
public void beginning(String ttsId) {
Log.d(TAG, "TTS开始播报 ttsId = " + ttsId);
}

@Override
public void received(byte[] data) {
Log.d(TAG, "收到音频,此方法会回调多次,直至data为0,音频结束 data = " + data.length);
String pcmData = Base64.encodeToString(data, Base64.DEFAULT);
JSONObject jo = new JSONObject();
try {
jo.put("type", "djTts");
jo.put("data", pcmData);
WebSocketManager.getInstance(MainActivity.instance).sendMsg(jo.toString());
} catch (JSONException e) {
throw new RuntimeException(e);
}
// File file = createFile(mTime + ".pcm");
// RandomAccessFile raf = null;
// try {
// raf = new RandomAccessFile(file, "rw");
// raf.seek(file.length());
// raf.write(data);
// raf.close();
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
private long mAsrTime = 0;

public void startAsrListening() {
DDS.getInstance().getAgent().getASREngine().setAsrListener(new AsrListener() {
@Override
public void onAsr(byte[] bytes) {
if(mTime == 0){
mTime = System.currentTimeMillis();
mAsrTime = System.currentTimeMillis();
}

@Override
public void end(String ttsId, int status) {

}

@Override
public void error(String error) {
Log.d(TAG, "出现错误," + error);
if(System.currentTimeMillis() - mAsrTime > 3000){
mTime = System.currentTimeMillis();
}

@Override
public void phoneReturnReceived(String s) {

mAsrTime = System.currentTimeMillis();
File file = createFile("asr-" + mTime + ".pcm");
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(file, "rw");
raf.seek(file.length());
raf.write(bytes);
raf.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
});
} catch (DDSNotInitCompleteException e) {
e.printStackTrace();
}

}
});
}

public File createFile(String name) {
String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath()
+"/Android/data/com.aispeech.nativedemo/cache/asrCache/";
+"/Android/data/com.aispeech.nativedemo/files/asrCache/";
File file = new File(dirPath);
if(!file.exists()) {
file.mkdirs();


+ 1
- 1
app/src/main/java/com/aispeech/nativedemo/DigiApplication.java Näytä tiedosto

@@ -16,7 +16,7 @@ public class DigiApplication extends Application {
super.onCreate();
mInstance = this;
CameraController.getInstance(this);
FaceManager.getInstance(this).initEngine();
FaceManager.getInstance().initEngine();
WebSocketManager.getInstance(this);
DigiNetworkManager.getManager().init(this);
}


+ 80
- 37
app/src/main/java/com/aispeech/nativedemo/MainActivity.java Näytä tiedosto

@@ -75,10 +75,15 @@ import com.aispeech.nativedemo.db.EmpDbHelper;
import com.aispeech.nativedemo.db.InitializeDbHelper;
import com.aispeech.nativedemo.db.ModelDbHelper;
import com.aispeech.nativedemo.db.SkillDbHelper;
import com.aispeech.nativedemo.db.StrangerDbHelper;
import com.aispeech.nativedemo.dds.DDSManager;
import com.aispeech.nativedemo.entity.Emp;
import com.aispeech.nativedemo.entity.Skill;
import com.aispeech.nativedemo.entity.Stranger;
import com.aispeech.nativedemo.face.FaceChatMode;
import com.aispeech.nativedemo.face.FaceManager;
import com.aispeech.nativedemo.face.FaceReceptionMode;
import com.aispeech.nativedemo.face.IdentityMode;
import com.aispeech.nativedemo.log.Logger;
import com.aispeech.nativedemo.mqtt.MqttManager;
import com.aispeech.nativedemo.network.NetworkStatusCallback;
@@ -348,14 +353,6 @@ public class MainActivity extends Activity implements DuiUpdateObserver.UpdateCa
// Utils.userFaces.clear();
// SkillDbHelper.getInstance().deleteAll();
// ModelDbHelper.getInstance().deleteAll();
JSONObject jo = new JSONObject();
try {
jo.put("type", "djTtsText");
jo.put("data", "缔智元是一家缔造数字人员工的科技企业,致力于综合图像识别、自然语言交互、知识图谱、超写实3D渲染、物联网等前沿技术,助力企业的数字化与智能化变革");
WebSocketManager.getInstance(MainActivity.this).sendMsg(jo.toString());
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
});
startClient = findViewById(R.id.start_client);
@@ -404,7 +401,7 @@ public class MainActivity extends Activity implements DuiUpdateObserver.UpdateCa

private void initManager() {
mWSManager = WebSocketManager.getInstance(getApplicationContext());
mFaceManager = FaceManager.getInstance(getApplicationContext());
mFaceManager = FaceManager.getInstance();
mFaceManager.setCallback(this);
mCameraController = CameraController.getInstance(getApplicationContext());
mCameraController.initTexture(mTextureView);
@@ -490,24 +487,24 @@ public class MainActivity extends Activity implements DuiUpdateObserver.UpdateCa
mRectFaceView.setBackground(xml2);
mRectFaceView.setRotationY(180);

if(System.currentTimeMillis() - mDoaTime > 1000){
mDoaTime = System.currentTimeMillis();
int doa = 0;
if(bd_x != 0 && bd_x > 100){
doa = 90 - (1080 - bd_x) / 25;
}
if(Math.abs(mDoa - doa) >= 5){
if(doa > 50 && doa < 130){
mDoa = doa;
try {
DDS.getInstance().getAgent().getWakeupEngine().setWakeupDoa(doa);
MessageUtils.sendDoa("define", doa);
} catch (DDSNotInitCompleteException e) {
throw new RuntimeException(e);
}
}
}
}
// if(System.currentTimeMillis() - mDoaTime > 1000){
// mDoaTime = System.currentTimeMillis();
// int doa = 0;
// if(bd_x != 0 && bd_x > 100){
// doa = 90 - (1080 - bd_x) / 25;
// }
// if(Math.abs(mDoa - doa) >= 5){
// if(doa > 50 && doa < 130){
// mDoa = doa;
// try {
// DDS.getInstance().getAgent().getWakeupEngine().setWakeupDoa(doa);
// MessageUtils.sendDoa("define", doa);
// } catch (DDSNotInitCompleteException e) {
// throw new RuntimeException(e);
// }
// }
// }
// }
}
});
}
@@ -542,49 +539,95 @@ public class MainActivity extends Activity implements DuiUpdateObserver.UpdateCa
backgroundHandler = new Handler(backgroundThread.getLooper());
updateLeFaceModel();
if (Utils.userFaces == null || Utils.userFaces.isEmpty()) {
List<Emp> empList = EmpDbHelper.getInstance().getAll();
for (Emp emp : empList) {
List<Emp> emps = EmpDbHelper.getInstance().getAll();
for (Emp emp : emps) {
Utils.userFaces.put(emp.id + "_1", emp.dfeatures);
}
}
if (Utils.userNewFaces == null || Utils.userNewFaces.isEmpty()) {
List<Stranger> strangers = StrangerDbHelper.getInstance().getAll();
for (Stranger stranger : strangers) {
Utils.userNewFaces.put(stranger.userId + "_1", stranger.faceFeatures);
}
}
// if (Utils.userLogs == null || Utils.userLogs.isEmpty()) {
// Utils.userLogs = DbHelper.Instance().loadAllLogs();
// }
backgroundHandler.post(periodicDetect);
}

/**
* 闲聊模式
*/
private final Runnable periodicDetect = new Runnable() {
@Override
public void run() {
try {
Log.e(TAG, "-----------------detect face----------------");
textureBitmap = mTextureView.getBitmap();
List<MultiAtt> results = mFaceManager.detectMultiAtt(textureBitmap);
List<MultiAtt> results = FaceChatMode.detectMultiAtt(textureBitmap);
if (results != null && results.size() > 0) {
mFaceManager.filterPersonForFeatExtract(results);
//过滤相同人物
FaceChatMode.filterPersonForFeatExtract(results, textureBitmap);
//删除过期人员
mFaceManager.deleteExpirePerson();

boolean isContinue = mFaceManager.featExtract(results, textureBitmap);
FaceChatMode.deleteExpirePerson();
boolean isContinue = FaceChatMode.featExtract(results, textureBitmap);
if(isContinue){
// if(isInitComplete){
// DDSManager.getInstance().wakeUpDDSDialog();
// }
mFaceManager.confirmCurrentPerson(textureBitmap);
FaceChatMode.confirmCurrentPerson(textureBitmap);
}
// if(!mFaceManager.hasPerson()){
// DDSManager.getInstance().stopDDSDialog();
// }
}
Log.e(TAG, "---------------thread execute over-------------");
backgroundHandler.post(periodicDetect);
loopDetect();
} catch (Exception e) {
e.printStackTrace();
}
}
};

/**
* 接待模式
*/
private final Runnable receptionDetect = new Runnable() {
@Override
public void run() {
try {
Log.e(TAG, "-----------------detect face----------------");
textureBitmap = mTextureView.getBitmap();
List<MultiAtt> results = FaceReceptionMode.detectMultiAtt(textureBitmap);
if (results != null && results.size() > 0) {
//过滤相同人物
FaceReceptionMode.filterPersonForFeatExtract(results, textureBitmap);
//删除过期人员
FaceReceptionMode.deleteExpirePerson();
boolean isContinue = FaceReceptionMode.featExtract(results, textureBitmap);
if(isContinue){
FaceReceptionMode.confirmCurrentWord();
}
} else{
FaceReceptionMode.checkSessionExpire(false);
}
Log.e(TAG, "---------------thread execute over-------------");
loopDetect();
} catch (Exception e) {
e.printStackTrace();
}
}
};

private void loopDetect(){
if(IdentityMode.MODE_CURRENT.equals(IdentityMode.MODE_CHAT)){
backgroundHandler.post(periodicDetect);
} else{
backgroundHandler.post(receptionDetect);
}
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);


+ 2
- 23
app/src/main/java/com/aispeech/nativedemo/asr/observer/DuiMessageObserver.java Näytä tiedosto

@@ -1,21 +1,13 @@
package com.aispeech.nativedemo.asr.observer;

import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;

import com.aispeech.dui.dds.DDS;
import com.aispeech.dui.dds.agent.DMTaskCallback;
import com.aispeech.dui.dds.agent.MessageObserver;
import com.aispeech.nativedemo.DuiApplication;
import com.aispeech.nativedemo.MainActivity;
import com.aispeech.nativedemo.face.FaceManager;
import com.aispeech.nativedemo.log.Logger;
import com.aispeech.nativedemo.mqtt.MqttManager;
import com.aispeech.nativedemo.network.ws.MessageUtils;
import com.aispeech.nativedemo.config.Config;
import com.aispeech.nativedemo.network.ws.WebSocketManager;
import com.aispeech.nativedemo.shape.ShapeManager;
import com.aispeech.nativedemo.widget.pageview.utils.JSONUtils;
import com.google.gson.Gson;

@@ -82,14 +74,7 @@ public class DuiMessageObserver implements MessageObserver {
try {
jsonObject.put("nlg", "");
jsonObject.put("display", "");

if (!TextUtils.isEmpty(readText)) {
JSONObject jo = new JSONObject();
jo.put("type", "djTtsNlpText");
jo.put("data", readText);
Logger.e("思必驰NLP结果发给叠境tts:" + readText);
WebSocketManager.getInstance(MainActivity.instance).sendMsg(jo.toString());
}
MessageUtils.sendTtsNlpText(readText);
} catch (JSONException e) {
e.printStackTrace();
}
@@ -97,13 +82,7 @@ public class DuiMessageObserver implements MessageObserver {
try {
jsonObject.put("nlg", "");
jsonObject.put("display", "");

JSONObject jo = new JSONObject();
jo.put("type", "djTtsNlpText");
jo.put("data", readText);
Logger.e("思必驰NLP结果发给叠境tts:" + readText);
WebSocketManager.getInstance(MainActivity.instance).sendMsg(jo.toString());

MessageUtils.sendTtsNlpText(readText);
} catch (JSONException e) {
e.printStackTrace();
}


+ 1
- 1
app/src/main/java/com/aispeech/nativedemo/config/Config.java Näytä tiedosto

@@ -9,7 +9,7 @@ public class Config {
public static final String PROD_BASE_URL= "http://123.57.75.177:8080/";
public static final String TEST_BASE_URL= "http://39.107.77.235:8080/";
public static final String DEV_BASE_URL= "http://192.168.10.244:8080/";
public static final String CURRENT_URL= PROD_BASE_URL;
public static final String CURRENT_URL= DEV_BASE_URL;

public static final long ONE_SECOND = 1000L;
public static final long ONE_MINUTE = 60 * ONE_SECOND;


+ 58
- 2
app/src/main/java/com/aispeech/nativedemo/config/ConfigManager.java Näytä tiedosto

@@ -9,15 +9,19 @@ import com.aispeech.nativedemo.DuiApplication;
import com.aispeech.nativedemo.MainActivity;
import com.aispeech.nativedemo.db.EmpDbHelper;
import com.aispeech.nativedemo.db.ModelDbHelper;
import com.aispeech.nativedemo.db.ReceptionDbHelper;
import com.aispeech.nativedemo.db.SkillDbHelper;
import com.aispeech.nativedemo.entity.Background;
import com.aispeech.nativedemo.entity.Emp;
import com.aispeech.nativedemo.entity.Icon;
import com.aispeech.nativedemo.entity.Model;
import com.aispeech.nativedemo.entity.Reception;
import com.aispeech.nativedemo.entity.ScreenOff;
import com.aispeech.nativedemo.entity.Skill;
import com.aispeech.nativedemo.entity.WorkDayHour;
import com.aispeech.nativedemo.entity.WorkTime;
import com.aispeech.nativedemo.face.FaceReceptionMode;
import com.aispeech.nativedemo.face.IdentityMode;
import com.aispeech.nativedemo.log.Logger;
import com.aispeech.nativedemo.network.ws.MessageUtils;
import com.aispeech.nativedemo.network.ws.WebSocketManager;
@@ -67,6 +71,7 @@ public class ConfigManager {
heartbeat();
MessageUtils.sendRest();
checkServiceStatus();
getReception();
}
}, 0, 60000);
}
@@ -131,7 +136,7 @@ public class ConfigManager {
getModel();
}
if((data & 0x1000) > 0){
getReception();
}
if((data & 0x10000) > 0){

@@ -351,7 +356,58 @@ public class ConfigManager {

@Override
public void onFail(String error) {
Log.e(TAG, "new Heartbeat = " + error);
Log.e(TAG, "getModel = " + error);
}
});
}

private void getReception() {
HashMap<String, String> map = new HashMap<>();
map.put("id", "123456");
map.put("devId", Build.SERIAL);
map.put("type", "3");
map.put("sign", "123456");
map.put("enterpriseName", "administrator");
map.put("timestamp", "1");
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), new JSONObject(map).toString());
HttpUtil.post(Config.CURRENT_URL + "message/api/update", requestBody, null, new HttpUtil.HttpCallback<String>() {

@Override
public void onSuccess(String success) {
Log.e(TAG, "getReception = " + success);
try {
JSONTokener t = new JSONTokener(success);
JSONObject obj = (JSONObject) t.nextValue();
int code = 0;
if (obj.has("code")) {
code = obj.getInt("code");
}
if (code == 200) {
// MessageUtils.sendMessage("接待任务:" + success);
if (obj.has("data")) {
JSONObject object = obj.getJSONObject("data");
Reception reception = new Reception();
reception.create(object);
ReceptionDbHelper.getInstance().add(reception);
if(IdentityMode.MODE_CURRENT.equals(IdentityMode.MODE_RECEPTION)){
FaceReceptionMode.mReception = reception;
}
// if (obj.has("timestamp")) {
// mUserTimeStamp = obj.optLong("timestamp");
// }
}
} else {
onFail(obj.getString("msg"));
}
} catch (Exception e) {
e.printStackTrace();
onFail(e.getMessage());
}
}

@Override
public void onFail(String error) {
Log.e(TAG, "getReception = " + error);
}
});
}


+ 3
- 0
app/src/main/java/com/aispeech/nativedemo/db/DatabaseImpl.java Näytä tiedosto

@@ -17,9 +17,12 @@ public class DatabaseImpl extends SQLiteOpenHelper {
private static final String DB_NAME = "digital_man";
public static final String TABLE_INITIALIZE = "initialize"; //初始化表
public static final String TABLE_EMP = "user_faces"; //员工表
public static final String TABLE_STRANGER = "new_user_faces"; //陌生人表
public static final String TABLE_SKILL = "skill"; //员工表
public static final String TABLE_MODEL = "model"; //员工表
public static final String TABLE_UPGRADE = "upgrade"; //软件升级表
public static final String TABLE_RECEPTION = "reception"; //接待任务表
public static final String TABLE_SETTING = "setting"; //设置表

public DatabaseImpl(Context context, String name, CursorFactory factory, int version) {
super(context, name, factory, version);


+ 57
- 0
app/src/main/java/com/aispeech/nativedemo/db/ReceptionBuilder.java Näytä tiedosto

@@ -0,0 +1,57 @@
package com.aispeech.nativedemo.db;

import android.content.ContentValues;
import android.database.Cursor;

import com.aispeech.nativedemo.entity.Reception;

import java.util.Collections;

public class ReceptionBuilder implements DatabaseBuilder<Reception>{

@Override
public Reception build(Cursor query) {
Reception reception = new Reception();
reception.name = (query.getString(query.getColumnIndex("name")));
reception.date = (query.getString(query.getColumnIndex("date")));
String guideStr = (query.getString(query.getColumnIndex("guide")));
Collections.addAll(reception.guide,guideStr.split(","));
String firstStr = (query.getString(query.getColumnIndex("first")));
Collections.addAll(reception.first,firstStr.split(","));
String secondStr = (query.getString(query.getColumnIndex("second")));
Collections.addAll(reception.second,secondStr.split(","));
String thirdStr = (query.getString(query.getColumnIndex("third")));
Collections.addAll(reception.third,thirdStr.split(","));
reception.underpinWord = (query.getString(query.getColumnIndex("underpin_word")));
return reception;
}

@Override
public ContentValues deconstruct(Reception reception) {
ContentValues contentValues = new ContentValues();
contentValues.put("name",reception.name);
contentValues.put("date",reception.date);
StringBuilder builder = new StringBuilder();
for(String str : reception.guide){
builder.append(str).append(",");
}
contentValues.put("guide",builder.toString());
builder = new StringBuilder();
for(String str : reception.first){
builder.append(str).append(",");
}
contentValues.put("first",builder.toString());
builder = new StringBuilder();
for(String str : reception.second){
builder.append(str).append(",");
}
contentValues.put("second",builder.toString());
builder = new StringBuilder();
for(String str : reception.third){
builder.append(str).append(",");
}
contentValues.put("third",builder.toString());
contentValues.put("underpin_word",reception.underpinWord);
return contentValues;
}
}

+ 112
- 0
app/src/main/java/com/aispeech/nativedemo/db/ReceptionDbHelper.java Näytä tiedosto

@@ -0,0 +1,112 @@
package com.aispeech.nativedemo.db;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.aispeech.nativedemo.entity.Reception;

import java.util.ArrayList;
import java.util.List;

public class ReceptionDbHelper extends IDbHelper<Reception> {
private static ReceptionDbHelper mHelper;

private ReceptionDbHelper() {

}

public static ReceptionDbHelper getInstance() {
if (mHelper == null)
mHelper = new ReceptionDbHelper();
return mHelper;
}

@Override
public void add(Reception reception) {
if(has(reception)){
update(reception);
} else{
SQLiteDatabase db = DatabaseImpl.getDatabase().getDb();
ContentValues values = new ReceptionBuilder().deconstruct(reception);
db.insert(DatabaseImpl.TABLE_RECEPTION, null, values);
}
}

@Override
public void delete(Reception reception) {
SQLiteDatabase db = DatabaseImpl.getDatabase().getDb();
db.delete(DatabaseImpl.TABLE_RECEPTION, "name =?", new String[]{reception.name});
}

public void deleteAll() {
SQLiteDatabase db = DatabaseImpl.getDatabase().getDb();
db.execSQL("delete from reception");
}

@Override
public void update(Reception reception) {
SQLiteDatabase db = DatabaseImpl.getDatabase().getDb();
ContentValues values = new ReceptionBuilder().deconstruct(reception);
db.update(DatabaseImpl.TABLE_RECEPTION, values, "name = ?", new String[]{reception.name});
}

@Override
public Reception get(Object name) {
SQLiteDatabase database = null;
Cursor cursor = null;
try {
database = DatabaseImpl.getDatabase().getDb();
cursor = database.rawQuery("select * from reception where name = ?", new String[]{(String)name});
while (cursor.moveToNext()) {
Reception reception = new ReceptionBuilder().build(cursor);
return reception;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
return null;
}

@Override
public List<Reception> getAll() {
SQLiteDatabase database = null;
List<Reception> receptionList = new ArrayList<>();
Cursor cursor = null;
try {
database = DatabaseImpl.getDatabase().getDb();
cursor = database.rawQuery("select * from reception", new String[]{});
while (cursor.moveToNext()) {
Reception reception = new ReceptionBuilder().build(cursor);
receptionList.add(reception);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
return receptionList;
}

@Override
public boolean has(Reception reception) {
SQLiteDatabase database = null;
Cursor cursor = null;
try {
database = DatabaseImpl.getDatabase().getDb();
cursor = database.rawQuery("select * from reception where name = ?",
new String[]{String.valueOf(reception.name)});
return cursor.getCount() > 0;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
return false;
}
}

+ 28
- 0
app/src/main/java/com/aispeech/nativedemo/db/SettingBuilder.java Näytä tiedosto

@@ -0,0 +1,28 @@
package com.aispeech.nativedemo.db;

import android.content.ContentValues;
import android.database.Cursor;

import com.aispeech.nativedemo.entity.Reception;
import com.aispeech.nativedemo.entity.Setting;

import java.util.Collections;

public class SettingBuilder implements DatabaseBuilder<Setting>{

@Override
public Setting build(Cursor query) {
Setting setting = new Setting();
setting.isReceptionMode = (query.getInt(query.getColumnIndex("is_reception_mode")));
setting.hbUpdateTime = (query.getLong(query.getColumnIndex("hb_update_time")));
return setting;
}

@Override
public ContentValues deconstruct(Setting setting) {
ContentValues contentValues = new ContentValues();
contentValues.put("is_reception_mode",setting.isReceptionMode);
contentValues.put("hb_update_time",setting.hbUpdateTime);
return contentValues;
}
}

+ 107
- 0
app/src/main/java/com/aispeech/nativedemo/db/SettingDbHelper.java Näytä tiedosto

@@ -0,0 +1,107 @@
package com.aispeech.nativedemo.db;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.aispeech.nativedemo.entity.Setting;

import java.util.ArrayList;
import java.util.List;

public class SettingDbHelper extends IDbHelper<Setting> {
private static SettingDbHelper mHelper;

private SettingDbHelper() {

}

public static SettingDbHelper getInstance() {
if (mHelper == null)
mHelper = new SettingDbHelper();
return mHelper;
}

@Override
public void add(Setting setting) {
if(has(setting)){
update(setting);
} else{
SQLiteDatabase db = DatabaseImpl.getDatabase().getDb();
ContentValues values = new SettingBuilder().deconstruct(setting);
db.insert(DatabaseImpl.TABLE_SETTING, null, values);
}
}

@Override
public void delete(Setting setting) {
SQLiteDatabase db = DatabaseImpl.getDatabase().getDb();
db.delete(DatabaseImpl.TABLE_SETTING, "id =?", new String[]{String.valueOf(setting.id)});
}

@Override
public void update(Setting setting) {
SQLiteDatabase db = DatabaseImpl.getDatabase().getDb();
ContentValues values = new SettingBuilder().deconstruct(setting);
db.update(DatabaseImpl.TABLE_SETTING, values, "id = ?", new String[]{String.valueOf(setting.id)});
}

@Override
public Setting get(Object id) {
SQLiteDatabase database = null;
Cursor cursor = null;
try {
database = DatabaseImpl.getDatabase().getDb();
cursor = database.rawQuery("select * from setting where id = ?", new String[]{(String) id});
while (cursor.moveToNext()) {
Setting setting = new SettingBuilder().build(cursor);
return setting;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
return null;
}

@Override
public List<Setting> getAll() {
SQLiteDatabase database = null;
List<Setting> settingList = new ArrayList<>();
Cursor cursor = null;
try {
database = DatabaseImpl.getDatabase().getDb();
cursor = database.rawQuery("select * from setting", new String[]{});
while (cursor.moveToNext()) {
Setting setting = new SettingBuilder().build(cursor);
settingList.add(setting);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
return settingList;
}

@Override
public boolean has(Setting setting) {
SQLiteDatabase database = null;
Cursor cursor = null;
try {
database = DatabaseImpl.getDatabase().getDb();
cursor = database.rawQuery("select * from setting where id = ?",
new String[]{String.valueOf(setting.id)});
return cursor.getCount() > 0;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
return false;
}
}

+ 37
- 0
app/src/main/java/com/aispeech/nativedemo/db/StrangerBuilder.java Näytä tiedosto

@@ -0,0 +1,37 @@
package com.aispeech.nativedemo.db;

import android.content.ContentValues;
import android.database.Cursor;

import com.aispeech.nativedemo.entity.Emp;
import com.aispeech.nativedemo.entity.Stranger;
import com.aispeech.nativedemo.utils.Utils;

public class StrangerBuilder implements DatabaseBuilder<Stranger>{

@Override
public Stranger build(Cursor query) {
Stranger stranger = new Stranger();
stranger.id = (query.getString(query.getColumnIndex("id")));
stranger.userId = (query.getString(query.getColumnIndex("user_id")));
stranger.nickName = (query.getString(query.getColumnIndex("user_name")));
stranger.tag = (query.getString(query.getColumnIndex("tag")));
stranger.gender = (query.getInt(query.getColumnIndex("gender")));
stranger.timestamp = (query.getLong(query.getColumnIndex("timestamp")));
stranger.faceFeatures = Utils.ByteArrayToFloatArray(query.getBlob(query.getColumnIndex("face_feature")));
return stranger;
}

@Override
public ContentValues deconstruct(Stranger stranger) {
ContentValues contentValues = new ContentValues();
contentValues.put("id",stranger.id);
contentValues.put("user_id",stranger.userId);
contentValues.put("user_name",stranger.nickName);
contentValues.put("tag",stranger.tag);
contentValues.put("gender",stranger.gender);
contentValues.put("timestamp",stranger.timestamp);
contentValues.put("face_feature",Utils.FloatArrayToByteArray(stranger.faceFeatures));
return contentValues;
}
}

+ 112
- 0
app/src/main/java/com/aispeech/nativedemo/db/StrangerDbHelper.java Näytä tiedosto

@@ -0,0 +1,112 @@
package com.aispeech.nativedemo.db;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.aispeech.nativedemo.entity.Stranger;

import java.util.ArrayList;
import java.util.List;

public class StrangerDbHelper extends IDbHelper<Stranger> {
private static StrangerDbHelper mHelper;

private StrangerDbHelper() {

}

public static StrangerDbHelper getInstance() {
if (mHelper == null)
mHelper = new StrangerDbHelper();
return mHelper;
}

@Override
public void add(Stranger stranger) {
if(has(stranger)){
update(stranger);
} else{
SQLiteDatabase db = DatabaseImpl.getDatabase().getDb();
ContentValues values = new StrangerBuilder().deconstruct(stranger);
db.insert(DatabaseImpl.TABLE_STRANGER, null, values);
}
}

@Override
public void delete(Stranger stranger) {
SQLiteDatabase db = DatabaseImpl.getDatabase().getDb();
db.delete(DatabaseImpl.TABLE_STRANGER, "user_id =?", new String[]{stranger.userId});
}

public void deleteAll() {
SQLiteDatabase db = DatabaseImpl.getDatabase().getDb();
db.execSQL("delete from new_user_faces");
}

@Override
public void update(Stranger stranger) {
SQLiteDatabase db = DatabaseImpl.getDatabase().getDb();
ContentValues values = new StrangerBuilder().deconstruct(stranger);
db.update(DatabaseImpl.TABLE_STRANGER, values, "user_id = ?", new String[]{stranger.id});
}

@Override
public Stranger get(Object userId) {
SQLiteDatabase database = null;
Cursor cursor = null;
try {
database = DatabaseImpl.getDatabase().getDb();
cursor = database.rawQuery("select * from new_user_faces where user_id = ?", new String[]{(String)userId});
while (cursor.moveToNext()) {
Stranger stranger = new StrangerBuilder().build(cursor);
return stranger;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
return null;
}

@Override
public List<Stranger> getAll() {
SQLiteDatabase database = null;
List<Stranger> strangerList = new ArrayList<>();
Cursor cursor = null;
try {
database = DatabaseImpl.getDatabase().getDb();
cursor = database.rawQuery("select * from new_user_faces", new String[]{});
while (cursor.moveToNext()) {
Stranger stranger = new StrangerBuilder().build(cursor);
strangerList.add(stranger);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
return strangerList;
}

@Override
public boolean has(Stranger stranger) {
SQLiteDatabase database = null;
Cursor cursor = null;
try {
database = DatabaseImpl.getDatabase().getDb();
cursor = database.rawQuery("select * from new_user_faces where eid = ?",
new String[]{String.valueOf(stranger.id)});
return cursor.getCount() > 0;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
return false;
}
}

+ 6
- 12
app/src/main/java/com/aispeech/nativedemo/dds/DDSManager.java Näytä tiedosto

@@ -1,7 +1,6 @@
package com.aispeech.nativedemo.dds;

import android.app.Activity;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

@@ -12,8 +11,8 @@ import com.aispeech.dui.dds.exceptions.DDSNotInitCompleteException;
import com.aispeech.nativedemo.MainActivity;
import com.aispeech.nativedemo.R;
import com.aispeech.nativedemo.asr.observer.DuiMessageObserver;
import com.aispeech.nativedemo.config.Config;
import com.aispeech.nativedemo.log.Logger;
import com.aispeech.nativedemo.network.ws.MessageUtils;
import com.aispeech.nativedemo.network.ws.WebSocketManager;

import org.json.JSONException;
@@ -102,21 +101,16 @@ public class DDSManager {

public void speakText(String text){
synchronized (lock){
try {
// try {
// if (!DuiMessageObserver.mIsSleep) {
// DDS.getInstance().getAgent().stopDialog();
// }
// DDS.getInstance().getAgent().avatarClick(text);
// DDS.getInstance().getAgent().sendText("");
if(!TextUtils.isEmpty(text)){
JSONObject jo = new JSONObject();
jo.put("type", "djTtsText");
jo.put("data", text);
WebSocketManager.getInstance(MainActivity.instance).sendMsg(jo.toString());
}
} catch (JSONException e) {
throw new RuntimeException(e);
}
// } catch (DDSNotInitCompleteException e) {
// throw new RuntimeException(e);
// }
MessageUtils.sendTtsText(text);
}

}


+ 3
- 0
app/src/main/java/com/aispeech/nativedemo/entity/PersonInfo.java Näytä tiedosto

@@ -1,5 +1,6 @@
package com.aispeech.nativedemo.entity;

import android.graphics.Bitmap;
import android.os.SystemClock;

import com.lenovo.lefacesdk.MultiAtt;
@@ -20,6 +21,8 @@ public class PersonInfo {
public MultiAtt result;
public int faceWidth; //x值
public int times;
public Bitmap bitmap;
public float[] dfeatures;

public PersonInfo(){



+ 60
- 0
app/src/main/java/com/aispeech/nativedemo/entity/Reception.java Näytä tiedosto

@@ -0,0 +1,60 @@
package com.aispeech.nativedemo.entity;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class Reception implements Serializable {
public String name; //接待任务名称
public String date; //接待日期
public List<String> guide; //负责人
public List<String> first; //第一优先级
public List<String> second; //第二优先级
public List<String> third; //第三优先级
public String underpinWord; //托底话术

public Reception(){
guide = new ArrayList<>();
first = new ArrayList<>();
second = new ArrayList<>();
third = new ArrayList<>();
}

public Reception create(JSONObject object){
try {
this.name = object.optString("name");
this.date = object.optString("date");
if(object.has("guide")){
JSONArray guideArray = object.getJSONArray("guide");
for (int i = 0; i < guideArray.length(); i++) {
guide.add(guideArray.getString(i));
}
}
if(object.has("first")){
JSONArray firstArray = object.getJSONArray("first");
for (int i = 0; i < firstArray.length(); i++) {
first.add(firstArray.getString(i));
}
}
if(object.has("second")){
JSONArray secondArray = object.getJSONArray("second");
for (int i = 0; i < secondArray.length(); i++) {
second.add(secondArray.getString(i));
}
}
if(object.has("third")){
JSONArray thirdArray = object.getJSONArray("third");
for (int i = 0; i < thirdArray.length(); i++) {
second.add(thirdArray.getString(i));
}
}
} catch (JSONException e) {
throw new RuntimeException(e);
}
return this;
}
}

+ 9
- 0
app/src/main/java/com/aispeech/nativedemo/entity/Setting.java Näytä tiedosto

@@ -0,0 +1,9 @@
package com.aispeech.nativedemo.entity;

import java.io.Serializable;

public class Setting implements Serializable {
public int id;
public int isReceptionMode; //接待模式 1.是 0.否
public long hbUpdateTime; //心跳更新时间戳
}

+ 35
- 0
app/src/main/java/com/aispeech/nativedemo/entity/Stranger.java Näytä tiedosto

@@ -0,0 +1,35 @@
package com.aispeech.nativedemo.entity;

import androidx.annotation.NonNull;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.Serializable;

public class Stranger implements Serializable {
public String id;
public String userId;
public String nickName;
public String tag;
public int gender;
public long timestamp;
public float[] faceFeatures;

@NonNull
@Override
public String toString() {
JSONObject object = new JSONObject();
try {
object.put("id", id);
object.put("userId", userId);
object.put("nickName", nickName);
object.put("tag", tag);
object.put("gender", gender);
object.put("timestamp", gender);
} catch (JSONException e) {
throw new RuntimeException(e);
}
return object.toString();
}
}

+ 67
- 0
app/src/main/java/com/aispeech/nativedemo/entity/Vip.java Näytä tiedosto

@@ -0,0 +1,67 @@
package com.aispeech.nativedemo.entity;

import android.graphics.Bitmap;

import com.lenovo.lefacesdk.MultiAtt;

import org.json.JSONException;
import org.json.JSONObject;

public class Vip {
public String id;
public String name; //昵称
public String tag; //人物类别
public int gender;
public int trackId;
public float score; //人像对比得分
public long startTime; //识别结果时间
public long updateTime; //识别更新时间
public long candidateTime; //候选时间
public MultiAtt result;
public int faceWidth; //x值
public int times;
public Bitmap bitmap;
public float[] dfeatures;
public boolean isGreet;

public Vip(){

}

public Vip(String id, String name, String tag, int times, int gender, int trackId, float score, MultiAtt att){
this.id = id;
this.name = name;
this.tag = tag;
this.times = times;
this.gender = gender;
this.trackId = trackId;
this.score = score;
this.result = att;
this.startTime = this.updateTime = System.currentTimeMillis();
this.faceWidth = result.fa_w;
}

public boolean isStranger(){
return id.equals("-2");
}

public String toString(){
try {
JSONObject obj = new JSONObject();
obj.put("id", id);
obj.put("name", name);
obj.put("tag", tag);
obj.put("gender", gender);
obj.put("trackId", trackId);
obj.put("score", score);
obj.put("fa_x", (result.fa_x1 + result.fa_x2) / 2);
obj.put("bd_x", (result.bd_x1 + result.bd_x2) / 2);
long time = System.currentTimeMillis();
obj.put("ts", time / 1000 + "." + time % 1000);
return obj.toString();
} catch (JSONException e) {
e.printStackTrace();
}
return super.toString();
}
}

+ 780
- 0
app/src/main/java/com/aispeech/nativedemo/face/FaceChatMode.java Näytä tiedosto

@@ -0,0 +1,780 @@
package com.aispeech.nativedemo.face;

import android.graphics.Bitmap;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;

import com.aispeech.nativedemo.DuiApplication;
import com.aispeech.nativedemo.asr.observer.DuiMessageObserver;
import com.aispeech.nativedemo.config.Config;
import com.aispeech.nativedemo.db.EmpDbHelper;
import com.aispeech.nativedemo.db.ModelDbHelper;
import com.aispeech.nativedemo.db.SkillDbHelper;
import com.aispeech.nativedemo.db.StrangerDbHelper;
import com.aispeech.nativedemo.entity.Emp;
import com.aispeech.nativedemo.entity.Model;
import com.aispeech.nativedemo.entity.PersonInfo;
import com.aispeech.nativedemo.entity.Skill;
import com.aispeech.nativedemo.entity.Stranger;
import com.aispeech.nativedemo.log.Logger;
import com.aispeech.nativedemo.network.ws.MessageUtils;
import com.aispeech.nativedemo.utils.BmpCompressUtils;
import com.aispeech.nativedemo.utils.HttpUtil;
import com.aispeech.nativedemo.utils.Utils;
import com.lenovo.lefacesdk.IdentificationResult;
import com.lenovo.lefacesdk.MultiAtt;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.stream.Stream;

import cz.msebera.android.httpclient.extras.Base64;
import okhttp3.MediaType;
import okhttp3.RequestBody;

public class FaceChatMode {
private static final String TAG = "FaceChatMode";
private static Map<String, PersonInfo> mPersons = new HashMap<>();
private static Map<Integer, PersonInfo> mUndeterminedPersons = new HashMap<>();
private static PersonInfo mSelectPerson = null;
private static boolean isContainSelectPerson = false;
public static long mInterval = 0;

public static List<MultiAtt> detectMultiAtt(Bitmap textureBitmap) {
if(mInterval == 0){
mInterval = System.currentTimeMillis();
}
return FaceManager.getInstance().detectMultiAtt(textureBitmap);
}

public static boolean featExtract(List<MultiAtt> results, Bitmap textureBitmap) {
List<float[]> employeeList = FaceManager.getInstance().featExtract(results, textureBitmap);
isContainSelectPerson = false;
for (int j = 0; j < employeeList.size(); j++) {
float[] feat = employeeList.get(j);
if(feat.length != 256){
continue;
}
PersonInfo person = identifyFace(feat, results.get(j));
if(person != null){
person.dfeatures = feat;
person.bitmap = textureBitmap;
Logger.e("识别对象为:" + person.name);
if(mSelectPerson != null && person.id.equals(mSelectPerson.id)){
isContainSelectPerson = true;
}
if(person.id.equals("-2")){ //添加识别条件 人脸质量高和识别置信度底
if(mUndeterminedPersons.containsKey(person.trackId)){
PersonInfo origin = mUndeterminedPersons.get(person.trackId);
origin.updateTime = System.currentTimeMillis();
origin.result = person.result;
origin.faceWidth = person.faceWidth;
origin.bitmap = person.bitmap;
mUndeterminedPersons.put(person.trackId, origin);
} else{
mUndeterminedPersons.put(person.trackId, person);
}
} else{
//已经认出人的处理
if(mPersons.containsKey(person.id)){
PersonInfo origin = mPersons.get(person.id);
origin.updateTime = System.currentTimeMillis();
origin.result = person.result;
origin.faceWidth = person.faceWidth;
origin.bitmap = person.bitmap;
mPersons.put(person.id, origin);
} else{
mPersons.put(person.id, person);
}
//
if(mUndeterminedPersons.containsKey(person.trackId)){
mUndeterminedPersons.remove(person.trackId);
}

}
}
}
if(System.currentTimeMillis() - mInterval < 1000){
return false;
}
// sendStrangerToServer();
mInterval = System.currentTimeMillis();
return true;
}

//过滤人物
public static void filterPersonForFeatExtract(List<MultiAtt> results, Bitmap textureBitmap){
filterExactLyFace(results, textureBitmap);
filterUndeterminedFace(results, textureBitmap);
}

public static void confirmCurrentPerson(Bitmap textureBitmap){
if(mPersons.size() == 0 && mUndeterminedPersons.size() == 0){
return;
}
//第二阶段 判断当前人
if(mSelectPerson == null){
if(mPersons.size() == 0){
if(mUndeterminedPersons.size() > 0){
//选择未确定脸大的人
mSelectPerson = selectUnknownMaxFacePerson(mUndeterminedPersons);
sendMsgAndLog(textureBitmap);
}
return;
} else{
mSelectPerson = selectKnownMaxTagAndFacePerson();
}
return;
}
//当前选择人不为空
// filterHighLevelAndMaxFaceId(); //选出预选人 未确定face大 已确定身份高face大
selectCandidate(mSelectPerson.faceWidth);

Stream<PersonInfo> pInfos = mCandidates.stream().filter(item->System.currentTimeMillis() - item.candidateTime >= CANDIDATE_STAY_TIME);

Map<String,PersonInfo> candidatesKnown = new HashMap<>();
Map<Integer,PersonInfo> candidatesUnknown = new HashMap<>();

pInfos.forEach(new Consumer<PersonInfo>() {
@Override
public void accept(PersonInfo personInfo) {
if(personInfo.isStranger()){
candidatesUnknown.put(personInfo.trackId, personInfo);
} else{
candidatesKnown.put(personInfo.id, personInfo);
}
}
});

if(candidatesKnown.size() == 0){
if(candidatesUnknown.size() > 0){
mSelectPerson = selectUnknownMaxFacePerson(candidatesUnknown);
}
} else{
int maxTag = selectPersonMaxTag(candidatesKnown);
mSelectPerson = filterHighLevelAndMaxFacePerson(candidatesKnown, maxTag);
}
sendMsgAndLog(textureBitmap);
}

private static PersonInfo selectKnownMaxTagAndFacePerson(){
int maxTag = selectPersonMaxTag(mPersons);
return filterHighLevelAndMaxFacePerson(mPersons, maxTag);
// sendMsgAndLog(textureBitmap);
}

private static List<PersonInfo> mCandidates = new ArrayList<>();
/**
* 选择候选人
* @param faceSize
*/
private static void selectCandidate(int faceSize){
//TODO 过期处理
List<PersonInfo> candidates = new ArrayList<>();
long time = System.currentTimeMillis();
mPersons.forEach((key, value) -> {
if(value.faceWidth - faceSize > FACE_DIFF){
Optional<PersonInfo> pInfo = mCandidates.stream().filter(item->item.id.equals(key)).findFirst();
if(pInfo.isPresent()){
value.candidateTime = pInfo.get().candidateTime;
} else{
value.candidateTime = time;
}
candidates.add(value);
}
});
mUndeterminedPersons.forEach((key, value) -> {
if(value.isStranger() && value.faceWidth - faceSize > FACE_DIFF){
Optional<PersonInfo> pInfo = mCandidates.stream().filter(item->item.trackId == key).findFirst();
if(pInfo.isPresent()){
value.candidateTime = pInfo.get().candidateTime;
} else{
value.candidateTime = time;
}
candidates.add(value);
}
});
mCandidates.clear();
mCandidates = candidates;
}

private static int selectPersonMaxTag(Map<String, PersonInfo> persons){
AtomicReference<Integer> maxTag = new AtomicReference<>(100);
persons.forEach((key, value) -> {
int mTag = Integer.parseInt(value.tag);
if (mTag == 9) { //重要贵宾
maxTag.set(mTag);
} else {
if (maxTag.get() != 9) {
if (mTag < maxTag.get()) {
maxTag.set(mTag);
}
}
}
});
return maxTag.get();
}

/**
* 获取脸大的人
* @return
*/
private static PersonInfo selectUnknownMaxFacePerson(Map<Integer, PersonInfo> persons){
// 筛选脸大的人
if(persons == null || persons.size() == 0){
return null;
}
AtomicReference<Integer> trackId = new AtomicReference<>(-1);
AtomicReference<Integer> maxFace = new AtomicReference<>(0);
persons.forEach((key, value) -> {
if(value.faceWidth > maxFace.get()){
maxFace.set(value.faceWidth);
trackId.set(key);
}
});
return persons.get(trackId.get());
}

private static void filterExactLyFace(List<MultiAtt> results,Bitmap textureBitmap){ //判断在认识人列表中是否存在
Iterator<MultiAtt> it = results.iterator();
while(it.hasNext()){
//查找已有列表中是否这人
MultiAtt att = it.next();
for (Map.Entry<String, PersonInfo> entry : mPersons.entrySet()) {
String key = entry.getKey();
PersonInfo value = entry.getValue();
if (att.track_id == value.trackId) {
value.updateTime = System.currentTimeMillis();
value.faceWidth = att.fa_w;
value.result = att;
value.bitmap = textureBitmap;
mPersons.put(key, value);
it.remove();
}
}
}
}

private static void filterUndeterminedFace(List<MultiAtt> results,Bitmap textureBitmap) { //在未确定人列表中对比
/**
* 清理这轮未确定的人
*/
Iterator<Map.Entry<Integer, PersonInfo>> iterator = mUndeterminedPersons.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Integer, PersonInfo> entry = iterator.next();
PersonInfo person = entry.getValue();

Iterator<MultiAtt> it = results.iterator();
while(it.hasNext()){
MultiAtt att = it.next();
if(att.track_id == person.trackId){
iterator.remove();
if(mSelectPerson != null && person.trackId == mSelectPerson.trackId){
mSelectPerson = null;
}
break;
}
}
}
/**
* 将不符合条件的人加入未确定列表中
*/
Iterator<MultiAtt> it = results.iterator();
while(it.hasNext()){
//查找未确定列表中是否这人
MultiAtt att = it.next();
//加入已确定却是陌生人的人 不需要识别
if(mUndeterminedPersons.containsKey(att.track_id)){
PersonInfo stranger = mUndeterminedPersons.get(att.track_id);
if(stranger.id.equals("-2")){
stranger.updateTime = System.currentTimeMillis();
stranger.faceWidth = att.fa_w;
stranger.result = att;
stranger.bitmap = textureBitmap;
mUndeterminedPersons.put(att.track_id, stranger);
it.remove();
return;
}
}
if(att.hd_fa == 0 || (att.hd_fa > 0 && att.fa_quality < 0.6f)){
if(!mUndeterminedPersons.containsKey(att.track_id)){
PersonInfo message = new PersonInfo();
message.id = "-1";
message.name = "";
message.tag = "6";
message.trackId = att.track_id;
message.startTime = System.currentTimeMillis();
message.result = att;
message.faceWidth = att.fa_w;
message.bitmap = textureBitmap;
mUndeterminedPersons.put(att.track_id, message);
} else{
PersonInfo message = mUndeterminedPersons.get(att.track_id);
message.updateTime = System.currentTimeMillis();
message.faceWidth = att.fa_w;
message.result = att;
message.bitmap = textureBitmap;
mUndeterminedPersons.put(att.track_id, message);
}
it.remove();
}
}
}

private static final int PERSON_EXPIRE_TIME = 5000; //人物过期时间
private static final int UNKNOWN_PERSON_EXPIRE_TIME = 1500;
private static final int FACE_DIFF = 70;
private static final int CANDIDATE_STAY_TIME = 3000;


public static void deleteExpirePerson(){
deleteExistExpirePerson();
deleteUndeterminedExpirePerson();
}

public static void deleteExistExpirePerson(){
//删除过期人员
Iterator<Map.Entry<String, PersonInfo>> iterator = mPersons.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, PersonInfo> entry = iterator.next();
PersonInfo person = entry.getValue();
if(System.currentTimeMillis() - person.updateTime > PERSON_EXPIRE_TIME) {
iterator.remove();
//置空当前选择人
if(mSelectPerson != null && person.id.equals(mSelectPerson.id)){
mSelectPerson = null;
}
}
}
}

//mUndeterminedPersons 未确定人确定过程时直接清理
private static void deleteUndeterminedExpirePerson(){
Iterator<Map.Entry<Integer, PersonInfo>> iterator = mUndeterminedPersons.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Integer, PersonInfo> entry = iterator.next();
PersonInfo person = entry.getValue();
if(System.currentTimeMillis() - person.updateTime > UNKNOWN_PERSON_EXPIRE_TIME) {
iterator.remove();
//置空当前选择人
if(mSelectPerson != null && person.id.equals(mSelectPerson.id)){
mSelectPerson = null;
}
}
}
}

private static PersonInfo filterHighLevelAndMaxFacePerson(Map<String, PersonInfo> persons, final int maxTag){
Map<String, PersonInfo> samePersons = new HashMap<>();
//筛选出一组最大身份的人
persons.forEach((key, value) -> {
int mTag = Integer.parseInt(value.tag);
if(mTag == maxTag){
samePersons.put(value.id, value);
}
});
//筛选出最大脸数据
AtomicReference<String> maxFaceId = new AtomicReference<>("");
AtomicReference<Integer> maxFace = new AtomicReference<>(0);
samePersons.forEach((key, value) -> {
if(value.faceWidth > maxFace.get()){
maxFace.set(value.faceWidth);
maxFaceId.set(value.id);
}
});
return persons.get(maxFaceId.get());
}

private static void sendMsgAndLog(Bitmap textureBitmap){
if(mSelectPerson == null){
return;
}
FaceManager.getInstance().updateRect(mSelectPerson.result);
sendMsg(mSelectPerson);

/**
* 发送日志
*/
// String sendId = mSelectPerson.id;
// boolean isStranger = sendId.equals("-1") || sendId.equals("-2");
// if (!sendId.equals(lastUserID)) {
// lastUserID = sendId;
// nextLogTime = System.currentTimeMillis();
// sendLog(isStranger, sendId, mSelectPerson.tag, (mSelectPerson.score), BmpCompressUtils.getBytesByBitmap(Utils.CompressBmp(textureBitmap, mSelectPerson.result), 50, Bitmap.CompressFormat.JPEG));
// } else {
// if (System.currentTimeMillis() - nextLogTime > 60000) {
// lastUserID = sendId;
// nextLogTime = System.currentTimeMillis();
// sendLog(isStranger, sendId, mSelectPerson.tag, (mSelectPerson.score), BmpCompressUtils.getBytesByBitmap(Utils.CompressBmp(textureBitmap, mSelectPerson.result), 50, Bitmap.CompressFormat.JPEG));
// }
// }
sendStrangerToServer();

}

public static PersonInfo identifyFace(float[] feat, MultiAtt result) {
String id = "-2";
String name = "";
String tag = "6";
int times = -1;
int gender = (int) result.bd_gender;
float thRecognition = 0.80f; //范围确定
IdentificationResult recRes = null;

//底库无数据,所有人陌生人
if (Utils.userFaces.size() != 0) {
recRes = FaceManager.getInstance().identifyFace(feat);

if (recRes == null) {
Logger.e("----------底库中查无此人----------");
// return null;
return new PersonInfo(id, name, tag, -1, gender, result.track_id, 0, result);
}
// Log.e(TAG, "confidence: " + recRes.confidence);
if (recRes.confidence >= thRecognition) {
id = recRes.id.substring(0, recRes.id.length() - 2);
// Log.e(TAG, "Recognized as: " + id);
Emp emp = EmpDbHelper.getInstance().get(id);
if(emp == null){
return new PersonInfo("-2", name, tag, times, gender, result.track_id, recRes.confidence, result);
}
name = !TextUtils.isEmpty(emp.nickName) ? emp.nickName : emp.name; //两个名称都传给H5
gender = emp.gender == 0 ? (int) result.bd_gender : emp.gender;
tag = emp.typeId +"";
Logger.e(TAG, "------------识别到人:" + name + "-------------");
Set<String> strings = Utils.userLogs.keySet();
if (strings.contains(id)) {
times = 1;
}
return new PersonInfo(id, name, tag, times, gender, result.track_id, recRes.confidence, result);
} else{
return new PersonInfo("-2", name, tag, times, gender, result.track_id, recRes.confidence, result);
}
} else{
return new PersonInfo("-2", name, tag, times, gender, result.track_id, 0, result);
}
//加上输出日志

// Set<String> strings = Utils.userLogs.keySet();
// if (!strings.contains(id)) {
// DbHelper.Instance().addLogs(id, 1);
// Utils.userLogs.put(id, 1);
// }
}

public static void sendMsg(PersonInfo message) {
try {
JSONObject obj = new JSONObject();
obj.put("type", "faceIdentity");
JSONObject person = new JSONObject();
person.put("id", message.id);
person.put("name", message.name);
person.put("tag", message.tag);
person.put("gender", message.gender);
person.put("trackId", message.trackId);
person.put("score", message.score);
person.put("faceWidth", message.faceWidth);
person.put("isInPicture", isContainSelectPerson);
Skill skill = SkillDbHelper.getInstance().getByType(message.tag);
if(skill != null){
person.put("skillStatus", skill.status);
person.put("resp", skill.resp);
person.put("motionName", skill.motionName);
}
person.put("isSpeakFinish", DuiMessageObserver.mSpeakFinishStatus);
person.put("speakFinishTime", DuiMessageObserver.mSpeakFinishTime);

StringBuilder allUsers = new StringBuilder();
mPersons.forEach((key, value) -> {
allUsers.append(value.name).append(",");
});
int index = 1;
mUndeterminedPersons.forEach((key, value) -> {
allUsers.append("陌生人").append(index).append(",");
});
String all = allUsers.toString();
if(!TextUtils.isEmpty(all)){
all = all.substring(0, all.length() - 1);
}
person.put("allUsers", all);
// person.put("onDutyHourStart", "10:00");
// person.put("onDutyHourEnd", "10:30");
// person.put("offDutyHourStart", "17:00");
// person.put("offDutyHourEnd", "24:00");
// person.put("dutyWord", "打卡成功");

List<Model> modelList = ModelDbHelper.getInstance().getAll();
if(modelList != null && modelList.size() > 0){
Model model = modelList.get(0);
if(model.workdayHour != null){
person.put("onDutyHourStart", model.workdayHour.onDutyHourStart);
person.put("onDutyHourEnd", model.workdayHour.onDutyHourEnd);
person.put("offDutyHourStart", model.workdayHour.offDutyHourStart);
person.put("offDutyHourEnd", model.workdayHour.offDutyHourEnd);
person.put("dutyWord", "打卡成功");
}
if(model.workTime != null){
person.put("workdayHourStart", model.workTime.workdayHourStart);
person.put("workdayHourEnd", model.workTime.workdayHourEnd);
person.put("weekendHourStart", model.workTime.weekendHourStart);
person.put("weekendHourEnd", model.workTime.weekendHourEnd);
}
}
obj.put("data", person.toString());

Date date = new Date(System.currentTimeMillis());
SimpleDateFormat spTime = new SimpleDateFormat("yyyy-MM-dd/HH:mm:ss");//yyyy-MM-dd/HH:mm:ss HH24 hh12
String sT = spTime.format(date);
String sendingMsg = obj.toString();
Logger.e(sT + ":发送消息到H5: " + sendingMsg + "/");
MessageUtils.sendMessage(sendingMsg);
} catch (JSONException e) {
e.printStackTrace();
}
}

private void faceLimit(List<MultiAtt> results) {
int leftLimit = 100;
results.removeIf(e -> e.fa_x1 < leftLimit);
int rightLimit = 2060;
results.removeIf(e -> (e.fa_x1 + e.fa_w) > rightLimit);
int topLimit = 100;
results.removeIf(e -> e.fa_y1 < topLimit);
int bottomLimit = 3740;
results.removeIf(e -> e.fa_y1 + e.fa_h > bottomLimit);
}

private void bodyLimit(List<MultiAtt> results) { //以后修改
int leftLimit = 100;
results.removeIf(e -> e.bd_x1 < leftLimit);
int rightLimit = 2060;
results.removeIf(e -> (e.bd_x1 + e.bd_w) > rightLimit);
int topLimit = 100;
results.removeIf(e -> e.bd_y1 < topLimit);
int bottomLimit = 3740;
results.removeIf(e -> e.bd_y1 + e.bd_h > bottomLimit);
}

/**
* find the largest face
* @param results
*/
private void faceROIFilter(List<MultiAtt> results) {
int maxFace = 0;
for (MultiAtt att : results) {
// if(mLastTrackId == att.track_id){
// Log.e(TAG,"------------------tracked---------------------");
// results.removeIf(e -> (e.track_id) != mLastTrackId);
// return;
// }
if(att.fa_w > maxFace) {
maxFace = att.fa_w;
}
}
int maxFaceSize = maxFace;
results.removeIf(e -> (e.fa_w) < maxFaceSize);
}

private void faceSizeFilter(List<MultiAtt> results) {
int minFaceSize = 140;
results.removeIf(e -> (e.fa_w) < minFaceSize);
}

private void faceQualityFilter(List<MultiAtt> results) {
boolean enableQualityFilter = true;
float thQuality = 0.60f;
if (enableQualityFilter) results.removeIf(e -> (e.fa_quality) < thQuality);
}

public boolean hasPerson(){
MessageUtils.sendMessage("识别人数量:" + mPersons.size() + " 未识别人数量:" + mUndeterminedPersons.size());
if(mPersons.size() > 0 || mUndeterminedPersons.size() > 0){
return true;
}
// if(mPersons.size() > 0){
// return true;
// } else if(mUndeterminedPersons.size() > 0){
// Iterator <Map.Entry< Integer, PersonInfo >> iterator = mUndeterminedPersons.entrySet().iterator();
// while (iterator.hasNext()) {
// Map.Entry< Integer, PersonInfo > entry = iterator.next();
// if(entry.getValue().result.fa_quality > 0.6f){
// return true;
// }
// }
// }
return false;
}

private void sendLog(boolean isStranger, String userId, String type, float confidence, byte[] bitmapBytes) {
String base64 = Base64.encodeToString(bitmapBytes, Base64.DEFAULT);

HashMap<String, String> postParam = new HashMap<>();
postParam.put("devId", Build.SERIAL);
postParam.put("timestamp", System.currentTimeMillis() + "");
postParam.put("userId", userId);
postParam.put("type", type);
postParam.put("faceScore", confidence + "");
postParam.put("imgbase64", base64.replace("\n", "").replace("\\", "") + "");
postParam.put("sign", "123456");

RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), new JSONObject(postParam).toString());
HttpUtil.post(Config.CURRENT_URL + "system/pass/api/upload-pass", requestBody, null, new HttpUtil.HttpCallback<String>() {
@Override
public void onSuccess(String success) {
try {
JSONTokener t = new JSONTokener(success);
JSONObject obj = (JSONObject) t.nextValue();
int status = -1001001;
String errMsg = "";

if (obj.has("status")) {
status = obj.getInt("status");
}
if (obj.has("errMsg")) {
errMsg = obj.getString("errMsg");
}

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String time = dateFormat.format(new Date(System.currentTimeMillis()));
if (status == 0) {
Logger.e(time + ":上传人脸日志成功: id =" + userId);
} else {
Logger.e(time + ":上传人脸日志失败: error =" + errMsg);
onFail(errMsg);
}
} catch (Exception e) {
e.printStackTrace();
onFail(e.getMessage());
}
}

@Override
public void onFail(String error) {
Log.e(TAG, "sendLog onFail: " + error);
}
});
}

public static void sendStrangerToServer(){
//有人脸且质量合格的陌生人才会发到服务端
Stream<PersonInfo> pInfos = mUndeterminedPersons.values().stream().filter(item-> item.result.hd_fa > 0 && item.result.fa_quality > 0.8f);
if(pInfos.count() == 0){
return;
}
Stream<PersonInfo> pInfos2 = mUndeterminedPersons.values().stream().filter(item-> item.result.hd_fa > 0 && item.result.fa_quality > 0.8f);
JSONArray array = new JSONArray();
pInfos2.forEach(new Consumer<PersonInfo>() {
@Override
public void accept(PersonInfo personInfo) {
Stranger stranger = null;
if(Utils.userNewFaces.size() > 0){
//陌生人人脸底库对比
IdentificationResult recRes = FaceManager.getInstance().identifyFace(personInfo.dfeatures);
if (recRes == null) {
stranger = saveStranger(personInfo);
} else{
if (recRes.confidence >= 0.8f) {
String id = recRes.id.substring(0, recRes.id.length() - 2);
Stranger s = StrangerDbHelper.getInstance().get(id);
if(s != null && System.currentTimeMillis() - s.timestamp > 10 * 1000){
s.timestamp = System.currentTimeMillis();
s.faceFeatures = personInfo.dfeatures;
s.userId = id + "";
s.tag = personInfo.tag;
StrangerDbHelper.getInstance().update(s);
stranger = s;
}
}
}
} else{
stranger = saveStranger(personInfo);
}
if(stranger != null){
try {
JSONObject object = new JSONObject();
object.put("userId",stranger.userId);
byte[] bitmapBytes = BmpCompressUtils.getBytesByBitmap(Utils.CompressBmp(personInfo.bitmap, mSelectPerson.result), 100, Bitmap.CompressFormat.JPEG);
String base64 = Base64.encodeToString(bitmapBytes, Base64.DEFAULT);
object.put("imgbase64", base64.replace("\n", "").replace("\\", "") + "");
object.put("type", personInfo.tag);
object.put("faceScore", personInfo.score);
array.put(object);
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
}
});

if(array.length() == 0){
return;
}
HashMap<String, Object> postParam = new HashMap<>();
postParam.put("devId", Build.SERIAL);
postParam.put("timestamp", System.currentTimeMillis() + "");
postParam.put("sign", "123456");
postParam.put("records", array);

RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), new JSONObject(postParam).toString());
HttpUtil.post(Config.CURRENT_URL + "system/pass/api/upload-multi-pass", requestBody, null, new HttpUtil.HttpCallback<String>() {
@Override
public void onSuccess(String success) {
try {
JSONTokener t = new JSONTokener(success);
JSONObject obj = (JSONObject) t.nextValue();
int status = -1001001;
String errMsg = "";
if (obj.has("status")) {
status = obj.getInt("status");
}
if (obj.has("errMsg")) {
errMsg = obj.getString("errMsg");
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String time = dateFormat.format(new Date(System.currentTimeMillis()));
if (status == 0) {
Logger.e(time + ":批量上传人脸日志成功");
} else {
Logger.e(time + ":批量上传人脸日志失败: error =" + errMsg);
onFail(errMsg);
}
} catch (Exception e) {
e.printStackTrace();
onFail(e.getMessage());
}
}

@Override
public void onFail(String error) {
Log.e(TAG, "sendStrangerToServer onFail: " + error);
}
});
}

public static Stranger saveStranger(PersonInfo personInfo) {
long id = System.currentTimeMillis();
Utils.userNewFaces.put(id + "_1", personInfo.dfeatures);
Stranger stranger = new Stranger();
stranger.timestamp = id;
stranger.userId = id + "";
stranger.tag = personInfo.tag;
stranger.faceFeatures = personInfo.dfeatures;
StrangerDbHelper.getInstance().add(stranger);
return stranger;
}
}

+ 711
- 674
app/src/main/java/com/aispeech/nativedemo/face/FaceManager.java
File diff suppressed because it is too large
Näytä tiedosto


+ 396
- 0
app/src/main/java/com/aispeech/nativedemo/face/FaceReceptionMode.java Näytä tiedosto

@@ -0,0 +1,396 @@
package com.aispeech.nativedemo.face;

import android.graphics.Bitmap;
import android.text.TextUtils;

import com.aispeech.nativedemo.db.EmpDbHelper;
import com.aispeech.nativedemo.entity.Emp;
import com.aispeech.nativedemo.entity.PersonInfo;
import com.aispeech.nativedemo.entity.Reception;
import com.aispeech.nativedemo.log.Logger;
import com.aispeech.nativedemo.network.ws.MessageUtils;
import com.aispeech.nativedemo.utils.Utils;
import com.lenovo.lefacesdk.IdentificationResult;
import com.lenovo.lefacesdk.MultiAtt;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

public class FaceReceptionMode {
private static final String TAG = "FaceReceptionMode";
private static final long COLLECT_TIME = 2000l;
private final static long ROUND_TIMES = 3;
private final static long SESSION_TIME = 5 * 60 * 1000;
private static int mCollectTimes = 0;
private static Map<String, PersonInfo> mGreetPersons = new HashMap<>();
private static Map<String, PersonInfo> mUngreetPersons = new HashMap<>();
private static Map<Integer, PersonInfo> mUndeterminedPersons = new HashMap<>();
public static long mInterval = 0;
public static Reception mReception = null;
public static boolean isStrangerAsk = false;
public static long mFreeTime = 0;

public static List<MultiAtt> detectMultiAtt(Bitmap textureBitmap) {
if(mInterval == 0){
mInterval = System.currentTimeMillis();
}
if(mFreeTime == 0){
mFreeTime = System.currentTimeMillis();
}
return FaceManager.getInstance().detectMultiAtt(textureBitmap);
}

public static void checkSessionExpire(boolean isSelf){
if(isSelf || System.currentTimeMillis() - mFreeTime > SESSION_TIME){
MessageUtils.receptionModeStep("会话时间超时,结束接待模式");
IdentityMode.MODE_CURRENT = IdentityMode.MODE_CHAT;
mUngreetPersons.clear();
mGreetPersons.clear();
mUndeterminedPersons.clear();
mCollectTimes = 0;
mReception = null;
mFreeTime = 0;
isStrangerAsk = false;
mInterval = 0;
MessageUtils.endReceptionMode();
}
}

public static boolean featExtract(List<MultiAtt> results, Bitmap textureBitmap) {
mFreeTime = System.currentTimeMillis();
List<float[]> employeeList = FaceManager.getInstance().featExtract(results, textureBitmap);
for (int j = 0; j < employeeList.size(); j++) {
float[] feat = employeeList.get(j);
if(feat.length != 256){
continue;
}
PersonInfo person = identifyFace(feat, results.get(j));
if(person != null){
person.dfeatures = feat;
person.bitmap = textureBitmap;
Logger.e("识别对象为:" + person.name);
if(person.id.equals("-2")){ //添加识别条件 人脸质量高和识别置信度底
if(mUndeterminedPersons.containsKey(person.trackId)){
PersonInfo origin = mUndeterminedPersons.get(person.trackId);
origin.updateTime = System.currentTimeMillis();
origin.result = person.result;
origin.faceWidth = person.faceWidth;
origin.bitmap = person.bitmap;
mUndeterminedPersons.put(person.trackId, origin);
} else{
mUndeterminedPersons.put(person.trackId, person);
}
} else{
//已经认出人的处理
if(mGreetPersons.containsKey(person.id)){
//已打招呼不处理
continue;
}
if(mUngreetPersons.containsKey(person.id)){
//未打招呼更新
PersonInfo origin = mUngreetPersons.get(person.id);
origin.updateTime = System.currentTimeMillis();
origin.result = person.result;
origin.faceWidth = person.faceWidth;
origin.bitmap = person.bitmap;
mUngreetPersons.put(person.id, origin);
} else{
//未打招呼新增
mUngreetPersons.put(person.id, person);
}
//从未识别列表中移除
if(mUndeterminedPersons.containsKey(person.trackId)){
mUndeterminedPersons.remove(person.trackId);
}
}
}
}
if(System.currentTimeMillis() - mInterval < COLLECT_TIME){
return false;
}
mInterval = System.currentTimeMillis();
mCollectTimes++;

if(mCollectTimes == ROUND_TIMES){
MessageUtils.receptionModeStep("第3轮收集数据,开始打招呼");
mCollectTimes = 0;
return true;
} else{
MessageUtils.receptionModeStep("第" + mCollectTimes + "轮收集数据");
}
return false;
}

public static void confirmCurrentWord(){
if(mUngreetPersons.size() == 0 && mUndeterminedPersons.size() == 0){
if(mGreetPersons.size() > 0){
MessageUtils.receptionModeStep("已经打过招呼");
} else{
MessageUtils.receptionModeStep("没有识别到人");
}
return;
}
if(IdentityMode.MODE_CURRENT != IdentityMode.MODE_RECEPTION){
MessageUtils.receptionModeStep("当前不是接待模式");
return;
}
Reception reception = mReception;
if(reception == null){
MessageUtils.receptionModeStep("接待任务为空");
return;
}
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat time = new SimpleDateFormat("MM-dd");
String dateStr = time.format(date);
if(!dateStr.equals(reception.date)){
MessageUtils.receptionModeStep("不在接待时间范围内");
return;
}
StringBuilder word = new StringBuilder();
AtomicInteger index1 = new AtomicInteger(0);
mUngreetPersons.forEach((key, person) -> {
if(person.tag.equals("4")){
index1.getAndIncrement();
word.append(person.name).append(",");
}
});
if(index1.get() > 0){
word.append(index1.get() > 1 ? "你们好," : "您好,");
}
AtomicInteger index2 = new AtomicInteger(0);
mUngreetPersons.forEach((key, person) -> {
if(person.tag.equals("5")){
index2.getAndIncrement();
word.append(person.name).append(",");
}
});
if(index2.get() > 0){
word.append(index2.get() > 1 ? "你们好," : "你好,");
}

AtomicInteger index3 = new AtomicInteger(0);
mUngreetPersons.forEach((key, person) -> {
String id = person.id;
if(reception.guide.size() > 0 && reception.first.contains(id)){
index3.getAndIncrement();
word.append(person.name).append(",");
}
});
mUngreetPersons.forEach((key, person) -> {
String id = person.id;
if(reception.guide.size() > 0 && reception.second.contains(id)){
index3.getAndIncrement();
word.append(person.name).append(",");
}
});
mUngreetPersons.forEach((key, person) -> {
String id = person.id;
if(reception.guide.size() > 0 && reception.third.contains(id)){
index3.getAndIncrement();
word.append(person.name).append(",");
}
});
if(index3.get() > 0){
word.append(index3.get() > 1 ? "你们好" : "你好");
}

if(TextUtils.isEmpty(word.toString())){
if(mUndeterminedPersons.size() > 2 && !isStrangerAsk){
MessageUtils.receptionModeStep("播放托底话术");
word.append(reception.underpinWord);
isStrangerAsk = true;
}
}
if(!TextUtils.isEmpty(word.toString())){
sendMsg(word.toString());
} else{
MessageUtils.receptionModeStep("招呼语为空");
}
}

//过滤人物
public static void filterPersonForFeatExtract(List<MultiAtt> results, Bitmap textureBitmap){
filterExactLyFace(results, mGreetPersons, textureBitmap);
filterExactLyFace(results, mUngreetPersons, textureBitmap);
filterUndeterminedFace(results, textureBitmap);
}

private static void filterExactLyFace(List<MultiAtt> results, Map<String, PersonInfo> persons, Bitmap textureBitmap){ //判断在认识人列表中是否存在
Iterator<MultiAtt> it = results.iterator();
while(it.hasNext()){
//查找已有列表中是否这人
MultiAtt att = it.next();
for (Map.Entry<String, PersonInfo> entry : persons.entrySet()) {
String key = entry.getKey();
PersonInfo value = entry.getValue();
if (att.track_id == value.trackId) {
value.updateTime = System.currentTimeMillis();
value.faceWidth = att.fa_w;
value.result = att;
value.bitmap = textureBitmap;
persons.put(key, value);
it.remove();
}
}
}
}

private static void filterUndeterminedFace(List<MultiAtt> results,Bitmap textureBitmap) { //在未确定人列表中对比
/**
* 清理这轮未确定的人
*/
Iterator<Map.Entry<Integer, PersonInfo>> iterator = mUndeterminedPersons.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Integer, PersonInfo> entry = iterator.next();
PersonInfo person = entry.getValue();

Iterator<MultiAtt> it = results.iterator();
while(it.hasNext()){
MultiAtt att = it.next();
if(att.track_id == person.trackId){
iterator.remove();
break;
}
}
}
/**
* 将不符合条件的人加入未确定列表中
*/
Iterator<MultiAtt> it = results.iterator();
while(it.hasNext()){
//查找未确定列表中是否这人
MultiAtt att = it.next();
//加入已确定却是陌生人的人 不需要识别
if(mUndeterminedPersons.containsKey(att.track_id)){
PersonInfo stranger = mUndeterminedPersons.get(att.track_id);
if(stranger.id.equals("-2")){
stranger.updateTime = System.currentTimeMillis();
stranger.faceWidth = att.fa_w;
stranger.result = att;
stranger.bitmap = textureBitmap;
mUndeterminedPersons.put(att.track_id, stranger);
it.remove();
return;
}
}
if(att.hd_fa == 0 || (att.hd_fa > 0 && att.fa_quality < 0.6f)){
if(!mUndeterminedPersons.containsKey(att.track_id)){
PersonInfo message = new PersonInfo();
message.id = "-1";
message.name = "";
message.tag = "6";
message.trackId = att.track_id;
message.startTime = System.currentTimeMillis();
message.result = att;
message.faceWidth = att.fa_w;
message.bitmap = textureBitmap;
mUndeterminedPersons.put(att.track_id, message);
} else{
PersonInfo message = mUndeterminedPersons.get(att.track_id);
message.updateTime = System.currentTimeMillis();
message.faceWidth = att.fa_w;
message.result = att;
message.bitmap = textureBitmap;
mUndeterminedPersons.put(att.track_id, message);
}
it.remove();
}
}
}

private static final int PERSON_EXPIRE_TIME = 10000; //人物过期时间
private static final int UNKNOWN_PERSON_EXPIRE_TIME = 10000;


public static void deleteExpirePerson(){
// deleteExistExpirePerson(mGreetPersons);
deleteExistExpirePerson(mUngreetPersons);
deleteUndeterminedExpirePerson();
}

public static void deleteExistExpirePerson(Map<String, PersonInfo> persons){
//删除过期人员
Iterator<Map.Entry<String, PersonInfo>> iterator = persons.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, PersonInfo> entry = iterator.next();
PersonInfo person = entry.getValue();
if(System.currentTimeMillis() - person.updateTime > PERSON_EXPIRE_TIME) {
iterator.remove();
}
}
}

//mUndeterminedPersons 未确定人确定过程时直接清理
private static void deleteUndeterminedExpirePerson(){
Iterator<Map.Entry<Integer, PersonInfo>> iterator = mUndeterminedPersons.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Integer, PersonInfo> entry = iterator.next();
PersonInfo person = entry.getValue();
if(System.currentTimeMillis() - person.updateTime > UNKNOWN_PERSON_EXPIRE_TIME) {
iterator.remove();
//置空当前选择人
}
}
}

public static PersonInfo identifyFace(float[] feat, MultiAtt result) {
String id = "-2";
String name = "";
String tag = "6";
int times = -1;
int gender = (int) result.bd_gender;
float thRecognition = 0.80f; //范围确定
IdentificationResult recRes = null;

//底库无数据,所有人陌生人
if (Utils.userFaces.size() != 0) {
recRes = FaceManager.getInstance().identifyFace(feat);

if (recRes == null) {
Logger.e("----------底库中查无此人----------");
// return null;
return new PersonInfo(id, name, tag, -1, gender, result.track_id, 0, result);
}
// Log.e(TAG, "confidence: " + recRes.confidence);
if (recRes.confidence >= thRecognition) {
id = recRes.id.substring(0, recRes.id.length() - 2);
// Log.e(TAG, "Recognized as: " + id);
Emp emp = EmpDbHelper.getInstance().get(id);
if(emp == null){
return new PersonInfo("-2", name, tag, times, gender, result.track_id, recRes.confidence, result);
}
name = !TextUtils.isEmpty(emp.nickName) ? emp.nickName : emp.name; //两个名称都传给H5
gender = emp.gender == 0 ? (int) result.bd_gender : emp.gender;
tag = emp.typeId +"";
Logger.e(TAG, "------------识别到人:" + name + "-------------");
Set<String> strings = Utils.userLogs.keySet();
if (strings.contains(id)) {
times = 1;
}
return new PersonInfo(id, name, tag, times, gender, result.track_id, recRes.confidence, result);
} else{
return new PersonInfo("-2", name, tag, times, gender, result.track_id, recRes.confidence, result);
}
} else{
return new PersonInfo("-2", name, tag, times, gender, result.track_id, 0, result);
}
}

public static void sendMsg(String message) {
MessageUtils.sendTtsNlpText(message);

Iterator<Map.Entry<String, PersonInfo>> iterator = mUngreetPersons.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, PersonInfo> entry = iterator.next();
PersonInfo person = entry.getValue();
mGreetPersons.put(person.id, person);
iterator.remove();
}
}
}

+ 7
- 0
app/src/main/java/com/aispeech/nativedemo/face/IdentityMode.java Näytä tiedosto

@@ -0,0 +1,7 @@
package com.aispeech.nativedemo.face;

public class IdentityMode {
public final static String MODE_CHAT = "chat";
public final static String MODE_RECEPTION = "reception";
public static String MODE_CURRENT = MODE_CHAT;
}

+ 26
- 0
app/src/main/java/com/aispeech/nativedemo/log/LogFile.java Näytä tiedosto

@@ -35,4 +35,30 @@ public class LogFile {
}
return null;
}

public static String saveDjLogMessageFile(String logMessage) {
logMessage = logMessage.replace("djlog-", "");
long timestamp = System.currentTimeMillis();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String time = dateFormat.format(new Date(timestamp));
StringBuffer sb = new StringBuffer();
sb.append(logMessage).append("\n");
try {
String fileName = "djlog-" + time + ".txt";
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File dir = new File(Config.FilePath.LOG_PATH);
if (!dir.exists()) {
dir.mkdirs();
}
FileOutputStream fos = new FileOutputStream(Config.FilePath.LOG_PATH + "/" + fileName,true);
String logFile = new String(sb.toString().getBytes(),"UTF-8");
fos.write(logFile.getBytes());
fos.close();
}
return fileName;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

+ 6
- 1
app/src/main/java/com/aispeech/nativedemo/log/LoggerPrinter.java Näytä tiedosto

@@ -377,7 +377,12 @@ final class LoggerPrinter implements Printer {
mSettings.getLogAdapter().d(finalTag, chunk);
break;
}
LogFile.saveLogMessageFile(chunk);
if(chunk.contains("djlog")){
LogFile.saveDjLogMessageFile(chunk);
} else{
LogFile.saveLogMessageFile(chunk);
}

// if (logType >= mSettings.getLog2FileLevel() && mSettings.isLog2File()) {
// LogFile.saveLogMessageFile(chunk, mSettings.getLogFilePath());
// }


+ 24
- 7
app/src/main/java/com/aispeech/nativedemo/network/ws/DigiWebSocketServer.java Näytä tiedosto

@@ -15,6 +15,8 @@ import com.aispeech.nativedemo.db.InitializeDbHelper;
import com.aispeech.nativedemo.dds.DDSManager;
import com.aispeech.nativedemo.entity.Initialize;
import com.aispeech.nativedemo.face.FaceManager;
import com.aispeech.nativedemo.face.FaceReceptionMode;
import com.aispeech.nativedemo.face.IdentityMode;
import com.aispeech.nativedemo.log.Logger;
import com.aispeech.nativedemo.mqtt.MqttManager;
import com.aispeech.nativedemo.network.DigiNetworkManager;
@@ -58,14 +60,15 @@ public class DigiWebSocketServer extends WebSocketServer {
Logger.e("onOpen()一个客户端连接成功:" + conn.getRemoteSocketAddress());
Utils.websocketList.add(conn.getRemoteSocketAddress().toString());
mConns.add(conn);
InetSocketAddress address = conn.getRemoteSocketAddress();
InetAddress address1 = address.getAddress();
String ad1 = address1.getHostAddress();
// InetSocketAddress address = conn.getRemoteSocketAddress();
// InetAddress address1 = address.getAddress();
// String ad1 = address1.getHostAddress();
// String ad2 = address1.getHostName();
getActivateStatus(ad1);
getActivateStatus();
MessageUtils.sendWakeupStatus(DuiMessageObserver.mIsSleep);
MessageUtils.sendFaceSDKInitStatus(FaceManager.getInstance(context).getInitResult());
MessageUtils.sendFaceSDKInitStatus(FaceManager.getInstance().getInitResult());
MessageUtils.sendSpeechSDKInitStatus(DDSService.initCompleted);
MessageUtils.getReceptionMode();
}

@Override
@@ -81,8 +84,14 @@ public class DigiWebSocketServer extends WebSocketServer {
public void onMessage(WebSocket conn, String message) {
// 这里在网页测试端发过来的是文本数据 测试网页 http://www.websocket-test.com/
// 需要保证android 和 加载网页的设备(我这边是电脑) 在同一个网段内,连同一个wifi即可
Logger.e("onMessage()网页端来的消息->" + conn.getRemoteSocketAddress() + ": " + message);
// Logger.e("onMessage()网页端来的消息->" + conn.getRemoteSocketAddress() + ": " + message);
//Collection<WebSocket> client = new ArrayList<>();
if(message.contains("djlog-")){
Logger.e(message);
return;
} else{
Logger.e("onMessage()网页端来的消息->" + conn.getRemoteSocketAddress() + ": " + message);
}
if (message.equals("ping")) {
broadcast("tong");
heartbeatTime = System.currentTimeMillis();
@@ -116,6 +125,14 @@ public class DigiWebSocketServer extends WebSocketServer {
} else{
DDSManager.getInstance().stopDDSDialog();
}
} else if(type.equals("receptionMode")){
boolean status = obj.optBoolean("status");
if(status){
IdentityMode.MODE_CURRENT = IdentityMode.MODE_RECEPTION;
} else{
IdentityMode.MODE_CURRENT = IdentityMode.MODE_CHAT;
FaceReceptionMode.checkSessionExpire(true);
}
}
} catch (JSONException e) {
throw new RuntimeException(e);
@@ -183,7 +200,7 @@ public class DigiWebSocketServer extends WebSocketServer {
mConns.clear();
}

private void getActivateStatus(String address) {
private void getActivateStatus() {
HashMap<String, String> map = new HashMap<>();
HttpUtil.get(Config.CURRENT_URL + "message/api/get_activate/" + Build.SERIAL, map, new HttpUtil.HttpCallback<String>() {



+ 62
- 3
app/src/main/java/com/aispeech/nativedemo/network/ws/MessageUtils.java Näytä tiedosto

@@ -7,19 +7,17 @@ import com.aispeech.dui.dds.DDS;
import com.aispeech.dui.dds.DDSMode;
import com.aispeech.dui.dds.exceptions.DDSNotInitCompleteException;
import com.aispeech.nativedemo.DuiApplication;
import com.aispeech.nativedemo.MainActivity;
import com.aispeech.nativedemo.asr.observer.DuiMessageObserver;
import com.aispeech.nativedemo.db.ModelDbHelper;
import com.aispeech.nativedemo.db.SkillDbHelper;
import com.aispeech.nativedemo.entity.Model;
import com.aispeech.nativedemo.entity.Skill;
import com.aispeech.nativedemo.log.Logger;
import com.aispeech.nativedemo.shape.ShapeManager;

import org.json.JSONException;
import org.json.JSONObject;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

public class MessageUtils {
@@ -195,6 +193,34 @@ public class MessageUtils {
}
}

public static void sendTtsText(String data){
try {
if(!TextUtils.isEmpty(data)){
JSONObject jo = new JSONObject();
jo.put("type", "djTtsText");
jo.put("data", data);
Logger.e("发给叠境tts:" + data);
sendMessage(jo.toString());
}
} catch (JSONException e) {
e.printStackTrace();
}
}

public static void sendTtsNlpText(String data){
try {
if(!TextUtils.isEmpty(data)){
JSONObject jo = new JSONObject();
jo.put("type", "djTtsNlpText");
jo.put("data", data);
Logger.e("思必驰NLP结果发给叠境tts:" + data);
sendMessage(jo.toString());
}
} catch (JSONException e) {
e.printStackTrace();
}
}

public static void sendRest(){
List<Model> modelList = ModelDbHelper.getInstance().getAll();
if(modelList != null && modelList.size() > 0){
@@ -232,4 +258,37 @@ public class MessageUtils {
e.printStackTrace();
}
}

public static void getReceptionMode(){
try {
JSONObject jo = new JSONObject();
jo.put("type", "getReceptionMode");
jo.put("data", "getReceptionMode");
sendMessage(jo.toString());
} catch (JSONException e) {
throw new RuntimeException(e);
}
}

public static void endReceptionMode(){
try {
JSONObject jo = new JSONObject();
jo.put("type", "reception");
jo.put("data", false);
sendMessage(jo.toString());
} catch (JSONException e) {
throw new RuntimeException(e);
}
}

public static void receptionModeStep(String message){
try {
JSONObject jo = new JSONObject();
jo.put("type", "receptionStep");
jo.put("data", message);
sendMessage(jo.toString());
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
}

+ 31
- 0
app/src/main/java/com/aispeech/nativedemo/rtasr/DraftWithOrigin.java Näytä tiedosto

@@ -0,0 +1,31 @@
package com.aispeech.nativedemo.rtasr;

import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ClientHandshakeBuilder;

import com.sun.istack.internal.NotNull;

@SuppressWarnings("deprecation")
public class DraftWithOrigin extends Draft_6455 {

private String originUrl;

public DraftWithOrigin(String originUrl) {
this.originUrl = originUrl;
}

@Override
public Draft copyInstance() {
System.out.println(originUrl);
return new DraftWithOrigin(originUrl);
}

@NotNull
@Override
public ClientHandshakeBuilder postProcessHandshakeRequestAsClient(@NotNull ClientHandshakeBuilder request) {
super.postProcessHandshakeRequestAsClient(request);
request.put("Origin", originUrl);
return request;
}
}

+ 66
- 0
app/src/main/java/com/aispeech/nativedemo/rtasr/EncryptUtil.java Näytä tiedosto

@@ -0,0 +1,66 @@
package com.aispeech.nativedemo.rtasr;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

public class EncryptUtil {

/**
* 加密数字签名(基于HMACSHA1算法)
*
* @param encryptText
* @param encryptKey
* @return
* @throws SignatureException
*/
public static String HmacSHA1Encrypt(String encryptText, String encryptKey) throws SignatureException {
byte[] rawHmac = null;
try {
byte[] data = encryptKey.getBytes("UTF-8");
SecretKeySpec secretKey = new SecretKeySpec(data, "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(secretKey);
byte[] text = encryptText.getBytes("UTF-8");
rawHmac = mac.doFinal(text);
} catch (InvalidKeyException e) {
throw new SignatureException("InvalidKeyException:" + e.getMessage());
} catch (NoSuchAlgorithmException e) {
throw new SignatureException("NoSuchAlgorithmException:" + e.getMessage());
} catch (UnsupportedEncodingException e) {
throw new SignatureException("UnsupportedEncodingException:" + e.getMessage());
}
String oauth = new String(Base64.encodeBase64(rawHmac));
return oauth;
}

public final static String MD5(String pstr) {
char md5String[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
try {
byte[] btInput = pstr.getBytes();
MessageDigest mdInst = MessageDigest.getInstance("MD5");
mdInst.update(btInput);
byte[] md = mdInst.digest();
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) { // i = 0
byte byte0 = md[i]; // 95
str[k++] = md5String[byte0 >>> 4 & 0xf]; // 5
str[k++] = md5String[byte0 & 0xf]; // F
}

return new String(str);
} catch (Exception e) {
return null;
}
}
}

+ 228
- 0
app/src/main/java/com/aispeech/nativedemo/rtasr/RTASRManager.java Näytä tiedosto

@@ -0,0 +1,228 @@
package com.aispeech.nativedemo.rtasr;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.enums.ReadyState;
import org.java_websocket.handshake.ServerHandshake;

import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;

public class RTASRManager {
private static final String TAG = "RTASRManager";
private static RTASRManager mInstance;

private static final String APPID = "";

// appid对应的secret_key
private static final String SECRET_KEY = "";

// 请求地址
private static final String HOST = "rtasr.xfyun.cn/v1/ws";

private static final String BASE_URL = "ws://" + HOST;

private static final String ORIGIN = "http://" + HOST;

// 音频文件路径
private static final String AUDIO_PATH = "./resource/test_1.pcm";

// 每次发送的数据大小 1280 字节
private static final int CHUNCKED_SIZE = 1280;

private static final SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss.SSS");

private RTASRManager() {

}

public static RTASRManager getInstance() {
if (mInstance == null) {
synchronized (RTASRManager.class) {
if (mInstance == null) {
mInstance = new RTASRManager();
}
}
}
return mInstance;
}

public static void sendAsrDataByte(Byte[] data) throws Exception {
while (true) {
URI url = new URI(BASE_URL + getHandShakeParams(APPID, SECRET_KEY));
DraftWithOrigin draft = new DraftWithOrigin(ORIGIN);
CountDownLatch handshakeSuccess = new CountDownLatch(1);
CountDownLatch connectClose = new CountDownLatch(1);
RTASRTest.MyWebSocketClient client = new RTASRTest.MyWebSocketClient(url, draft, handshakeSuccess, connectClose);

client.connect();

while (!client.getReadyState().equals(ReadyState.OPEN)) {
System.out.println(getCurrentTimeStr() + "\t连接中");
Thread.sleep(1000);
}

// 等待握手成功
handshakeSuccess.await();
System.out.println(sdf.format(new Date()) + " 开始发送音频数据");
// 发送音频
byte[] bytes = new byte[CHUNCKED_SIZE];
try (RandomAccessFile raf = new RandomAccessFile(AUDIO_PATH, "r")) {
int len = -1;
long lastTs = 0;
while ((len = raf.read(bytes)) != -1) {
if (len < CHUNCKED_SIZE) {
send(client, bytes = Arrays.copyOfRange(bytes, 0, len));
break;
}

long curTs = System.currentTimeMillis();
if (lastTs == 0) {
lastTs = System.currentTimeMillis();
} else {
long s = curTs - lastTs;
if (s < 40) {
System.out.println("error time interval: " + s + " ms");
}
}
send(client, bytes);
// 每隔40毫秒发送一次数据
Thread.sleep(40);
}

// 发送结束标识
send(client,"{\"end\": true}".getBytes());
System.out.println(getCurrentTimeStr() + "\t发送结束标识完成");
} catch (Exception e) {
e.printStackTrace();
}

// 等待连接关闭
connectClose.await();
break;
}
}

// 生成握手参数
public static String getHandShakeParams(String appId, String secretKey) {
String ts = System.currentTimeMillis()/1000 + "";
String signa = "";
try {
signa = EncryptUtil.HmacSHA1Encrypt(EncryptUtil.MD5(appId + ts), secretKey);
return "?appid=" + appId + "&ts=" + ts + "&signa=" + URLEncoder.encode(signa, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}

return "";
}

public static void send(WebSocketClient client, byte[] bytes) {
if (client.isClosed()) {
throw new RuntimeException("client connect closed!");
}

client.send(bytes);
}

public static String getCurrentTimeStr() {
return sdf.format(new Date());
}

public static class MyWebSocketClient extends WebSocketClient {

private CountDownLatch handshakeSuccess;
private CountDownLatch connectClose;

public MyWebSocketClient(URI serverUri, Draft protocolDraft, CountDownLatch handshakeSuccess, CountDownLatch connectClose) {
super(serverUri, protocolDraft);
this.handshakeSuccess = handshakeSuccess;
this.connectClose = connectClose;
}

@Override
public void onOpen(ServerHandshake handshake) {
System.out.println(getCurrentTimeStr() + "\t连接建立成功!");
}

@Override
public void onMessage(String msg) {
JSONObject msgObj = JSON.parseObject(msg);
String action = msgObj.getString("action");
if (Objects.equals("started", action)) {
// 握手成功
System.out.println(getCurrentTimeStr() + "\t握手成功!sid: " + msgObj.getString("sid"));
handshakeSuccess.countDown();
} else if (Objects.equals("result", action)) {
// 转写结果
System.out.println(getCurrentTimeStr() + "\tresult: " + getContent(msgObj.getString("data")));
} else if (Objects.equals("error", action)) {
// 连接发生错误
System.out.println("Error: " + msg);
System.exit(0);
}
}

@Override
public void onError(Exception e) {
System.out.println(getCurrentTimeStr() + "\t连接发生错误:" + e.getMessage() + ", " + new Date());
e.printStackTrace();
System.exit(0);
}

@Override
public void onClose(int arg0, String arg1, boolean arg2) {
System.out.println(getCurrentTimeStr() + "\t链接关闭");
connectClose.countDown();
}

@Override
public void onMessage(ByteBuffer bytes) {
try {
System.out.println(getCurrentTimeStr() + "\t服务端返回:" + new String(bytes.array(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}

// 把转写结果解析为句子
public static String getContent(String message) {
StringBuffer resultBuilder = new StringBuffer();
try {
JSONObject messageObj = JSON.parseObject(message);
JSONObject cn = messageObj.getJSONObject("cn");
JSONObject st = cn.getJSONObject("st");
JSONArray rtArr = st.getJSONArray("rt");
for (int i = 0; i < rtArr.size(); i++) {
JSONObject rtArrObj = rtArr.getJSONObject(i);
JSONArray wsArr = rtArrObj.getJSONArray("ws");
for (int j = 0; j < wsArr.size(); j++) {
JSONObject wsArrObj = wsArr.getJSONObject(j);
JSONArray cwArr = wsArrObj.getJSONArray("cw");
for (int k = 0; k < cwArr.size(); k++) {
JSONObject cwArrObj = cwArr.getJSONObject(k);
String wStr = cwArrObj.getString("w");
resultBuilder.append(wStr);
}
}
}
} catch (Exception e) {
return message;
}

return resultBuilder.toString();
}
}

+ 219
- 0
app/src/main/java/com/aispeech/nativedemo/rtasr/RTASRTest.java Näytä tiedosto

@@ -0,0 +1,219 @@
package com.aispeech.nativedemo.rtasr;

import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.enums.ReadyState;
import org.java_websocket.handshake.ServerHandshake;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
* 实时转写调用demo
* 此demo只是一个简单的调用示例,不适合用到实际生产环境中
*
* @author white
*
*/
public class RTASRTest {

// appid
private static final String APPID = "";

// appid对应的secret_key
private static final String SECRET_KEY = "";

// 请求地址
private static final String HOST = "rtasr.xfyun.cn/v1/ws";

private static final String BASE_URL = "ws://" + HOST;

private static final String ORIGIN = "http://" + HOST;

// 音频文件路径
private static final String AUDIO_PATH = "./resource/test_1.pcm";

// 每次发送的数据大小 1280 字节
private static final int CHUNCKED_SIZE = 1280;

private static final SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss.SSS");

public static void sendAsrDataByte(Byte[] data) throws Exception {
while (true) {
URI url = new URI(BASE_URL + getHandShakeParams(APPID, SECRET_KEY));
DraftWithOrigin draft = new DraftWithOrigin(ORIGIN);
CountDownLatch handshakeSuccess = new CountDownLatch(1);
CountDownLatch connectClose = new CountDownLatch(1);
MyWebSocketClient client = new MyWebSocketClient(url, draft, handshakeSuccess, connectClose);
client.connect();
while (!client.getReadyState().equals(ReadyState.OPEN)) {
System.out.println(getCurrentTimeStr() + "\t连接中");
Thread.sleep(1000);
}
// 等待握手成功
handshakeSuccess.await();
System.out.println(sdf.format(new Date()) + " 开始发送音频数据");
// 发送音频
byte[] bytes = new byte[CHUNCKED_SIZE];
try (RandomAccessFile raf = new RandomAccessFile(AUDIO_PATH, "r")) {
int len = -1;
long lastTs = 0;
while ((len = raf.read(bytes)) != -1) {
if (len < CHUNCKED_SIZE) {
send(client, bytes = Arrays.copyOfRange(bytes, 0, len));
break;
}

long curTs = System.currentTimeMillis();
if (lastTs == 0) {
lastTs = System.currentTimeMillis();
} else {
long s = curTs - lastTs;
if (s < 40) {
System.out.println("error time interval: " + s + " ms");
}
}
send(client, bytes);
// 每隔40毫秒发送一次数据
Thread.sleep(40);
}
// 发送结束标识
send(client,"{\"end\": true}".getBytes());
System.out.println(getCurrentTimeStr() + "\t发送结束标识完成");
} catch (Exception e) {
e.printStackTrace();
}
// 等待连接关闭
connectClose.await();
break;
}
}

// 生成握手参数
public static String getHandShakeParams(String appId, String secretKey) {
String ts = System.currentTimeMillis()/1000 + "";
String signa = "";
try {
signa = EncryptUtil.HmacSHA1Encrypt(EncryptUtil.MD5(appId + ts), secretKey);
return "?appid=" + appId + "&ts=" + ts + "&signa=" + URLEncoder.encode(signa, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}

return "";
}

public static void send(WebSocketClient client, byte[] bytes) {
if (client.isClosed()) {
throw new RuntimeException("client connect closed!");
}

client.send(bytes);
}

public static String getCurrentTimeStr() {
return sdf.format(new Date());
}

public static class MyWebSocketClient extends WebSocketClient {

private CountDownLatch handshakeSuccess;
private CountDownLatch connectClose;

public MyWebSocketClient(URI serverUri, Draft protocolDraft, CountDownLatch handshakeSuccess, CountDownLatch connectClose) {
super(serverUri, protocolDraft);
this.handshakeSuccess = handshakeSuccess;
this.connectClose = connectClose;
}

@Override
public void onOpen(ServerHandshake handshake) {
System.out.println(getCurrentTimeStr() + "\t连接建立成功!");
}

@Override
public void onMessage(String msg) {
JSONObject msgObj = JSON.parseObject(msg);
String action = msgObj.getString("action");
if (Objects.equals("started", action)) {
// 握手成功
System.out.println(getCurrentTimeStr() + "\t握手成功!sid: " + msgObj.getString("sid"));
handshakeSuccess.countDown();
} else if (Objects.equals("result", action)) {
// 转写结果
System.out.println(getCurrentTimeStr() + "\tresult: " + getContent(msgObj.getString("data")));
} else if (Objects.equals("error", action)) {
// 连接发生错误
System.out.println("Error: " + msg);
System.exit(0);
}
}

@Override
public void onError(Exception e) {
System.out.println(getCurrentTimeStr() + "\t连接发生错误:" + e.getMessage() + ", " + new Date());
e.printStackTrace();
System.exit(0);
}

@Override
public void onClose(int arg0, String arg1, boolean arg2) {
System.out.println(getCurrentTimeStr() + "\t链接关闭");
connectClose.countDown();
}

@Override
public void onMessage(ByteBuffer bytes) {
try {
System.out.println(getCurrentTimeStr() + "\t服务端返回:" + new String(bytes.array(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}

// 把转写结果解析为句子
public static String getContent(String message) {
StringBuffer resultBuilder = new StringBuffer();
try {
JSONObject messageObj = JSON.parseObject(message);
JSONObject cn = messageObj.getJSONObject("cn");
JSONObject st = cn.getJSONObject("st");
JSONArray rtArr = st.getJSONArray("rt");
for (int i = 0; i < rtArr.size(); i++) {
JSONObject rtArrObj = rtArr.getJSONObject(i);
JSONArray wsArr = rtArrObj.getJSONArray("ws");
for (int j = 0; j < wsArr.size(); j++) {
JSONObject wsArrObj = wsArr.getJSONObject(j);
JSONArray cwArr = wsArrObj.getJSONArray("cw");
for (int k = 0; k < cwArr.size(); k++) {
JSONObject cwArrObj = cwArr.getJSONObject(k);
String wStr = cwArrObj.getString("w");
resultBuilder.append(wStr);
}
}
}
} catch (Exception e) {
return message;
}

return resultBuilder.toString();
}
}

+ 5
- 0
app/src/main/java/com/aispeech/nativedemo/upload/UploadManager.java Näytä tiedosto

@@ -153,6 +153,11 @@ public class UploadManager {
File[] logs = file.listFiles();
if(logs != null && logs.length > 0){
for(File log : logs){
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String time = dateFormat.format(new Date(System.currentTimeMillis()));
if(log.getName().contains(time)){
return;
}
HashMap<String, String> map = new HashMap<>();
map.put("devId", Build.SERIAL);
map.put("logType", uploadType + "");


+ 0
- 1
app/src/main/java/com/aispeech/nativedemo/utils/Utils.java Näytä tiedosto

@@ -44,7 +44,6 @@ import java.util.List;
public class Utils {

public static LinkedHashMap<String, float[]> userFaces = new LinkedHashMap<>();
public static LinkedHashMap<String, float[]> userFaces2 = new LinkedHashMap<>();
public static LinkedHashMap<String, float[]> userNewFaces = new LinkedHashMap<>();
public static LinkedHashMap<String, Integer> userLogs = new LinkedHashMap<>();
public static LinkedHashMap<String, Long> logsTime = new LinkedHashMap<>();


+ 7
- 6
app/src/main/java/com/aispeech/nativedemo/widget/AlertWindowView.java Näytä tiedosto

@@ -40,6 +40,7 @@ import com.aispeech.nativedemo.db.ModelDbHelper;
import com.aispeech.nativedemo.db.SkillDbHelper;
import com.aispeech.nativedemo.dds.DDSManager;
import com.aispeech.nativedemo.entity.Emp;
import com.aispeech.nativedemo.face.FaceChatMode;
import com.aispeech.nativedemo.face.FaceManager;
import com.aispeech.nativedemo.mqtt.MqttManager;
import com.aispeech.nativedemo.network.ws.MessageUtils;
@@ -324,7 +325,7 @@ public class AlertWindowView extends ConstraintLayout implements FaceManager.Upd

private void initManager(Context context) {
mWSManager = WebSocketManager.getInstance(mActivity.getApplicationContext());
mFaceManager = FaceManager.getInstance(mActivity.getApplicationContext());
mFaceManager = FaceManager.getInstance();
mFaceManager.setCallback(this);
mCameraController = CameraController.getInstance(mActivity.getApplicationContext());
mCameraController.initTexture(mTextureView);
@@ -477,17 +478,17 @@ public class AlertWindowView extends ConstraintLayout implements FaceManager.Upd
try {
Log.e(TAG, "-----------------detect face----------------");
textureBitmap = mTextureView.getBitmap();
List<MultiAtt> results = mFaceManager.detectMultiAtt(textureBitmap);
List<MultiAtt> results = FaceChatMode.detectMultiAtt(textureBitmap);
if (results != null && results.size() > 0) {
mFaceManager.filterPersonForFeatExtract(results);
FaceChatMode.filterPersonForFeatExtract(results, textureBitmap);

//删除过期人员
mFaceManager.deleteExpirePerson();
FaceChatMode.deleteExpirePerson();

boolean isContinue = mFaceManager.featExtract(results, textureBitmap);
boolean isContinue = FaceChatMode.featExtract(results, textureBitmap);
if(isContinue){
DDSManager.getInstance().wakeUpDDSDialog();
mFaceManager.confirmCurrentPerson(textureBitmap);
FaceChatMode.confirmCurrentPerson(textureBitmap);
}
// if(!mFaceManager.hasPerson()){
// DDSManager.getInstance().stopDDSDialog();


BIN
test/libs/lib-dds-2.9.0.1-release.aar → test/libs/lib-dds-2.9.2.1-release.aar Näytä tiedosto


BIN
test/src/main/assets/sspe-aec-mann-70mm-6chan-2mic-2ref-v2.0.0.127-0926-nocross-dcrn-decoderadd_20230714_aecGain4_v1.bin Näytä tiedosto


Ladataan…
Peruuta
Tallenna