diff --git a/libs/arcsoft-sdk-face-4.1.1.0.jar b/libs/arcsoft-sdk-face-4.1.1.0.jar
new file mode 100644
index 0000000..c49fe45
Binary files /dev/null and b/libs/arcsoft-sdk-face-4.1.1.0.jar differ
diff --git a/shapelight-admin/pom.xml b/shapelight-admin/pom.xml
index 8849cc4..a83d240 100644
--- a/shapelight-admin/pom.xml
+++ b/shapelight-admin/pom.xml
@@ -18,6 +18,9 @@
2.7.0
+ 1.4.4
+
+ linux-x86_64
@@ -221,6 +224,67 @@
2.0.0
+
+
+
+ com.arcsoft.face
+ arcsoft-sdk-face
+ 4.1.1.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/shapelight-admin/src/main/java/net/shapelight/AdminApplication.java b/shapelight-admin/src/main/java/net/shapelight/AdminApplication.java
index fb66eb1..4696ffb 100644
--- a/shapelight-admin/src/main/java/net/shapelight/AdminApplication.java
+++ b/shapelight-admin/src/main/java/net/shapelight/AdminApplication.java
@@ -5,6 +5,10 @@ package net.shapelight;
//import net.shapelight.modules.dev.mqtt.MqttClientUtil;
import lombok.extern.slf4j.Slf4j;
import net.shapelight.commons.engine.sdk.PalmSDK;
+//import org.bytedeco.javacpp.Loader;
+//import org.bytedeco.opencv.global.opencv_imgproc;
+//import org.bytedeco.opencv.opencv_core.CvPoint;
+//import org.bytedeco.opencv.opencv_imgproc.CvFont;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -26,23 +30,27 @@ public class AdminApplication {
public static void main(String[] args) {
SpringApplication.run(AdminApplication.class, args);
+// Loader.load(opencv_imgproc.class);
+// Loader.load(CvPoint.class);
+// Loader.load(CvFont.class);
+
//初始化掌静脉sdk
- int initCode = PalmSDK.init();
- log.debug("掌静脉sdk初始化。。。。。。。。。。:"+initCode);
-// //mqtt服务启动
-// MqttClientUtil.createClient();
-//
- Runtime.getRuntime().addShutdownHook(new Thread() {
- @Override
- public void run() {
- try {
- int code = PalmSDK.release();
- log.debug("掌静脉sdk释放。。。。。。。。。。:"+code);
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- });
+// int initCode = PalmSDK.init();
+// log.debug("掌静脉sdk初始化。。。。。。。。。。:"+initCode);
+//// //mqtt服务启动
+//// MqttClientUtil.createClient();
+////
+// Runtime.getRuntime().addShutdownHook(new Thread() {
+// @Override
+// public void run() {
+// try {
+// int code = PalmSDK.release();
+// log.debug("掌静脉sdk释放。。。。。。。。。。:"+code);
+// } catch (Throwable e) {
+// e.printStackTrace();
+// }
+// }
+// });
}
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/common/aspect/SysLogAspect.java b/shapelight-admin/src/main/java/net/shapelight/common/aspect/SysLogAspect.java
index 61416b3..126a9aa 100644
--- a/shapelight-admin/src/main/java/net/shapelight/common/aspect/SysLogAspect.java
+++ b/shapelight-admin/src/main/java/net/shapelight/common/aspect/SysLogAspect.java
@@ -76,13 +76,13 @@ public class SysLogAspect {
sysLog.setMethod(className + "." + methodName + "()");
//请求的参数
- Object[] args = joinPoint.getArgs();
- try{
- String params = new Gson().toJson(args[0]);
- sysLog.setParams(params);
- }catch (Exception e){
-
- }
+// Object[] args = joinPoint.getArgs();
+// try{
+// String params = new Gson().toJson(args[0]);
+// sysLog.setParams(params);
+// }catch (Exception e){
+//
+// }
//获取request
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
diff --git a/shapelight-admin/src/main/java/net/shapelight/common/config/GlobalValue.java b/shapelight-admin/src/main/java/net/shapelight/common/config/GlobalValue.java
index 39532ff..6a600bc 100644
--- a/shapelight-admin/src/main/java/net/shapelight/common/config/GlobalValue.java
+++ b/shapelight-admin/src/main/java/net/shapelight/common/config/GlobalValue.java
@@ -59,14 +59,6 @@ public class GlobalValue {
@Value("${global.file_path.opt_dir}")
private String optDir;
- @Value("${spring.mqtt.username}")
- private String mqttUsername;
- @Value("${spring.mqtt.password}")
- private String mqttPassword;
- @Value("${spring.mqtt.url}")
- private String mqttUrl;
- @Value("${spring.mqtt.api}")
- private String mqttApi;
@Value("${global.minio.endpoint}")
private String minioEndpoint;
@@ -98,5 +90,12 @@ public class GlobalValue {
@Value("${global.app.secret}")
private String appSecret;
+ @Value("${config.arcface-sdk.rec-face-thd}")
+ private String recFaceThd;
+ @Value("${config.arcface-sdk.rec-id-thd}")
+ private String recIdThd;
+
+ @Value("${global.tenantId}")
+ private String tenantId;
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/common/utils/CompressZipUtils.java b/shapelight-admin/src/main/java/net/shapelight/common/utils/CompressZipUtils.java
index 0d3764d..b493393 100644
--- a/shapelight-admin/src/main/java/net/shapelight/common/utils/CompressZipUtils.java
+++ b/shapelight-admin/src/main/java/net/shapelight/common/utils/CompressZipUtils.java
@@ -148,7 +148,7 @@ public class CompressZipUtils {
{
String fileName = file.getAbsolutePath();
//判断jpg图片
- if (fileName.endsWith("jpg") || fileName.endsWith("png")) {
+ if (fileName.endsWith("jpg") || fileName.endsWith("jpeg") || fileName.endsWith("png")) {
imageFiles.add(fileName);
}else if(fileName.endsWith("xls") || fileName.endsWith("xlsx")){
excelFiles.add(fileName);
diff --git a/shapelight-admin/src/main/java/net/shapelight/common/utils/TimeUtils.java b/shapelight-admin/src/main/java/net/shapelight/common/utils/TimeUtils.java
new file mode 100644
index 0000000..7cf5d99
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/common/utils/TimeUtils.java
@@ -0,0 +1,19 @@
+package net.shapelight.common.utils;
+
+import io.swagger.models.auth.In;
+
+import java.time.LocalTime;
+
+public class TimeUtils {
+ public static boolean isIn(String p){
+ //00:00-23:00
+ String[] pArray = p.split("-");
+ String[] startStr = pArray[0].split(":");
+ String[] endStr = pArray[1].split(":");
+ LocalTime start = LocalTime.of(Integer.parseInt(startStr[0]), Integer.parseInt(startStr[1])); // 时间段开始时间
+ LocalTime end = LocalTime.of(Integer.parseInt(endStr[0]), Integer.parseInt(endStr[1])); // 时间段结束时间
+ LocalTime time = LocalTime.now(); // 当前时间
+ boolean isWithinRange = time.isAfter(start) && time.isBefore(end); // 判断当前时间是否在时间段内
+ return isWithinRange;
+ }
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/excel/listener/PersonExcelListener.java b/shapelight-admin/src/main/java/net/shapelight/modules/excel/listener/PersonExcelListener.java
index 4bd4d80..cc6d1af 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/excel/listener/PersonExcelListener.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/excel/listener/PersonExcelListener.java
@@ -1,8 +1,13 @@
package net.shapelight.modules.excel.listener;
+import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSONObject;
+import com.arcsoft.face.FaceInfo;
+import com.arcsoft.face.enums.ExtractType;
+import com.arcsoft.face.toolkit.ImageFactory;
+import com.arcsoft.face.toolkit.ImageInfo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.minio.PutObjectOptions;
import lombok.Getter;
@@ -10,18 +15,18 @@ import net.shapelight.common.utils.R;
import net.shapelight.common.utils.UUIDUtil;
import net.shapelight.commons.engine.sdk.PicSDK;
import net.shapelight.modules.excel.model.PersonModel;
+import net.shapelight.modules.face.dto.FaceRecognitionResDTO;
+import net.shapelight.modules.face.service.FaceEngineService;
import net.shapelight.modules.ten.entity.*;
import net.shapelight.modules.ten.service.TenCellDeptService;
import net.shapelight.modules.ten.service.TenPersonService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
+import java.io.*;
import java.util.*;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
public class PersonExcelListener extends AnalysisEventListener {
private static final Logger LOGGER = LoggerFactory.getLogger(PersonExcelListener.class);
@@ -32,10 +37,13 @@ public class PersonExcelListener extends AnalysisEventListener {
// private List imagelist;
private TenPersonService tenPersonService;
private TenCellDeptService tenCellDeptService;
+ private FaceEngineService faceEngineService;
private String tenantId;
private Map imageMap = new HashMap<>();
List personList = new ArrayList<>();
+ List idCardList = new ArrayList<>();
+ List deptList = new ArrayList<>();
// @Getter
// private List tmp;
@@ -51,11 +59,13 @@ public class PersonExcelListener extends AnalysisEventListener {
* 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
*/
public PersonExcelListener(List imagelist,TenPersonService tenPersonService,
- TenCellDeptService tenCellDeptService,String tenantId){
+ TenCellDeptService tenCellDeptService,FaceEngineService faceEngineService,List idCardList,String tenantId){
// this.tenStudentDao = tenStudentDao;
this.tenPersonService = tenPersonService;
this.tenCellDeptService = tenCellDeptService;
+ this.faceEngineService = faceEngineService;
+ this.idCardList = idCardList;
this.tenantId = tenantId;
//this.imagelist = imagelist;
String osName = System.getProperty("os.name");//获取指定键(即os.name)的系统属性,如:Windows 7。
@@ -84,15 +94,17 @@ public class PersonExcelListener extends AnalysisEventListener {
personModel.setTenantId(tenantId);
if(personModel.getName()==null
- || personModel.getGender() == null
+// || personModel.getGender() == null
|| personModel.getCellName() == null
- || personModel.getDeptNameAll() == null){
+ || personModel.getDeptNameAll() == null
+ || personModel.getLabel() == null
+ || personModel.getIdCard() == null){
// || personModel.getBuildName() == null
// || personModel.getBuildUnit() == null
// || personModel.getRoomName() == null){
// personModel.setMessage("姓名,性别,小区,楼栋,单元,房间不能为空");
- personModel.setMessage("姓名,性别,小区,组织不能为空");
+ personModel.setMessage("姓名,身份证号,小区,组织,标签不能为空");
list.add(personModel);
return;
}
@@ -102,6 +114,22 @@ public class PersonExcelListener extends AnalysisEventListener {
* 张三 男 13200000001 352456199302121456 太白阁 一栋/二单元/3层/1002室
* 李四 男 103215199601125620 太白阁 一栋/二单元/3层/1002室
*/
+ /**
+ * "姓名
+ * (必填)" "性别
+ * (非必填)" "手机号
+ * (非必填)" "身份证号
+ * (必填)" "小区名称
+ * (必填)" "组织/部门
+ * (必填)" "类别/标签
+ * (必填)" "一卡通号
+ * (非必填)" "户主姓名
+ * (非必填)" "与户主关系
+ * (非必填)" "备注
+ * (非必填)"
+ * 张三 13200000001 610113199805021245 本部校区 音乐学院 家属 1586877 李市民 父子 一个家属
+ * 李四 男 610113200102011253 本部校区 音乐学院 2020级学生 1689874
+ */
TenCellEntity cellEntity = tenPersonService.findCellByCellName(personModel.getCellName(),tenantId);
@@ -109,42 +137,55 @@ public class PersonExcelListener extends AnalysisEventListener {
personModel.setMessage("小区不存在");
list.add(personModel);
return;
+ }else{
+ if(this.deptList.size() == 0){
+ this.deptList = tenCellDeptService.list(new QueryWrapper()
+ .eq("cell_id",cellEntity.getCellId()));
+ }
+ personModel.setCellId(cellEntity.getCellId());
+ }
+
+ TenLabelEntity labelEntity = tenPersonService.findLabelByName(personModel.getLabel(),tenantId);
+ if(labelEntity==null){
+ personModel.setMessage("标签不存在");
+ list.add(personModel);
+ return;
+ }else{
+ personModel.setLabelId(labelEntity.getLabelId().intValue());
}
String[] deptAll = personModel.getDeptNameAll().split("/");
Long parentId = cellEntity.getCellId();
+ Long deptIdLast = null;
if(deptAll.length>0 && deptAll.length<6){
+// boolean isOk = true;
for(int i = 0;i deviceEntity = tenCellDeptService.list(new QueryWrapper()
- .eq("parent_id",parentId)
- .eq("name",deptName));
+ Long parentIdTemp = parentId;
+// List deviceEntity = tenCellDeptService.list(new QueryWrapper()
+// .eq("parent_id",parentId)
+// .eq("name",deptName));
+
+ List deviceEntity = this.deptList.stream()
+ .filter(dept -> dept.getParentId().equals(parentIdTemp))
+ .filter(dept -> dept.getName().equals(deptName))
+ .collect(Collectors.toList());
+
if(deviceEntity.size()==0){
//不存在,添加
- //父部门:
- if(i == 0){
- parentId = cellEntity.getCellId();
- }else{
- TenCellDeptEntity parent = tenCellDeptService.getOne(new QueryWrapper()
- .eq("cell_id",cellEntity.getCellId())
- .eq("parent_id",parentId)
- .eq("name",deptName));
- }
- TenCellDeptEntity tenCellDept = new TenCellDeptEntity();
- tenCellDept.setParentId(parentId);
- tenCellDept.setName(deptName);
- tenCellDept.setCellId(cellEntity.getCellId());
- tenCellDept.setTenantId(cellEntity.getTenantId());
- tenCellDeptService.save(tenCellDept);
- parentId = tenCellDept.getDeptId();
- personModel.setDeptId(tenCellDept.getDeptId());
+ personModel.setMessage("组织不存在");
+ list.add(personModel);
+ return;
}else{
//存在
TenCellDeptEntity deptEntity = deviceEntity.get(0);
parentId = deptEntity.getDeptId();
- personModel.setDeptId(deptEntity.getDeptId());
+// personModel.setDeptId(deptEntity.getDeptId());
+ deptIdLast = deptEntity.getDeptId();
}
}
+
+ personModel.setDeptId(deptIdLast);
}else{
personModel.setMessage("组织结构最多5层");
list.add(personModel);
@@ -186,33 +227,45 @@ public class PersonExcelListener extends AnalysisEventListener {
// }
//
//
-// TenPersonEntity tenPersonEntityIdCord = tenPersonService.findByIdCard(personModel.getIdCard(),
-// tenRoomEntity.getRoomId(),cellEntity.getCellId());
-// if(tenPersonEntityIdCord!=null){
-// personModel.setMessage("身份证在此房间已存在");
+// int idCardCount = tenPersonService.findByIdCardCount(personModel.getIdCard(),tenantId);
+// if(idCardCount>0){
+// personModel.setMessage("身份证已存在");
// list.add(personModel);
// return;
// }
+ boolean idCardIsUse = idCardList.contains(personModel.getIdCard());
+ if(idCardIsUse){
+ personModel.setMessage("身份证已存在");
+ list.add(personModel);
+ return;
+ }
String gender = personModel.getGender();
if(gender==null){
- personModel.setMessage("性别为空");
- list.add(personModel);
- return;
- }
- if (!gender.equals("男") && !gender.equals("女")) {
- personModel.setMessage("性别错误");
- list.add(personModel);
- return;
+// personModel.setMessage("性别为空");
+// list.add(personModel);
+// return;
+ //性别0女1男
+ if (personModel.getIdCard() != null && (personModel.getIdCard().length() == 18)) {
+ char genderCode = personModel.getIdCard().charAt(16);
+ String g = (genderCode % 2 == 0) ? "女" : "男";
+ personModel.setGender(g);
+ }
}
+// if (!gender.equals("男") && !gender.equals("女")) {
+// personModel.setMessage("性别错误");
+// list.add(personModel);
+// return;
+// }
String image = imageMap.get(personModel.getIdCard());
if(image==null){
image = imageMap.get(personModel.getMobile());
if(image==null){
- personModel.setMessage("没有照片");
- list.add(personModel);
- return;
+// personModel.setMessage("没有照片");
+// list.add(personModel);
+// return;
+ personModel.setOrgImage(null);
}else{
personModel.setOrgImage(image);
}
@@ -221,17 +274,95 @@ public class PersonExcelListener extends AnalysisEventListener {
}
+ //1.
+ if(personModel.getOrgImage()!=null){
+ try{
+ InputStream tempInputStream = new FileInputStream(personModel.getOrgImage());
+ //----------------算法检测----------------------------------------------
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = tempInputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, length);
+ }
+
+ byte[] bytes = outputStream.toByteArray();
+ outputStream.close();
+ tempInputStream.close();
+ //-------------------------------------------------------------------------
+ ImageInfo rgbData = ImageFactory.getRGBData(bytes);
+ List faceInfoList = faceEngineService.detectFaces(rgbData);
+ if (CollectionUtil.isNotEmpty(faceInfoList)) {
+ FaceInfo faceInfo = faceInfoList.get(0);
+ FaceRecognitionResDTO faceRecognitionResDTO = new FaceRecognitionResDTO();
+ faceRecognitionResDTO.setRect(faceInfo.getRect());
+ byte[] featureBytes = faceEngineService.extractFaceFeature(rgbData, faceInfo, ExtractType.REGISTER);
+ if (featureBytes != null) {
+ personModel.setFeature(Base64.getEncoder().encodeToString(featureBytes));
+ }else{
+ personModel.setMessage("图片不合格,未检测到人脸");
+ list.add(personModel);
+ return;
+ }
+ }else{
+ personModel.setMessage("图片不合格,未检测到人脸");
+ list.add(personModel);
+ return;
+ }
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ }else{
+
+ }
+
//检测图片人脸
//---------------------------------------------------------------------
- String tempPath = "";
- if (Pattern.matches("Linux.*", System.getProperty("os.name"))) {
- tempPath = image.substring(0,image.lastIndexOf("/")+1);
- } else if (Pattern.matches("Windows.*", System.getProperty("os.name"))) {
- tempPath = image.substring(0,image.lastIndexOf("\\")+1);
- }
- String tempFaceFileName = UUIDUtil.uuid() + ".jpg";
- String tempFaceFilePath = tempPath + tempFaceFileName;
+// String tempPath = "";
+// if (Pattern.matches("Linux.*", System.getProperty("os.name"))) {
+// tempPath = image.substring(0,image.lastIndexOf("/")+1);
+// } else if (Pattern.matches("Windows.*", System.getProperty("os.name"))) {
+// tempPath = image.substring(0,image.lastIndexOf("\\")+1);
+// }
+// String tempFaceFileName = UUIDUtil.uuid() + ".jpg";
+// String tempFaceFilePath = tempPath + tempFaceFileName;
+
+
+
+ //判断人脸照片是否合格
+ //1.保存到本地
+// InputStream tempInputStream = minioClient.getObject(minioConfig.getBucketName(), tempOrgImageFile);
+// //----------------算法检测----------------------------------------------
+// ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+// byte[] buffer = new byte[1024];
+// int length;
+// while ((length = tempInputStream.read(buffer)) != -1) {
+// outputStream.write(buffer, 0, length);
+// }
+//
+// byte[] bytes = outputStream.toByteArray();
+// outputStream.close();
+// tempInputStream.close();
+// //-------------------------------------------------------------------------
+// ImageInfo rgbData = ImageFactory.getRGBData(bytes);
+// List faceInfoList = faceEngineService.detectFaces(rgbData);
+// if (CollectionUtil.isNotEmpty(faceInfoList)) {
+// FaceInfo faceInfo = faceInfoList.get(0);
+// FaceRecognitionResDTO faceRecognitionResDTO = new FaceRecognitionResDTO();
+// faceRecognitionResDTO.setRect(faceInfo.getRect());
+// byte[] featureBytes = faceEngineService.extractFaceFeature(rgbData, faceInfo, ExtractType.REGISTER);
+// if (featureBytes != null) {
+// entity.setFeature(Base64.getEncoder().encodeToString(featureBytes));
+// }else{
+// log.error("图片不合格,未检测到人脸");
+// return 2;
+// }
+// }else{
+// log.error("图片不合格,未检测到人脸");
+// return 2;
+// }
+
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/excel/model/PersonModel.java b/shapelight-admin/src/main/java/net/shapelight/modules/excel/model/PersonModel.java
index 4521c6d..115c1c0 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/excel/model/PersonModel.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/excel/model/PersonModel.java
@@ -29,8 +29,27 @@ public class PersonModel extends BaseRowModel implements Serializable {
@ExcelProperty(value = "组织名称", index = 5)
private String deptNameAll;
+ @ExcelProperty(value = "标签", index = 6)
+ private String label;
+
+ @ExcelProperty(value = "一卡通号", index = 7)
+ private String ic;
+
+ @ExcelProperty(value = "户主姓名", index = 8)
+ private String householder;
+
+ @ExcelProperty(value = "户主关系", index = 9)
+ private String relation;
+
+ @ExcelProperty(value = "备注", index = 10)
+ private String remark;
+
private Long deptId;
+ private Integer labelId;
+
+ private Long cellId;
+
// @ExcelProperty(value = "父级名称", index = 5)
// private String parentDeptName;
@@ -62,6 +81,7 @@ public class PersonModel extends BaseRowModel implements Serializable {
private String tenantId;
+ private String feature;
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/FaceEngineAutoRun.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/FaceEngineAutoRun.java
new file mode 100644
index 0000000..cd67d31
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/FaceEngineAutoRun.java
@@ -0,0 +1,79 @@
+package net.shapelight.modules.face;
+
+import lombok.extern.slf4j.Slf4j;
+import net.shapelight.modules.face.entity.UserCompareInfo;
+import net.shapelight.modules.face.service.FaceEngineService;
+import net.shapelight.modules.face.util.Base64Util;
+import net.shapelight.modules.face.util.UserRamCache;
+import net.shapelight.modules.ten.entity.TenPersonEntity;
+import net.shapelight.modules.ten.service.TenPersonService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.core.annotation.Order;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.stereotype.Component;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+@Component
+@Order(1)
+@Slf4j
+public class FaceEngineAutoRun implements ApplicationRunner {
+ @Autowired
+ private FaceEngineService faceEngineService;
+ @Autowired
+ private TenPersonService tenPersonService;
+
+ @Override
+ public void run(ApplicationArguments args) throws Exception {
+ // 任务初始化
+ log.debug("服务启动。。。。。初始化人脸库");
+// Map fileMap = Maps.newHashMap();
+// fileMap.put("zhao1", "赵丽颖");
+// fileMap.put("yang1", "杨紫");
+// fileMap.put("baixue", "白雪");
+// fileMap.put("chenchuang", "陈创");
+// for (String f : fileMap.keySet()) {
+// ClassPathResource resource = new ClassPathResource("static/images/" + f + ".jpg");
+// InputStream inputStream = resource.getInputStream();
+// ImageInfo rgbData = ImageFactory.getRGBData(inputStream);
+// List faceInfoList = faceEngineService.detectFaces(rgbData);
+// if (CollectionUtil.isNotEmpty(faceInfoList)) {
+// byte[] feature = faceEngineService.extractFaceFeature(rgbData, faceInfoList.get(0), ExtractType.REGISTER);
+// UserRamCache.UserInfo userInfo = new UserCompareInfo();
+// userInfo.setFaceId(f);
+// userInfo.setName(fileMap.get(f));
+// userInfo.setFaceFeature(feature);
+// //这边注册到内存缓存中,也可以根据业务,注册到数据库中
+// UserRamCache.addUser(userInfo);
+// }
+// }
+
+ int count = tenPersonService.findCount();
+ int pageSize = 1000;
+ int page = count/pageSize;
+ if(count%1000!=0){
+ page = page+1;
+ }
+ int faceCount = 0;
+ for (int i = 0; i < page; i++) {
+ int start = i*1000;
+ List listPage = tenPersonService.listPage(start,1000);
+ for(TenPersonEntity personEntity: listPage){
+ if(personEntity.getFeature()!=null && personEntity.getFeature().length()>0){
+ UserRamCache.UserInfo userInfo = new UserCompareInfo();
+ userInfo.setFaceId(personEntity.getPersonId()+"");
+ userInfo.setName(personEntity.getName());
+ userInfo.setFaceFeature(Base64Util.base64ToBytes(personEntity.getFeature()));
+ //这边注册到内存缓存中
+ UserRamCache.addUser(userInfo);
+ faceCount++;
+ }
+ }
+ }
+ log.debug("初始化人脸库完成,共 "+faceCount+" 人");
+ }
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/config/ArcFaceAutoConfiguration.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/config/ArcFaceAutoConfiguration.java
new file mode 100644
index 0000000..605c24e
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/config/ArcFaceAutoConfiguration.java
@@ -0,0 +1,133 @@
+package net.shapelight.modules.face.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.ClassPathResource;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.LinkedList;
+import java.util.List;
+
+@Slf4j
+@Configuration
+public class ArcFaceAutoConfiguration implements InitializingBean, DisposableBean {
+
+
+ private static final String PLATFORM;
+
+ private static final String USER_HOME;
+
+ public static String CACHE_LIB_FOLDER;
+
+ @Value("${config.arcface-sdk.version}")
+ public String ARC_FACE_VERSION;
+
+ static {
+ String jvmName = System.getProperty("java.vm.name", "").toLowerCase();
+ String osName = System.getProperty("os.name", "").toLowerCase();
+ String osArch = System.getProperty("os.arch", "").toLowerCase();
+ String abiType = System.getProperty("sun.arch.abi", "").toLowerCase();
+ String libPath = System.getProperty("sun.boot.library.path", "").toLowerCase();
+ USER_HOME = System.getProperty("user.home");
+ if (jvmName.startsWith("dalvik") && osName.startsWith("linux")) {
+ osName = "android";
+ } else if (jvmName.startsWith("robovm") && osName.startsWith("darwin")) {
+ osName = "ios";
+ osArch = "arm";
+ } else if (osName.startsWith("mac os x") || osName.startsWith("darwin")) {
+ osName = "macosx";
+ } else {
+ int spaceIndex = osName.indexOf(' ');
+ if (spaceIndex > 0) {
+ osName = osName.substring(0, spaceIndex);
+ }
+ }
+ if (osArch.equals("i386") || osArch.equals("i486") || osArch.equals("i586") || osArch.equals("i686")) {
+ osArch = "x86";
+ } else if (osArch.equals("amd64") || osArch.equals("x86-64") || osArch.equals("x64")) {
+ osArch = "x86_64";
+ } else if (osArch.startsWith("aarch64") || osArch.startsWith("armv8") || osArch.startsWith("arm64")) {
+ osArch = "arm64";
+ } else if ((osArch.startsWith("arm")) && ((abiType.equals("gnueabihf")) || (libPath.contains("openjdk-armhf")))) {
+ osArch = "armhf";
+ } else if (osArch.startsWith("arm")) {
+ osArch = "arm";
+ }
+ PLATFORM = osName + "-" + osArch;
+
+ }
+
+
+ @Override
+ public void afterPropertiesSet() throws IOException {
+ CACHE_LIB_FOLDER = USER_HOME + "/.arcface/cache/" + ARC_FACE_VERSION + "/" + PLATFORM + "/";
+ loadLibrary();
+ }
+
+ public void loadLibrary() throws IOException {
+ String baseFolder = "";
+ String suffix = ".dll";
+ if ("windows-x86_64".equals(PLATFORM)) {
+ baseFolder = "WIN64";
+ } else if ("windows-x86".equals(PLATFORM)) {
+ baseFolder = "WIN32";
+ } else if ("linux-x86_64".equals(PLATFORM)) {
+ baseFolder = "LINUX64";
+ suffix = ".so";
+ }
+
+ if ("".equals(baseFolder)) {
+ throw new RuntimeException("ArcFace不支持该操作系统");
+ }
+
+
+ File file = new File(CACHE_LIB_FOLDER);
+ if (!file.exists()) {
+ file.mkdirs();
+ }
+
+ List libList = new LinkedList<>();
+ libList.add("libarcsoft_face");
+ libList.add("libarcsoft_face_engine");
+ libList.add("libarcsoft_face_engine_jni");
+
+ for (String lib : libList) {
+ ClassPathResource resource = new ClassPathResource("libs/" + ARC_FACE_VERSION + "/" + baseFolder + "/" + lib + suffix);
+ InputStream inputStream = resource.getInputStream();
+ int faceLength = inputStream.available();
+ File facePath = new File(CACHE_LIB_FOLDER + lib + suffix);
+ if (facePath.exists()) {
+ if (facePath.length() == faceLength) {
+ continue;
+ }
+ facePath.delete();
+ }
+ writeToLocal(CACHE_LIB_FOLDER + lib + suffix, inputStream);
+ }
+ }
+
+ private void writeToLocal(String destination, InputStream input)
+ throws IOException {
+ int index;
+ byte[] bytes = new byte[1024 * 100];
+ FileOutputStream fileOutputStream = new FileOutputStream(destination);
+ while ((index = input.read(bytes)) != -1) {
+ fileOutputStream.write(bytes, 0, index);
+ }
+ fileOutputStream.flush();
+ fileOutputStream.close();
+ input.close();
+ }
+
+
+ @Override
+ public void destroy() throws Exception {
+ }
+
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/CompareFacesReqDTO.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/CompareFacesReqDTO.java
new file mode 100644
index 0000000..c4971fb
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/CompareFacesReqDTO.java
@@ -0,0 +1,14 @@
+package net.shapelight.modules.face.dto;
+
+import lombok.Data;
+
+/**
+ * @author shentao
+ * @desc
+ * @date 2022/3/30
+ */
+@Data
+public class CompareFacesReqDTO {
+ private String image1;
+ private String image2;
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/FaceAddReqDTO.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/FaceAddReqDTO.java
new file mode 100644
index 0000000..b438dfb
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/FaceAddReqDTO.java
@@ -0,0 +1,12 @@
+package net.shapelight.modules.face.dto;
+
+import lombok.Data;
+
+@Data
+public class FaceAddReqDTO {
+
+ private String name;
+
+ private String image;
+
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/FaceDetectReqDTO.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/FaceDetectReqDTO.java
new file mode 100644
index 0000000..30bf032
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/FaceDetectReqDTO.java
@@ -0,0 +1,10 @@
+package net.shapelight.modules.face.dto;
+
+import lombok.Data;
+
+@Data
+public class FaceDetectReqDTO {
+
+ private String image;
+
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/FaceDetectResDTO.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/FaceDetectResDTO.java
new file mode 100644
index 0000000..45e2ca2
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/FaceDetectResDTO.java
@@ -0,0 +1,14 @@
+package net.shapelight.modules.face.dto;
+
+import com.arcsoft.face.Rect;
+import lombok.Data;
+
+@Data
+public class FaceDetectResDTO {
+ private Rect rect;
+ private int orient;
+ private int faceId = -1;
+ private int age = -1;
+ private int gender = -1;
+ private int liveness = -1;
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/FaceRecognitionReqDTO.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/FaceRecognitionReqDTO.java
new file mode 100644
index 0000000..5d4dd52
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/FaceRecognitionReqDTO.java
@@ -0,0 +1,10 @@
+package net.shapelight.modules.face.dto;
+
+import lombok.Data;
+
+@Data
+public class FaceRecognitionReqDTO {
+
+ private String image;
+
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/FaceRecognitionResDTO.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/FaceRecognitionResDTO.java
new file mode 100644
index 0000000..3d77ef9
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/FaceRecognitionResDTO.java
@@ -0,0 +1,15 @@
+package net.shapelight.modules.face.dto;
+
+
+import com.arcsoft.face.Rect;
+import lombok.Data;
+
+@Data
+public class FaceRecognitionResDTO {
+
+ private Rect rect;
+ private String personId;
+ private String name;
+ private float similar;
+
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/GetFaceListResDTO.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/GetFaceListResDTO.java
new file mode 100644
index 0000000..beecd7a
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/dto/GetFaceListResDTO.java
@@ -0,0 +1,14 @@
+package net.shapelight.modules.face.dto;
+
+import lombok.Data;
+
+@Data
+public class GetFaceListResDTO {
+
+ private String id;
+
+ private String name;
+
+ private String url;
+
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/entity/ProcessInfo.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/entity/ProcessInfo.java
new file mode 100644
index 0000000..01e0fe9
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/entity/ProcessInfo.java
@@ -0,0 +1,12 @@
+package net.shapelight.modules.face.entity;
+
+
+import lombok.Data;
+
+@Data
+public class ProcessInfo {
+ private int age;
+ private int gender;
+ private int liveness;
+
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/entity/UserCompareInfo.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/entity/UserCompareInfo.java
new file mode 100644
index 0000000..eeeffd5
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/entity/UserCompareInfo.java
@@ -0,0 +1,10 @@
+package net.shapelight.modules.face.entity;
+
+
+import lombok.Data;
+import net.shapelight.modules.face.util.UserRamCache;
+
+@Data
+public class UserCompareInfo extends UserRamCache.UserInfo {
+ private Float similar;
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/enums/ErrorCodeEnum.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/enums/ErrorCodeEnum.java
new file mode 100644
index 0000000..50795eb
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/enums/ErrorCodeEnum.java
@@ -0,0 +1,49 @@
+package net.shapelight.modules.face.enums;
+
+
+import lombok.Getter;
+import net.shapelight.modules.face.rpc.ErrorCode;
+
+@Getter
+public enum ErrorCodeEnum implements ErrorCode {
+
+ /**
+ * 成功
+ */
+ SUCCESS(0, "success", "成功"),
+ FAIL(1, "fail", "失败"),
+ PARAM_ERROR(2, "param error", "参数错误"),
+ SYSTEM_ERROR(999, "system error", "系统错误"),
+
+ ;
+ private Integer code;
+ private String desc;
+ private String descCN;
+
+ ErrorCodeEnum(Integer code, String desc) {
+ this.code = code;
+ this.desc = desc;
+ }
+
+ ErrorCodeEnum(Integer code, String desc, String descCN) {
+ this.code = code;
+ this.desc = desc;
+ this.descCN = descCN;
+ }
+
+ @Override
+ public Integer getCode() {
+ return code;
+ }
+
+ @Override
+ public String getDesc() {
+ return desc;
+ }
+
+ @Override
+ public String getDescCN() {
+ return descCN;
+ }
+
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/face/FaceRecognize.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/face/FaceRecognize.java
new file mode 100644
index 0000000..6e9f829
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/face/FaceRecognize.java
@@ -0,0 +1,292 @@
+package net.shapelight.modules.face.face;
+
+import com.arcsoft.face.*;
+import com.arcsoft.face.enums.DetectMode;
+import com.arcsoft.face.enums.ErrorInfo;
+import com.arcsoft.face.enums.ExtractType;
+import com.arcsoft.face.toolkit.ImageFactory;
+import com.arcsoft.face.toolkit.ImageInfo;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import net.shapelight.modules.face.config.ArcFaceAutoConfiguration;
+import net.shapelight.modules.face.factory.FaceEngineFactory;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.pool2.impl.GenericObjectPool;
+import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
+
+import java.io.File;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+@Slf4j
+public class FaceRecognize {
+
+ /**
+ * VIDEO模式人脸检测引擎,用于预览帧人脸追踪
+ */
+ private FaceEngine ftEngine;
+
+ /**
+ * 人脸注册引擎
+ */
+ private FaceEngine regEngine;
+
+ /**
+ * 用于人脸识别的引擎池
+ */
+ private GenericObjectPool frEnginePool;
+
+
+ private volatile ConcurrentHashMap faceResultRegistry = new ConcurrentHashMap<>();
+
+ private ExecutorService frService = Executors.newFixedThreadPool(20);
+
+ public ConcurrentHashMap faceFeatureRegistry = new ConcurrentHashMap<>();
+
+ /**
+ * 初始化引擎
+ */
+ public void initEngine(String appId, String sdkKey, String activeKey, String activeFile) {
+
+ //引擎配置
+ ftEngine = new FaceEngine(ArcFaceAutoConfiguration.CACHE_LIB_FOLDER);
+ int activeCode;
+ if (StringUtils.isNotEmpty(activeFile)) {
+ activeCode = ftEngine.activeOffline(activeFile);
+ } else {
+ activeCode = ftEngine.activeOnline(appId, sdkKey, activeKey);
+ }
+
+ EngineConfiguration ftEngineCfg = new EngineConfiguration();
+ ftEngineCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_VIDEO);
+ ftEngineCfg.setFunctionConfiguration(FunctionConfiguration.builder().supportFaceDetect(true).build());
+ int ftInitCode = ftEngine.init(ftEngineCfg);
+
+ //引擎配置
+ regEngine = new FaceEngine(ArcFaceAutoConfiguration.CACHE_LIB_FOLDER);
+
+ EngineConfiguration regEngineCfg = new EngineConfiguration();
+ regEngineCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
+ regEngineCfg.setFunctionConfiguration(FunctionConfiguration.builder().supportFaceDetect(true).supportFaceRecognition(true).build());
+ int regInitCode = regEngine.init(regEngineCfg);
+
+
+ GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
+ poolConfig.setMaxIdle(5);
+ poolConfig.setMaxTotal(5);
+ poolConfig.setMinIdle(5);
+ poolConfig.setLifo(false);
+ EngineConfiguration frEngineCfg = new EngineConfiguration();
+ frEngineCfg.setFunctionConfiguration(FunctionConfiguration.builder().supportFaceRecognition(true).build());
+ frEnginePool = new GenericObjectPool(new FaceEngineFactory(appId, sdkKey, activeKey,activeFile, frEngineCfg), poolConfig);//底层库算法对象池
+
+
+ if (!(activeCode == ErrorInfo.MOK.getValue() || activeCode == ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue())) {
+ log.error("activeCode: " + activeCode);
+ throw new RuntimeException("activeCode: " + activeCode);
+ }
+ if (ftInitCode != ErrorInfo.MOK.getValue()) {
+ log.error("ftInitEngine: " + ftInitCode);
+ throw new RuntimeException("ftInitEngine: " + ftInitCode);
+ }
+
+ if (regInitCode != ErrorInfo.MOK.getValue()) {
+ log.error("regInitEngine: " + regInitCode);
+ throw new RuntimeException("regInitEngine: " + regInitCode);
+ }
+
+ }
+
+
+ public void registerFace(String imagePath) {
+
+ log.info("正在注册人脸");
+
+ int count = 0;
+ if (regEngine != null) {
+ File file = new File(imagePath);
+ File[] files = file.listFiles();
+
+ for (File file1 : files) {
+ ImageInfo imageInfo = ImageFactory.getRGBData(file1);
+ if (imageInfo != null) {
+ List faceInfoList = new ArrayList<>();
+ int code = regEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(),
+ imageInfo.getImageFormat(), faceInfoList);
+
+ if (code == 0 && faceInfoList.size() > 0) {
+ FaceFeature faceFeature = new FaceFeature();
+ int resCode = regEngine.extractFaceFeature(imageInfo, faceInfoList.get(0), ExtractType.REGISTER, 0, faceFeature);
+ if (resCode == 0) {
+ int lastIndexOf = file1.getName().lastIndexOf(".");
+ String name = file1.getName().substring(0, file1.getName().length() - lastIndexOf - 1);
+ faceFeatureRegistry.put(name, faceFeature.getFeatureData());
+ log.info("成功注册人脸:" + name);
+ count++;
+ }
+ }
+ }
+ }
+ log.info("人脸注册完成,共注册:" + count + "张人脸");
+ } else {
+ throw new RuntimeException("注册失败,引擎未初始化或初始化失败");
+ }
+
+
+ }
+
+ public void registerFace(Map face) {
+ face.forEach((k, v) -> {
+ faceFeatureRegistry.put(k, v.clone());
+ });
+ }
+
+ public void removeFace(String name) {
+ faceFeatureRegistry.remove(name);
+ }
+
+ public void clearFace() {
+ faceFeatureRegistry.clear();
+ }
+
+ public FaceResult getFaceResult(FaceInfo faceInfo, ImageInfo imageInfo) {
+ FaceResult faceResult = faceResultRegistry.get(faceInfo.getFaceId());
+ if (faceResult == null) {
+ faceResult = new FaceResult();
+ faceResultRegistry.put(faceInfo.getFaceId(), faceResult);
+ frService.submit(new FaceInfoRunnable(faceInfo, imageInfo, faceResult));
+ } else if (faceResult.isFlag()) {
+ return faceResult;
+ }
+ return null;
+ }
+
+ public List detectFaces(ImageInfo imageInfo) {
+ if (ftEngine != null) {
+ List faceInfoList = new ArrayList<>();
+ int code = ftEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(),
+ imageInfo.getImageFormat(), faceInfoList);
+
+ List previewInfoList = new LinkedList<>();
+ for (FaceInfo faceInfo : faceInfoList) {
+ FacePreviewInfo facePreviewInfo = new FacePreviewInfo();
+ facePreviewInfo.setFaceInfo(faceInfo);
+ previewInfoList.add(facePreviewInfo);
+ }
+
+ clearFaceResultRegistry(faceInfoList);
+ return previewInfoList;
+
+ }
+ return null;
+ }
+
+
+ private long lastClearTime = System.currentTimeMillis();
+
+ //清理过时的人脸
+ private void clearFaceResultRegistry(List faceInfoList) {
+ if (System.currentTimeMillis() - lastClearTime > 5000) {
+ Iterator iterator = faceResultRegistry.keySet().iterator();
+ for (; iterator.hasNext(); ) {
+ Integer next = iterator.next();
+ boolean flag = false;
+ for (FaceInfo faceInfo : faceInfoList) {
+ if (next.equals(faceInfo.getFaceId())) {
+ flag = true;
+ }
+ }
+ if (!flag) {
+ iterator.remove();
+ }
+
+ }
+ lastClearTime = System.currentTimeMillis();
+ }
+
+
+ }
+
+
+ @Data
+ public class FaceResult {
+ private boolean flag = false;
+ private String name;
+ private float score;
+
+
+ }
+
+ @Data
+ public class FacePreviewInfo {
+
+ private FaceInfo faceInfo;
+ private int age;
+ private boolean liveness;
+
+ }
+
+
+ private class FaceInfoRunnable implements Runnable {
+ private FaceInfo faceInfo;
+ private ImageInfo imageInfo;
+ private FaceResult faceResult;
+
+ public FaceInfoRunnable(FaceInfo faceInfo, ImageInfo imageInfo, FaceResult faceResult) {
+ this.faceInfo = faceInfo;
+ this.imageInfo = imageInfo;
+ this.faceResult = faceResult;
+ }
+
+ @Override
+ public void run() {
+ FaceEngine frEngine = null;
+ try {
+ frEngine = frEnginePool.borrowObject();
+ if (frEngine != null) {
+ FaceFeature faceFeature = new FaceFeature();
+ int resCode = frEngine.extractFaceFeature(imageInfo, faceInfo, ExtractType.RECOGNIZE, 0, faceFeature);
+ if (resCode == 0) {
+
+ float score = 0.0F;
+ Iterator> iterator = faceFeatureRegistry.entrySet().iterator();
+ for (; iterator.hasNext(); ) {
+ Map.Entry next = iterator.next();
+ FaceFeature faceFeatureTarget = new FaceFeature();
+ faceFeatureTarget.setFeatureData(next.getValue());
+
+ FaceSimilar faceSimilar = new FaceSimilar();
+ frEngine.compareFaceFeature(faceFeatureTarget, faceFeature, faceSimilar);
+ if (faceSimilar.getScore() > score) {
+ score = faceSimilar.getScore();
+ faceResult.setName(next.getKey());
+ }
+ }
+
+ log.info("相似度:" + score);
+ if (score >= 0.8f) {
+ faceResult.setScore(score);
+ faceResult.setFlag(true);
+ faceResultRegistry.put(faceInfo.getFaceId(), faceResult);
+ } else {
+ faceResultRegistry.remove(faceInfo.getFaceId());
+ }
+
+ }
+ }
+ } catch (Exception e) {
+
+ } finally {
+ if (frEngine != null) {
+ frEnginePool.returnObject(frEngine);
+ }
+ }
+
+
+ }
+ }
+
+
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/factory/FaceEngineFactory.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/factory/FaceEngineFactory.java
new file mode 100644
index 0000000..bc90db4
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/factory/FaceEngineFactory.java
@@ -0,0 +1,73 @@
+package net.shapelight.modules.face.factory;
+
+import com.arcsoft.face.EngineConfiguration;
+import com.arcsoft.face.FaceEngine;
+import com.arcsoft.face.enums.ErrorInfo;
+import lombok.extern.slf4j.Slf4j;
+import net.shapelight.modules.face.config.ArcFaceAutoConfiguration;
+import net.shapelight.modules.face.enums.ErrorCodeEnum;
+import net.shapelight.modules.face.rpc.BusinessException;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.pool2.BasePooledObjectFactory;
+import org.apache.commons.pool2.PooledObject;
+import org.apache.commons.pool2.impl.DefaultPooledObject;
+
+@Slf4j
+public class FaceEngineFactory extends BasePooledObjectFactory {
+
+ private String appId;
+ private String sdkKey;
+ private String activeKey;
+ private String activeFile;
+ private EngineConfiguration engineConfiguration;
+
+
+ public FaceEngineFactory(String appId, String sdkKey, String activeKey, String activeFile, EngineConfiguration engineConfiguration) {
+ this.appId = appId;
+ this.sdkKey = sdkKey;
+ this.activeKey = activeKey;
+ this.activeFile=activeFile;
+ this.engineConfiguration = engineConfiguration;
+ }
+
+
+ @Override
+ public FaceEngine create() {
+
+
+ FaceEngine faceEngine = new FaceEngine(ArcFaceAutoConfiguration.CACHE_LIB_FOLDER);
+
+// FaceEngine faceEngine = new FaceEngine("/home/huangyifang/gb/咸阳师范/ArcSoft_ArcFacePro_linux_java_V4.1/libs/LINUX64/");
+ int activeCode;
+ if (StringUtils.isNotEmpty(activeFile)) {
+ activeCode = faceEngine.activeOffline(activeFile);
+ } else {
+ activeCode = faceEngine.activeOnline(appId, sdkKey, activeKey);
+ }
+ log.debug("引擎激活errorCode:" + activeCode);
+ if (activeCode != ErrorInfo.MOK.getValue() && activeCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
+ log.error("引擎激活失败" + activeCode);
+ throw new BusinessException(ErrorCodeEnum.FAIL, "引擎激活失败" + activeCode);
+ }
+ int initCode = faceEngine.init(engineConfiguration);
+ if (initCode != ErrorInfo.MOK.getValue()) {
+ log.error("引擎初始化失败" + initCode);
+ throw new BusinessException(ErrorCodeEnum.FAIL, "引擎初始化失败" + initCode);
+ }
+ log.debug("初始化引擎errorCode:" + initCode);
+ return faceEngine;
+ }
+
+ @Override
+ public PooledObject wrap(FaceEngine faceEngine) {
+ return new DefaultPooledObject<>(faceEngine);
+ }
+
+
+ @Override
+ public void destroyObject(PooledObject p) throws Exception {
+ FaceEngine faceEngine = p.getObject();
+ int result = faceEngine.unInit();
+ super.destroyObject(p);
+ }
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/rpc/BusinessException.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/rpc/BusinessException.java
new file mode 100644
index 0000000..4675a16
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/rpc/BusinessException.java
@@ -0,0 +1,64 @@
+package net.shapelight.modules.face.rpc;
+
+import lombok.Data;
+
+/**
+ * @Author: st7251
+ * @Date: 2018/11/23 14:18
+ */
+@Data
+public class BusinessException extends RuntimeException {
+ private ErrorCode errorCode;
+ private String msg;
+ private String msgCN;
+
+ public BusinessException(Response response) {
+ this.errorCode = new ErrorCode() {
+ @Override
+ public Integer getCode() {
+ return response.getCode();
+ }
+
+ @Override
+ public String getDesc() {
+ return response.getMsg();
+ }
+
+ @Override
+ public String getDescCN() {
+ return response.getMsg();
+ }
+ };
+ this.msg=response.getMsg();
+ this.msgCN=response.getMsg();
+ }
+
+ public BusinessException(ErrorCode errorCode) {
+ super(errorCode.getDesc());
+ this.errorCode = errorCode;
+ this.msg= errorCode.getDesc();
+ this.msgCN=errorCode.getDescCN();
+ }
+
+ public BusinessException(ErrorCode errorCode, String msg) {
+ super(errorCode.getDesc());
+ this.errorCode = errorCode;
+ this.msg = msg;
+ this.msgCN=msg;
+ }
+
+ public BusinessException(Throwable cause, ErrorCode errorCode) {
+ super(cause);
+ this.errorCode = errorCode;
+ this.msg= errorCode.getDesc();
+ this.msgCN=errorCode.getDescCN();
+ }
+
+
+ public BusinessException(Throwable cause, ErrorCode errorCode, String msg) {
+ super(cause);
+ this.errorCode = errorCode;
+ this.msg = msg;
+ this.msgCN=msg;
+ }
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/rpc/ErrorCode.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/rpc/ErrorCode.java
new file mode 100644
index 0000000..e22ec67
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/rpc/ErrorCode.java
@@ -0,0 +1,12 @@
+package net.shapelight.modules.face.rpc;
+
+public interface ErrorCode {
+
+
+ Integer getCode();
+
+ String getDesc();
+
+ String getDescCN();
+
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/rpc/GlobalExceptionHandler.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/rpc/GlobalExceptionHandler.java
new file mode 100644
index 0000000..ddd04ef
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/rpc/GlobalExceptionHandler.java
@@ -0,0 +1,47 @@
+package net.shapelight.modules.face.rpc;
+
+
+import lombok.extern.slf4j.Slf4j;
+import net.shapelight.modules.face.enums.ErrorCodeEnum;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+@RestControllerAdvice
+@Slf4j
+public class GlobalExceptionHandler{
+
+
+ /**
+ * 自定义异常
+ */
+ @ExceptionHandler(BusinessException.class)
+ public Response businessException(BusinessException e) {
+ log.error(e.getMessage(), e);
+ Response response = new Response();
+ response.setCode(e.getErrorCode().getCode());
+ response.setMsg(e.getMsgCN());
+ return response;
+ }
+
+ @ExceptionHandler(IllegalArgumentException.class)
+ public Response handleIllegalArgumentException(IllegalArgumentException e) {
+ log.error(e.getMessage(), e);
+ Response response = new Response();
+ response.setCode(ErrorCodeEnum.PARAM_ERROR.getCode());
+ response.setMsg(e.getMessage());
+ return response;
+ }
+
+ @ExceptionHandler(Exception.class)
+ public Response handleException(Exception e) {
+ log.error(e.getMessage(), e);
+ Response response = new Response();
+ response.setCode(ErrorCodeEnum.SYSTEM_ERROR.getCode());
+ response.setMsg(ErrorCodeEnum.SYSTEM_ERROR.getDescCN());
+ return response;
+ }
+
+
+
+
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/rpc/Response.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/rpc/Response.java
new file mode 100644
index 0000000..926d866
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/rpc/Response.java
@@ -0,0 +1,39 @@
+package net.shapelight.modules.face.rpc;
+
+import lombok.Data;
+
+@Data
+public class Response {
+
+ private int code = -1;
+ private String msg = "success";
+ private T data;
+
+ public static Response newSuccessResponse(T data) {
+ return newResponse(data, 0, "success");
+ }
+
+ public static Response newFailedResponse(Integer code, String message) {
+ return newResponse(null, code, message);
+ }
+
+ public static Response newFailedResponse(ErrorCode ErrorCode) {
+ return newResponse(null, ErrorCode.getCode(), ErrorCode.getDesc());
+ }
+
+ public static Response newFailedResponse(ErrorCode ErrorCode, String message) {
+ return newResponse(null, ErrorCode.getCode(), message);
+ }
+
+ public static Response newResponse(T data, Integer code, String message) {
+ Response response = new Response();
+ response.setCode(code);
+ response.setMsg(message);
+ if (data != null && data instanceof String && "".equals(data)) {
+ response.setData(null);
+ } else {
+ response.setData(data);
+ }
+ return response;
+ }
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/service/FaceEngineService.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/service/FaceEngineService.java
new file mode 100644
index 0000000..556a16d
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/service/FaceEngineService.java
@@ -0,0 +1,30 @@
+package net.shapelight.modules.face.service;
+
+
+import com.arcsoft.face.FaceInfo;
+import com.arcsoft.face.enums.ExtractType;
+import com.arcsoft.face.toolkit.ImageInfo;
+import net.shapelight.modules.face.entity.ProcessInfo;
+import net.shapelight.modules.face.entity.UserCompareInfo;
+import net.shapelight.modules.face.util.UserRamCache;
+
+import java.util.List;
+
+
+public interface FaceEngineService {
+
+ List detectFaces(ImageInfo imageInfo);
+
+ Float compareFace(ImageInfo imageInfo1, ImageInfo imageInfo2) ;
+
+ byte[] extractFaceFeature(ImageInfo imageInfo, FaceInfo faceInfo, ExtractType extractType);
+
+ List faceRecognition(byte[] faceFeature, List userInfoList, float passRate) ;
+
+ List process(ImageInfo imageInfo, List faceInfoList);
+
+
+
+
+
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/service/impl/FaceEngineServiceImpl.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/service/impl/FaceEngineServiceImpl.java
new file mode 100644
index 0000000..41c7b9f
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/service/impl/FaceEngineServiceImpl.java
@@ -0,0 +1,348 @@
+package net.shapelight.modules.face.service.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.arcsoft.face.*;
+import com.arcsoft.face.enums.DetectMode;
+import com.arcsoft.face.enums.DetectOrient;
+import com.arcsoft.face.enums.ExtractType;
+import com.arcsoft.face.toolkit.ImageInfo;
+import com.google.common.collect.Lists;
+import lombok.extern.slf4j.Slf4j;
+import net.shapelight.modules.face.entity.ProcessInfo;
+import net.shapelight.modules.face.entity.UserCompareInfo;
+import net.shapelight.modules.face.enums.ErrorCodeEnum;
+import net.shapelight.modules.face.factory.FaceEngineFactory;
+import net.shapelight.modules.face.rpc.BusinessException;
+import net.shapelight.modules.face.service.FaceEngineService;
+import net.shapelight.modules.face.util.UserRamCache;
+import org.apache.commons.pool2.impl.GenericObjectPool;
+import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.*;
+
+
+@Service("faceEngineService")
+@Slf4j
+public class FaceEngineServiceImpl implements FaceEngineService {
+
+ public final static Logger logger = LoggerFactory.getLogger(FaceEngineServiceImpl.class);
+
+ @Value("${config.arcface-sdk.app-id}")
+ public String appId;
+
+ @Value("${config.arcface-sdk.sdk-key}")
+ public String sdkKey;
+
+ @Value("${config.arcface-sdk.active-key}")
+ public String activeKey;
+
+ @Value("${config.arcface-sdk.active-file}")
+ public String activeFile;
+
+ @Value("${config.arcface-sdk.detect-pool-size}")
+ public Integer detectPooSize;
+
+ @Value("${config.arcface-sdk.compare-pool-size}")
+ public Integer comparePooSize;
+
+ private ExecutorService compareExecutorService;
+
+ //通用人脸识别引擎池
+ private GenericObjectPool faceEngineGeneralPool;
+
+ //人脸比对引擎池
+ private GenericObjectPool faceEngineComparePool;
+
+ @PostConstruct
+ public void init() {
+
+
+ GenericObjectPoolConfig detectPoolConfig = new GenericObjectPoolConfig();
+ detectPoolConfig.setMaxIdle(detectPooSize);
+ detectPoolConfig.setMaxTotal(detectPooSize);
+ detectPoolConfig.setMinIdle(detectPooSize);
+ detectPoolConfig.setLifo(false);
+ EngineConfiguration detectCfg = new EngineConfiguration();
+ FunctionConfiguration detectFunctionCfg = new FunctionConfiguration();
+ detectFunctionCfg.setSupportFaceDetect(true);//开启人脸检测功能
+ detectFunctionCfg.setSupportFaceRecognition(true);//开启人脸识别功能
+ detectFunctionCfg.setSupportAge(true);//开启年龄检测功能
+ detectFunctionCfg.setSupportGender(true);//开启性别检测功能
+ detectFunctionCfg.setSupportLiveness(true);//开启活体检测功能
+ detectCfg.setFunctionConfiguration(detectFunctionCfg);
+ detectCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);//图片检测模式,如果是连续帧的视频流图片,那么改成VIDEO模式
+ detectCfg.setDetectFaceOrientPriority(DetectOrient.ASF_OP_0_ONLY);//人脸旋转角度
+ faceEngineGeneralPool = new GenericObjectPool(new FaceEngineFactory(appId, sdkKey, activeKey, activeFile, detectCfg), detectPoolConfig);//底层库算法对象池
+
+
+ //初始化特征比较线程池
+ GenericObjectPoolConfig comparePoolConfig = new GenericObjectPoolConfig();
+ comparePoolConfig.setMaxIdle(comparePooSize);
+ comparePoolConfig.setMaxTotal(comparePooSize);
+ comparePoolConfig.setMinIdle(comparePooSize);
+ comparePoolConfig.setLifo(false);
+ EngineConfiguration compareCfg = new EngineConfiguration();
+ FunctionConfiguration compareFunctionCfg = new FunctionConfiguration();
+ compareFunctionCfg.setSupportFaceRecognition(true);//开启人脸识别功能
+ compareCfg.setFunctionConfiguration(compareFunctionCfg);
+ compareCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);//图片检测模式,如果是连续帧的视频流图片,那么改成VIDEO模式
+ compareCfg.setDetectFaceOrientPriority(DetectOrient.ASF_OP_0_ONLY);//人脸旋转角度
+ faceEngineComparePool = new GenericObjectPool(new FaceEngineFactory(appId, sdkKey, activeKey, activeFile, compareCfg), comparePoolConfig);//底层库算法对象池
+ compareExecutorService = Executors.newFixedThreadPool(comparePooSize);
+ }
+
+
+ @Override
+ public List detectFaces(ImageInfo imageInfo) {
+
+ FaceEngine faceEngine = null;
+ try {
+ faceEngine = faceEngineGeneralPool.borrowObject();
+ if (faceEngine == null) {
+ throw new BusinessException(ErrorCodeEnum.FAIL, "获取引擎失败");
+ }
+
+ //人脸检测得到人脸列表
+ List faceInfoList = new ArrayList();
+ //人脸检测
+ int errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
+ if (errorCode == 0) {
+ return faceInfoList;
+ } else {
+ log.error("人脸检测失败,errorCode:" + errorCode);
+ }
+
+ } catch (Exception e) {
+ log.error("", e);
+ } finally {
+ if (faceEngine != null) {
+ //释放引擎对象
+ faceEngineGeneralPool.returnObject(faceEngine);
+ }
+ }
+
+ return null;
+
+ }
+
+ @Override
+ public Float compareFace(ImageInfo imageInfo1, ImageInfo imageInfo2) {
+
+ List faceInfoList1 = detectFaces(imageInfo1);
+ List faceInfoList2 = detectFaces(imageInfo2);
+
+ if (CollectionUtil.isEmpty(faceInfoList1)) {
+ throw new BusinessException(ErrorCodeEnum.FAIL, "照片1未检测到人脸");
+ }
+ if (CollectionUtil.isEmpty(faceInfoList2)) {
+ throw new BusinessException(ErrorCodeEnum.FAIL, "照片2未检测到人脸");
+ }
+
+ byte[] feature1 = extractFaceFeature(imageInfo1, faceInfoList1.get(0), ExtractType.REGISTER);
+ byte[] feature2 = extractFaceFeature(imageInfo2, faceInfoList2.get(0), ExtractType.RECOGNIZE);
+
+ FaceEngine faceEngine = null;
+ try {
+ faceEngine = faceEngineGeneralPool.borrowObject();
+ if (faceEngine == null) {
+ throw new BusinessException(ErrorCodeEnum.FAIL, "获取引擎失败");
+ }
+
+ FaceFeature faceFeature1 = new FaceFeature();
+ faceFeature1.setFeatureData(feature1);
+ FaceFeature faceFeature2 = new FaceFeature();
+ faceFeature2.setFeatureData(feature2);
+ //提取人脸特征
+ FaceSimilar faceSimilar = new FaceSimilar();
+ int errorCode = faceEngine.compareFaceFeature(faceFeature1, faceFeature2, faceSimilar);
+ if (errorCode == 0) {
+ return faceSimilar.getScore();
+ } else {
+ log.error("特征提取失败,errorCode:" + errorCode);
+ }
+
+ } catch (Exception e) {
+ log.error("", e);
+ } finally {
+ if (faceEngine != null) {
+ //释放引擎对象
+ faceEngineGeneralPool.returnObject(faceEngine);
+ }
+ }
+
+ return null;
+
+ }
+
+ /**
+ * 人脸特征
+ *
+ * @param imageInfo
+ * @return
+ */
+ @Override
+ public byte[] extractFaceFeature(ImageInfo imageInfo, FaceInfo faceInfo, ExtractType extractType) {
+
+ FaceEngine faceEngine = null;
+ try {
+ faceEngine = faceEngineGeneralPool.borrowObject();
+ if (faceEngine == null) {
+ throw new BusinessException(ErrorCodeEnum.FAIL, "获取引擎失败");
+ }
+
+ FaceFeature faceFeature = new FaceFeature();
+ //提取人脸特征
+ int errorCode = faceEngine.extractFaceFeature(imageInfo, faceInfo, extractType, 0, faceFeature);
+ if (errorCode == 0) {
+ return faceFeature.getFeatureData();
+ } else {
+ log.error("特征提取失败,errorCode:" + errorCode);
+ }
+
+ } catch (Exception e) {
+ log.error("", e);
+ } finally {
+ if (faceEngine != null) {
+ //释放引擎对象
+ faceEngineGeneralPool.returnObject(faceEngine);
+ }
+ }
+
+ return null;
+
+ }
+
+ @Override
+ public List faceRecognition(byte[] faceFeature, List userInfoList, float passRate) {
+ List resultUserInfoList = Lists.newLinkedList();//识别到的人脸列表
+
+ FaceFeature targetFaceFeature = new FaceFeature();
+ targetFaceFeature.setFeatureData(faceFeature);
+
+ List> faceUserInfoPartList = Lists.partition(userInfoList, 1000);//分成1000一组,多线程处理
+ CompletionService> completionService = new ExecutorCompletionService(compareExecutorService);
+ for (List part : faceUserInfoPartList) {
+ completionService.submit(new CompareFaceTask(part, targetFaceFeature, passRate));
+ }
+ for (int i = 0; i < faceUserInfoPartList.size(); i++) {
+ List faceUserInfoList = null;
+ try {
+ faceUserInfoList = completionService.take().get();
+ } catch (InterruptedException | ExecutionException e) {
+ }
+ if (CollectionUtil.isNotEmpty(userInfoList)) {
+ resultUserInfoList.addAll(faceUserInfoList);
+ }
+ }
+
+ resultUserInfoList.sort((h1, h2) -> h2.getSimilar().compareTo(h1.getSimilar()));//从大到小排序
+
+ return resultUserInfoList;
+ }
+
+
+ @Override
+ public List process(ImageInfo imageInfo, List faceInfoList) {
+ FaceEngine faceEngine = null;
+ try {
+ //获取引擎对象
+ faceEngine = faceEngineGeneralPool.borrowObject();
+ if (faceEngine == null) {
+ throw new BusinessException(ErrorCodeEnum.FAIL, "获取引擎失败");
+ }
+
+
+ int errorCode = faceEngine.process(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList, FunctionConfiguration.builder().supportAge(true).supportGender(true).supportLiveness(true).build());
+ if (errorCode == 0) {
+ List processInfoList = Lists.newLinkedList();
+
+ //性别列表
+ List genderInfoList = new ArrayList();
+ faceEngine.getGender(genderInfoList);
+
+ //年龄列表
+ List ageInfoList = new ArrayList();
+ faceEngine.getAge(ageInfoList);
+ //活体结果列表
+ List livenessInfoList = new ArrayList();
+ faceEngine.getLiveness(livenessInfoList);
+
+
+ for (int i = 0; i < genderInfoList.size(); i++) {
+ ProcessInfo processInfo = new ProcessInfo();
+ processInfo.setGender(genderInfoList.get(i).getGender());
+ processInfo.setAge(ageInfoList.get(i).getAge());
+ processInfo.setLiveness(livenessInfoList.get(i).getLiveness());
+ processInfoList.add(processInfo);
+ }
+ return processInfoList;
+
+ }
+
+
+ } catch (Exception e) {
+ logger.error("", e);
+ } finally {
+ if (faceEngine != null) {
+ //释放引擎对象
+ faceEngineGeneralPool.returnObject(faceEngine);
+ }
+ }
+
+ return null;
+
+ }
+
+
+ private class CompareFaceTask implements Callable> {
+
+ private List userInfoList;
+ private FaceFeature targetFaceFeature;
+ private float passRate;
+
+
+ public CompareFaceTask(List userInfoList, FaceFeature targetFaceFeature, float passRate) {
+ this.userInfoList = userInfoList;
+ this.targetFaceFeature = targetFaceFeature;
+ this.passRate = passRate;
+ }
+
+ @Override
+ public List call() throws Exception {
+ FaceEngine faceEngine = null;
+ List resultUserInfoList = Lists.newLinkedList();//识别到的人脸列表
+ try {
+ faceEngine = faceEngineComparePool.borrowObject();
+ for (UserRamCache.UserInfo userInfo : userInfoList) {
+ FaceFeature sourceFaceFeature = new FaceFeature();
+ sourceFaceFeature.setFeatureData(userInfo.getFaceFeature());
+ FaceSimilar faceSimilar = new FaceSimilar();
+ faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
+ if (faceSimilar.getScore() > passRate) {//相似值大于配置预期,加入到识别到人脸的列表
+ UserCompareInfo info = new UserCompareInfo();
+ info.setName(userInfo.getName());
+ info.setFaceId(userInfo.getFaceId());
+ info.setSimilar(faceSimilar.getScore());
+ resultUserInfoList.add(info);
+ }
+ }
+ } catch (Exception e) {
+ logger.error("", e);
+ } finally {
+ if (faceEngine != null) {
+ faceEngineComparePool.returnObject(faceEngine);
+ }
+ }
+
+ return resultUserInfoList;
+ }
+
+ }
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/util/Base64Util.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/util/Base64Util.java
new file mode 100644
index 0000000..29db3c6
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/util/Base64Util.java
@@ -0,0 +1,33 @@
+package net.shapelight.modules.face.util;
+
+import org.springframework.util.ObjectUtils;
+
+import java.util.Base64;
+
+public class Base64Util {
+ public static String base64Process(String base64Str) {
+ if (!ObjectUtils.isEmpty(base64Str)) {
+ String photoBase64 = base64Str.substring(0, 30).toLowerCase();
+ int indexOf = photoBase64.indexOf("base64,");
+ if (indexOf > 0) {
+ base64Str = base64Str.substring(indexOf + 7);
+ }
+ base64Str = base64Str.replaceAll(" ", "+");
+ base64Str = base64Str.replaceAll("\r|\n", "");
+ return base64Str;
+ }
+ return "";
+ }
+
+ public static byte[] base64ToBytes(String base64) {
+ if (ObjectUtils.isEmpty(base64)) {
+ return null;
+ }
+ String base64Process = base64Process(base64);
+
+ byte[] decode = Base64.getDecoder().decode(base64Process);
+ return decode;
+
+
+ }
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/util/FaceEngineTest.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/util/FaceEngineTest.java
new file mode 100644
index 0000000..4e4fa7d
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/util/FaceEngineTest.java
@@ -0,0 +1,225 @@
+package net.shapelight.modules.face.util;
+
+import com.arcsoft.face.*;
+import com.arcsoft.face.enums.*;
+import com.arcsoft.face.toolkit.ImageFactory;
+import com.arcsoft.face.toolkit.ImageInfo;
+import com.arcsoft.face.toolkit.ImageInfoEx;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class FaceEngineTest {
+
+
+ public static void main(String[] args) {
+
+ //激活码,从官网获取
+ String appId = "DEnAZa1bWXcaAxyWUg33QZaKCmMkNmrQxuKZJQGmZsHJ";
+ String sdkKey = "vWbvUyStZeartSaM6QoTzPYWFpSaj4uhfDmRifSzCd6";
+ String activeKey = "82G1-11QA-713Y-8NB4";
+
+ System.err.println("注意,如果返回的errorCode不为0,可查看com.arcsoft.face.enums.ErrorInfo类获取相应的错误信息");
+
+ //人脸识别引擎库存放路径
+ FaceEngine faceEngine = new FaceEngine("/home/huangyifang/gb/咸阳师范/ArcSoft_ArcFacePro_linux_java_V4.1/libs/LINUX64");
+ //激活引擎
+ int errorCode = faceEngine.activeOnline(appId, sdkKey, activeKey);
+ System.out.println("引擎激活errorCode:" + errorCode);
+
+ ActiveDeviceInfo activeDeviceInfo = new ActiveDeviceInfo();
+ //采集设备信息(可离线)
+ errorCode = faceEngine.getActiveDeviceInfo(activeDeviceInfo);
+ System.out.println("采集设备信息errorCode:" + errorCode);
+ System.out.println("设备信息:" + activeDeviceInfo.getDeviceInfo());
+
+// faceEngine.activeOffline("d:\\ArcFacePro64.dat.offline");
+
+ ActiveFileInfo activeFileInfo = new ActiveFileInfo();
+ errorCode = faceEngine.getActiveFileInfo(activeFileInfo);
+ System.out.println("获取激活文件errorCode:" + errorCode);
+ System.out.println("激活文件信息:" + activeFileInfo.toString());
+
+ //引擎配置
+ EngineConfiguration engineConfiguration = new EngineConfiguration();
+ engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
+ engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
+ engineConfiguration.setDetectFaceMaxNum(10);
+ //功能配置
+ FunctionConfiguration functionConfiguration = new FunctionConfiguration();
+ functionConfiguration.setSupportAge(true);
+ functionConfiguration.setSupportFaceDetect(true);
+ functionConfiguration.setSupportFaceRecognition(true);
+ functionConfiguration.setSupportGender(true);
+ functionConfiguration.setSupportLiveness(true);
+ functionConfiguration.setSupportIRLiveness(true);
+ functionConfiguration.setSupportImageQuality(true);
+ functionConfiguration.setSupportMaskDetect(true);
+ functionConfiguration.setSupportUpdateFaceData(true);
+ engineConfiguration.setFunctionConfiguration(functionConfiguration);
+
+ //初始化引擎
+ errorCode = faceEngine.init(engineConfiguration);
+ System.out.println("初始化引擎errorCode:" + errorCode);
+ VersionInfo version = faceEngine.getVersion();
+ System.out.println(version);
+
+ //人脸检测
+ ImageInfo imageInfo = ImageFactory.getRGBData(new File("/home/huangyifang/gb/咸阳师范/10.jpg"));
+ List faceInfoList = new ArrayList();
+ errorCode = faceEngine.detectFaces(imageInfo, faceInfoList);
+ System.out.println("人脸检测errorCode:" + errorCode);
+ System.out.println("检测到人脸数:" + faceInfoList.size());
+
+ ImageQuality imageQuality = new ImageQuality();
+ errorCode = faceEngine.imageQualityDetect(imageInfo, faceInfoList.get(0), 0, imageQuality);
+ System.out.println("图像质量检测errorCode:" + errorCode);
+ System.out.println("图像质量分数:" + imageQuality.getFaceQuality());
+
+ //特征提取
+ FaceFeature faceFeature = new FaceFeature();
+ errorCode = faceEngine.extractFaceFeature(imageInfo, faceInfoList.get(0), ExtractType.REGISTER, 0, faceFeature);
+ System.out.println("特征提取errorCode:" + errorCode);
+
+ //人脸检测2
+ ImageInfo imageInfo2 = ImageFactory.getRGBData(new File("/home/huangyifang/gb/咸阳师范/10.jpg"));
+ List faceInfoList2 = new ArrayList();
+ errorCode = faceEngine.detectFaces(imageInfo2, faceInfoList2);
+ System.out.println("人脸检测errorCode:" + errorCode);
+ System.out.println("检测到人脸数:" + faceInfoList.size());
+
+ //特征提取2
+ FaceFeature faceFeature2 = new FaceFeature();
+ errorCode = faceEngine.extractFaceFeature(imageInfo2, faceInfoList2.get(0), ExtractType.RECOGNIZE, 0, faceFeature2);
+ System.out.println("特征提取errorCode:" + errorCode);
+
+ //特征比对
+ FaceFeature targetFaceFeature = new FaceFeature();
+ targetFaceFeature.setFeatureData(faceFeature.getFeatureData());
+ FaceFeature sourceFaceFeature = new FaceFeature();
+ sourceFaceFeature.setFeatureData(faceFeature2.getFeatureData());
+ FaceSimilar faceSimilar = new FaceSimilar();
+
+ errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
+ System.out.println("特征比对errorCode:" + errorCode);
+ System.out.println("人脸相似度:" + faceSimilar.getScore());
+
+
+ //人脸属性检测
+ FunctionConfiguration configuration = new FunctionConfiguration();
+ configuration.setSupportAge(true);
+ configuration.setSupportGender(true);
+ configuration.setSupportLiveness(true);
+ configuration.setSupportMaskDetect(true);
+ errorCode = faceEngine.process(imageInfo, faceInfoList, configuration);
+ System.out.println("图像属性处理errorCode:" + errorCode);
+
+ //性别检测
+ List genderInfoList = new ArrayList();
+ errorCode = faceEngine.getGender(genderInfoList);
+ System.out.println("性别:" + genderInfoList.get(0).getGender());
+
+ //年龄检测
+ List ageInfoList = new ArrayList();
+ errorCode = faceEngine.getAge(ageInfoList);
+ System.out.println("年龄:" + ageInfoList.get(0).getAge());
+
+ //活体检测
+ List livenessInfoList = new ArrayList();
+ errorCode = faceEngine.getLiveness(livenessInfoList);
+ System.out.println("活体:" + livenessInfoList.get(0).getLiveness());
+
+ //口罩检测
+ List maskInfoList = new ArrayList();
+ errorCode = faceEngine.getMask(maskInfoList);
+ System.out.println("口罩:" + maskInfoList.get(0).getMask());
+
+
+ //IR属性处理
+ ImageInfo imageInfoGray = ImageFactory.getGrayData(new File("/home/huangyifang/gb/咸阳师范/10.jpg"));
+ List faceInfoListGray = new ArrayList();
+ errorCode = faceEngine.detectFaces(imageInfoGray, faceInfoListGray);
+
+ FunctionConfiguration configuration2 = new FunctionConfiguration();
+ configuration2.setSupportIRLiveness(true);
+ errorCode = faceEngine.processIr(imageInfoGray, faceInfoListGray, configuration2);
+ //IR活体检测
+ List irLivenessInfo = new ArrayList<>();
+ errorCode = faceEngine.getLivenessIr(irLivenessInfo);
+ System.out.println("IR活体:" + irLivenessInfo.get(0).getLiveness());
+
+ //获取激活文件信息
+ ActiveFileInfo activeFileInfo2 = new ActiveFileInfo();
+ errorCode = faceEngine.getActiveFileInfo(activeFileInfo2);
+
+ //更新人脸数据
+ errorCode = faceEngine.updateFaceData(imageInfo, faceInfoList);
+
+ //高级人脸图像处理接口
+ ImageInfoEx imageInfoEx = new ImageInfoEx();
+ imageInfoEx.setHeight(imageInfo.getHeight());
+ imageInfoEx.setWidth(imageInfo.getWidth());
+ imageInfoEx.setImageFormat(imageInfo.getImageFormat());
+ imageInfoEx.setImageDataPlanes(new byte[][]{imageInfo.getImageData()});
+ imageInfoEx.setImageStrides(new int[]{imageInfo.getWidth() * 3});
+ List faceInfoList1 = new ArrayList<>();
+ errorCode = faceEngine.detectFaces(imageInfoEx, DetectModel.ASF_DETECT_MODEL_RGB, faceInfoList1);
+ ImageQuality imageQuality1 = new ImageQuality();
+ errorCode = faceEngine.imageQualityDetect(imageInfoEx, faceInfoList1.get(0), 0, imageQuality1);
+ FunctionConfiguration fun = new FunctionConfiguration();
+ fun.setSupportAge(true);
+ errorCode = faceEngine.process(imageInfoEx, faceInfoList1, fun);
+ List ageInfoList1 = new ArrayList<>();
+ int age = faceEngine.getAge(ageInfoList1);
+ FaceFeature feature = new FaceFeature();
+ errorCode = faceEngine.extractFaceFeature(imageInfoEx, faceInfoList1.get(0), ExtractType.REGISTER, 0, feature);
+ errorCode = faceEngine.updateFaceData(imageInfoEx, faceInfoList1);
+
+ //设置活体测试
+ errorCode = faceEngine.setLivenessParam(0.5f, 0.7f, 0.3f);
+ System.out.println("设置活体活体阈值errorCode:" + errorCode);
+
+ LivenessParam livenessParam=new LivenessParam();
+ errorCode = faceEngine.getLivenessParam(livenessParam);
+
+ //注册人脸信息1
+ FaceFeatureInfo faceFeatureInfo = new FaceFeatureInfo();
+ faceFeatureInfo.setSearchId(5);
+ faceFeatureInfo.setFaceTag("FeatureData1");
+ faceFeatureInfo.setFeatureData(faceFeature.getFeatureData());
+ errorCode = faceEngine.registerFaceFeature(faceFeatureInfo);
+
+ //注册人脸信息2
+ FaceFeatureInfo faceFeatureInfo2 = new FaceFeatureInfo();
+ faceFeatureInfo2.setSearchId(6);
+ faceFeatureInfo2.setFaceTag("FeatureData2");
+ faceFeatureInfo2.setFeatureData(faceFeature2.getFeatureData());
+ errorCode = faceEngine.registerFaceFeature(faceFeatureInfo2);
+
+ //获取注册人脸个数
+ FaceSearchCount faceSearchCount = new FaceSearchCount();
+ errorCode = faceEngine.getFaceCount(faceSearchCount);
+ System.out.println("注册人脸个数:" + faceSearchCount.getCount());
+
+ //搜索最相似人脸
+ SearchResult searchResult = new SearchResult();
+ errorCode = faceEngine.searchFaceFeature(faceFeature, CompareModel.LIFE_PHOTO, searchResult);
+ System.out.println("最相似人脸Id:" + searchResult.getFaceFeatureInfo().getSearchId());
+
+ //更新人脸信息
+ FaceFeatureInfo faceFeatureInfo3 = new FaceFeatureInfo();
+ faceFeatureInfo3.setSearchId(6);
+ faceFeatureInfo3.setFaceTag("FeatureData2Update");
+ faceFeatureInfo3.setFeatureData(faceFeature2.getFeatureData());
+ errorCode = faceEngine.updateFaceFeature(faceFeatureInfo3);
+
+ //移除人脸信息
+ errorCode = faceEngine.removeFaceFeature(6);
+
+ //引擎卸载
+ errorCode = faceEngine.unInit();
+
+
+ }
+}
\ No newline at end of file
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/face/util/UserRamCache.java b/shapelight-admin/src/main/java/net/shapelight/modules/face/util/UserRamCache.java
new file mode 100644
index 0000000..acf2558
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/face/util/UserRamCache.java
@@ -0,0 +1,67 @@
+package net.shapelight.modules.face.util;
+
+import com.google.common.collect.Lists;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+public class UserRamCache {
+
+ private static final ConcurrentHashMap USER_INFO_MAP = new ConcurrentHashMap<>();
+
+ private static final Set REGISTER = new CopyOnWriteArraySet<>();
+
+ public static void addUser(UserInfo userInfo) {
+ USER_INFO_MAP.put(userInfo.getFaceId(), userInfo);
+ for (Listener listener : REGISTER) {
+ listener.onAdd(userInfo);
+ }
+ }
+
+ public static void removeUser(String faceId) {
+ UserInfo userInfo = USER_INFO_MAP.remove(faceId);
+ for (Listener listener : REGISTER) {
+ listener.onRemove(userInfo);
+ }
+ }
+
+ public static List getUserList() {
+ List userInfoList = Lists.newLinkedList();
+ userInfoList.addAll(USER_INFO_MAP.values());
+ return userInfoList;
+ }
+
+ public static void clear(){
+ USER_INFO_MAP.clear();
+ REGISTER.clear();
+ }
+
+ public static void addListener(Listener listener) {
+ REGISTER.add(listener);
+ }
+
+ public static void removeListener(Listener listener) {
+ REGISTER.remove(listener);
+ }
+
+ @Data
+ public static class UserInfo {
+
+ private String faceId;
+ private String name;
+ private byte[] faceFeature;
+
+ }
+
+ public interface Listener {
+ default void onAdd(UserInfo userInfo) {
+ }
+
+ default void onRemove(UserInfo userInfo) {
+
+ }
+ }
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/httpapi/controler/FaceController.java b/shapelight-admin/src/main/java/net/shapelight/modules/httpapi/controler/FaceController.java
new file mode 100644
index 0000000..3852217
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/httpapi/controler/FaceController.java
@@ -0,0 +1,239 @@
+package net.shapelight.modules.httpapi.controler;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.arcsoft.face.FaceInfo;
+import com.arcsoft.face.enums.ExtractType;
+import com.arcsoft.face.toolkit.ImageFactory;
+import com.arcsoft.face.toolkit.ImageInfo;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import io.minio.PutObjectOptions;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import net.shapelight.common.utils.R;
+import net.shapelight.common.utils.UUIDUtil;
+import net.shapelight.modules.face.dto.*;
+import net.shapelight.modules.face.entity.ProcessInfo;
+import net.shapelight.modules.face.entity.UserCompareInfo;
+import net.shapelight.modules.face.rpc.Response;
+import net.shapelight.modules.face.service.FaceEngineService;
+import net.shapelight.modules.face.util.Base64Util;
+import net.shapelight.modules.face.util.UserRamCache;
+import org.apache.commons.io.FilenameUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.PostConstruct;
+import java.io.InputStream;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+
+@Controller
+@Slf4j
+@RequestMapping("/api/dev/v3")
+public class FaceController {
+
+ @Autowired
+ private FaceEngineService faceEngineService;
+
+
+ //初始化注册人脸,注册到本地内存
+// @PostConstruct
+// public void initFace() throws Exception {
+// Map fileMap = Maps.newHashMap();
+// fileMap.put("zhao1", "赵丽颖");
+// fileMap.put("yang1", "杨紫");
+// fileMap.put("baixue", "白雪");
+// fileMap.put("chenchuang", "陈创");
+// for (String f : fileMap.keySet()) {
+// ClassPathResource resource = new ClassPathResource("static/images/" + f + ".jpg");
+// InputStream inputStream = resource.getInputStream();
+// ImageInfo rgbData = ImageFactory.getRGBData(inputStream);
+// List faceInfoList = faceEngineService.detectFaces(rgbData);
+// if (CollectionUtil.isNotEmpty(faceInfoList)) {
+// byte[] feature = faceEngineService.extractFaceFeature(rgbData, faceInfoList.get(0), ExtractType.REGISTER);
+// UserRamCache.UserInfo userInfo = new UserCompareInfo();
+// userInfo.setFaceId(f);
+// userInfo.setName(fileMap.get(f));
+// userInfo.setFaceFeature(feature);
+// //这边注册到内存缓存中,也可以根据业务,注册到数据库中
+// UserRamCache.addUser(userInfo);
+// }
+// }
+// }
+
+
+ /*
+ 人脸添加
+ */
+ @RequestMapping(value = "/faceAdd", method = RequestMethod.POST)
+ @ResponseBody
+ public Response faceAdd(@RequestBody FaceAddReqDTO faceAddReqDTO) {
+ String image = faceAddReqDTO.getImage();
+
+ byte[] bytes = Base64Util.base64ToBytes(image);
+ ImageInfo rgbData = ImageFactory.getRGBData(bytes);
+ List faceInfoList = faceEngineService.detectFaces(rgbData);
+ if (CollectionUtil.isNotEmpty(faceInfoList)) {
+ for (FaceInfo faceInfo : faceInfoList) {
+ FaceRecognitionResDTO faceRecognitionResDTO = new FaceRecognitionResDTO();
+ faceRecognitionResDTO.setRect(faceInfo.getRect());
+ byte[] feature = faceEngineService.extractFaceFeature(rgbData, faceInfo,ExtractType.REGISTER);
+ if (feature != null) {
+ UserRamCache.UserInfo userInfo = new UserCompareInfo();
+ userInfo.setFaceId(faceAddReqDTO.getName());
+ userInfo.setName(faceAddReqDTO.getName());
+ userInfo.setFaceFeature(feature);
+ //这边注册到内存缓存中,也可以根据业务,注册到数据库中
+ UserRamCache.addUser(userInfo);
+ }
+ }
+ }
+ return Response.newSuccessResponse("");
+ }
+
+
+ @RequestMapping(value = "/getFaceList", method = RequestMethod.POST)
+ @ResponseBody
+ public Response> getFaceList() {
+ List userList = UserRamCache.getUserList();
+ List resDTOS = new LinkedList<>();
+ for (UserRamCache.UserInfo userInfo : userList) {
+ GetFaceListResDTO face = new GetFaceListResDTO();
+ face.setId(userInfo.getFaceId());
+ face.setName(userInfo.getName());
+ face.setUrl("/images/" + face.getId() + ".jpg");
+ resDTOS.add(face);
+ }
+ return Response.newSuccessResponse(resDTOS);
+ }
+
+
+// @RequestMapping(value = "/recognition", method = RequestMethod.POST)
+// @ResponseBody
+// public R recognition(@RequestParam("file") MultipartFile file) {
+// if (file.isEmpty() || file.getSize() == 0) {
+// return R.error("文件不能为空");
+// }
+//// List faceRecognitionResDTOList = Lists.newLinkedList();
+// FaceRecognitionResDTO faceRecognitionResDTO = null;
+// try{
+// byte[] bytes = file.getBytes();
+// ImageInfo rgbData = ImageFactory.getRGBData(bytes);
+// List faceInfoList = faceEngineService.detectFaces(rgbData);
+// if (CollectionUtil.isNotEmpty(faceInfoList)) {
+// FaceInfo faceInfo = faceInfoList.get(0);
+// faceRecognitionResDTO = new FaceRecognitionResDTO();
+//// faceRecognitionResDTO.setRect(faceInfo.getRect());
+// byte[] feature = faceEngineService.extractFaceFeature(rgbData, faceInfo,ExtractType.RECOGNIZE);
+// if (feature != null) {
+// List userCompareInfos = faceEngineService.faceRecognition(feature, UserRamCache.getUserList(), 0.8f);
+// if (CollectionUtil.isNotEmpty(userCompareInfos)) {
+// faceRecognitionResDTO.setName(userCompareInfos.get(0).getName());
+// faceRecognitionResDTO.setSimilar(userCompareInfos.get(0).getSimilar());
+// }
+// }
+// }else{
+// return R.error("未检测到人脸");
+// }
+// }catch (Exception e){
+// e.printStackTrace();
+// }
+//
+// if (faceRecognitionResDTO == null) {
+// return R.error("陌生人");
+// }
+//
+// return R.ok().put("data",faceRecognitionResDTO);
+// }
+
+
+ /*
+ 人脸识别
+ */
+ @RequestMapping(value = "/faceRecognition", method = RequestMethod.POST)
+ @ResponseBody
+ public Response> faceRecognition(@RequestBody FaceRecognitionReqDTO faceRecognitionReqDTO) {
+ String image = faceRecognitionReqDTO.getImage();
+
+ List faceRecognitionResDTOList = Lists.newLinkedList();
+ byte[] bytes = Base64Util.base64ToBytes(image);
+ ImageInfo rgbData = ImageFactory.getRGBData(bytes);
+ List faceInfoList = faceEngineService.detectFaces(rgbData);
+ if (CollectionUtil.isNotEmpty(faceInfoList)) {
+ for (FaceInfo faceInfo : faceInfoList) {
+ FaceRecognitionResDTO faceRecognitionResDTO = new FaceRecognitionResDTO();
+ faceRecognitionResDTO.setRect(faceInfo.getRect());
+ byte[] feature = faceEngineService.extractFaceFeature(rgbData, faceInfo,ExtractType.RECOGNIZE);
+ if (feature != null) {
+ List userCompareInfos = faceEngineService.faceRecognition(feature, UserRamCache.getUserList(), 0.8f);
+ if (CollectionUtil.isNotEmpty(userCompareInfos)) {
+ faceRecognitionResDTO.setName(userCompareInfos.get(0).getName());
+ faceRecognitionResDTO.setSimilar(userCompareInfos.get(0).getSimilar());
+ }
+ }
+ faceRecognitionResDTOList.add(faceRecognitionResDTO);
+ }
+
+ }
+
+
+ return Response.newSuccessResponse(faceRecognitionResDTOList);
+ }
+
+ @RequestMapping(value = "/detectFaces", method = RequestMethod.POST)
+ @ResponseBody
+ public Response> detectFaces(@RequestBody FaceDetectReqDTO faceDetectReqDTO) {
+ String image = faceDetectReqDTO.getImage();
+ byte[] bytes = Base64Util.base64ToBytes(image);
+ ImageInfo rgbData = ImageFactory.getRGBData(bytes);
+ List faceDetectResDTOS = Lists.newLinkedList();
+ List faceInfoList = faceEngineService.detectFaces(rgbData);
+ if (CollectionUtil.isNotEmpty(faceInfoList)) {
+ List process = faceEngineService.process(rgbData, faceInfoList);
+
+ for (int i = 0; i < faceInfoList.size(); i++) {
+ FaceDetectResDTO faceDetectResDTO = new FaceDetectResDTO();
+ FaceInfo faceInfo = faceInfoList.get(i);
+ faceDetectResDTO.setRect(faceInfo.getRect());
+ faceDetectResDTO.setOrient(faceInfo.getOrient());
+ faceDetectResDTO.setFaceId(faceInfo.getFaceId());
+ if (CollectionUtil.isNotEmpty(process)) {
+ ProcessInfo processInfo = process.get(i);
+ faceDetectResDTO.setAge(processInfo.getAge());
+ faceDetectResDTO.setGender(processInfo.getGender());
+ faceDetectResDTO.setLiveness(processInfo.getLiveness());
+
+ }
+ faceDetectResDTOS.add(faceDetectResDTO);
+
+ }
+ }
+
+ return Response.newSuccessResponse(faceDetectResDTOS);
+ }
+
+ @RequestMapping(value = "/compareFaces", method = RequestMethod.POST)
+ @ResponseBody
+ public Response compareFaces(@RequestBody CompareFacesReqDTO compareFacesReqDTO) {
+
+ String image1 = compareFacesReqDTO.getImage1();
+ String image2 = compareFacesReqDTO.getImage2();
+
+ byte[] bytes1 = Base64Util.base64ToBytes(image1);
+ byte[] bytes2 = Base64Util.base64ToBytes(image2);
+ ImageInfo rgbData1 = ImageFactory.getRGBData(bytes1);
+ ImageInfo rgbData2 = ImageFactory.getRGBData(bytes2);
+
+ Float similar = faceEngineService.compareFace(rgbData1, rgbData2);
+
+ return Response.newSuccessResponse(similar);
+ }
+
+
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/httpapi/controler/HttpApiController.java b/shapelight-admin/src/main/java/net/shapelight/modules/httpapi/controler/HttpApiController.java
index 73a905e..4a8c9ac 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/httpapi/controler/HttpApiController.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/httpapi/controler/HttpApiController.java
@@ -1,9 +1,14 @@
package net.shapelight.modules.httpapi.controler;
+import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
+import com.arcsoft.face.FaceInfo;
+import com.arcsoft.face.enums.ExtractType;
+import com.arcsoft.face.toolkit.ImageFactory;
+import com.arcsoft.face.toolkit.ImageInfo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.minio.MinioClient;
import io.minio.PutObjectOptions;
@@ -18,7 +23,12 @@ import net.shapelight.common.config.MinioUtils;
import net.shapelight.common.utils.*;
import net.shapelight.modules.app.entity.AppUserEntity;
import net.shapelight.modules.app.service.AppUserService;
+import net.shapelight.modules.face.dto.FaceRecognitionResDTO;
+import net.shapelight.modules.face.entity.UserCompareInfo;
+import net.shapelight.modules.face.service.FaceEngineService;
+import net.shapelight.modules.face.util.UserRamCache;
import net.shapelight.modules.httpapi.service.AuthService;
+import net.shapelight.modules.httpapi.service.RecordSaveSyncService;
import net.shapelight.modules.nettyapi.config.CmdConstant;
import net.shapelight.modules.nettyapi.config.MyMessage;
import net.shapelight.modules.nettyapi.utils.Result;
@@ -28,14 +38,12 @@ import net.shapelight.modules.ten.entity.*;
import net.shapelight.modules.ten.service.*;
import net.shapelight.modules.vo.*;
import org.apache.commons.io.FilenameUtils;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
+import java.io.*;
import java.util.*;
@@ -96,6 +104,10 @@ public class HttpApiController {
private TenCheckService tenCheckService;
@Autowired
private SysUserService sysUserService;
+ @Autowired
+ private FaceEngineService faceEngineService;
+ @Autowired
+ private RecordSaveSyncService recordSaveSyncService;
/**
*
@@ -1433,270 +1445,568 @@ public class HttpApiController {
-
-// @PostMapping("/addPersonV2")
-// @ApiOperation("设备添加人员")
+// @PostMapping("/updatePerson")
+// @ApiOperation("设备修改人员")
// @ApiImplicitParams({
// @ApiImplicitParam(name = "dev_id", value = "sn", paramType = "query", dataType = "String", required = true),
// @ApiImplicitParam(name = "appKey", value = "appkey", paramType = "query", dataType = "String", required = true),
// @ApiImplicitParam(name = "timestamp", value = "timestamp", paramType = "query", dataType = "String", required = true),
// @ApiImplicitParam(name = "sign", value = "sign", paramType = "query", dataType = "String", required = true),
// })
-// public R addPersonV2(@RequestBody JSONObject jsonContent) {
+// public R updatePerson(@RequestParam("jsonString") String jsonString, @RequestParam(value = "orgImage",required = false) MultipartFile orgImage, @RequestParam(value = "sourceFile",required = false) MultipartFile sourceFile,@RequestParam("thdFeature") String thdFeature) {
+// JSONObject jsonContent = JSONObject.parseObject(jsonString);
// String sn = jsonContent.getString("dev_id");
// String appKey = jsonContent.getString("appKey");
// String timestamp = jsonContent.getString("timestamp");
// String sign = jsonContent.getString("sign");
-// //鉴权
-// R res = authService.auth(sn,appKey,timestamp,sign);
-// if((Integer) res.get("code") != 0){
-// return res;
+
+
+ @PostMapping("/recognition")
+ public R recognition(@RequestParam("jsonString") String jsonString, @RequestParam(value = "faceFile",required = false) MultipartFile faceFile, @RequestParam(value = "idFile",required = false) MultipartFile idFile) {
+ JSONObject jsonContent = JSONObject.parseObject(jsonString);
+ String sn = jsonContent.getString("dev_id");
+ String appKey = jsonContent.getString("appKey");
+ String timestamp = jsonContent.getString("timestamp");
+ String sign = jsonContent.getString("sign");
+ //鉴权
+ R res = authService.auth(sn,appKey,timestamp,sign);
+ if((Integer) res.get("code") != 0){
+ return res;
+ }
+ log.debug("设备端识别人员开始---------------------------------------------:"+sn);
+// if (faceFile.isEmpty() || faceFile.getSize() == 0) {
+// return R.error("文件不能为空");
// }
-// log.debug("设备端添加人员:"+sn);
-// TenDeviceEntity deviceEntity = tenDeviceService.findBySn(sn);
-////----------------------------------------以下业务-----------------------------------------------------
-// JSONObject personJson = jsonContent.getJSONObject("data");
-//// tenPerson.setCellId(personJson.getLong("cellId"));
-//// tenPerson.setRoomId(personJson.getLong("roomId"));
-//// tenPerson.setPersonType(personJson.getInteger("personType"));
-//// tenPerson.setName(personJson.getString("name"));
-//// tenPerson.setMobile(personJson.getString("mobile"));
-//// tenPerson.setIdCard(personJson.getString("idCard"));
-//// tenPerson.setGender(personJson.getInteger("gender"));
-//
-// TenPersonEntity tenPerson = JSONObject.toJavaObject(personJson,TenPersonEntity.class);
-//
-//// tenPerson.setThdFeature(thdFeature);
-//
-// //------------------------获取掌静脉数据---------------------------
-//// String pvLeft = jsonContent.getString("pvLeft");
-//// String pvRight = jsonContent.getString("pvRight");
-//// Integer featureType = jsonContent.getInteger("featureType");
-//
-// if(tenPerson.getIdCard()!=null){
-// if(tenPerson.getIdCard().length() == 15){
-// String id18 = Convert.toEighteen(tenPerson.getIdCard());
-// tenPerson.setIdCard(id18);
-// }
-// }
-//
-//// TenPersonEntity tenPersonEntity = tenPersonService.findByName(tenPerson.getName(),
-//// tenPerson.getRoomId(),tenPerson.getCellId());
-//// if(tenPersonEntity!=null){
-//// return R.error("姓名在此组织已存在");
-//// }
-//
-//
-//// if(tenPerson.getIdCard()!=null){
-//// TenPersonEntity tenPersonIdcard = tenPersonService.findByIdCard(tenPerson.getIdCard(),
-//// tenPerson.getRoomId(),tenPerson.getCellId());
-//// if(tenPersonIdcard!=null){
-//// return R.error("身份证在此组织已存在");
-//// }
-//// }
-//
-// if(tenPerson.getDeptId()!=null){
-// int c = tenPersonService.checkByIdCardDept(tenPerson.getIdCard(),tenPerson.getDeptId());
-// if(c>0){
-// return R.error("身份证在组织已存在");
-// }
-// }else{
-// int p = tenPersonService.checkByIdCardCell(tenPerson.getIdCard(),deviceEntity.getCellId());
-// if(p>0){
-// return R.error("身份证在小区已存在");
-// }
-// }
-//
-//// if(tenPerson.getPersonType()!=Constant.PERSON_TYPE_PROPERTY){
-//// int c = tenPersonService.checkByIdCardDept(tenPerson.getIdCard(),tenPerson.getDeptId());
-//// if(c>0){
-//// return R.error("身份证在组织已存在");
-//// }
-//// }else{
-//// int p = tenPersonService.checkByIdCardCell(tenPerson.getIdCard(),deviceEntity.getCellId());
-//// if(p>0){
-//// return R.error("身份证在小区已存在");
-//// }
-//// }
-//
-// if (tenPerson.getRoomId()!=null) {
-// TenRoomEntity roomEntity = tenRoomService.getById(tenPerson.getRoomId(),tenPerson.getCellId());
-// if(roomEntity!=null){
-// tenPerson.setBuildId(roomEntity.getBuildId());
-// }
-// }
-//
-// Date now = new Date();
+ String idCard = jsonContent.getString("idCard");
+ String icCard = jsonContent.getString("icCard");
+ String name = jsonContent.getString("name");
+
+ Date now = new Date();
+
+ //1. 先判断是否有人脸,没有人脸直接判断卡号
+ if(faceFile!=null){
+ //1. 先通过人脸识别
+ FaceRecognitionResDTO faceRecognitionResDTO = null;
+ try{
+ byte[] bytes = faceFile.getBytes();
+ ImageInfo rgbData = ImageFactory.getRGBData(bytes);
+ List faceInfoList = faceEngineService.detectFaces(rgbData);
+ if (CollectionUtil.isNotEmpty(faceInfoList)) {
+ FaceInfo faceInfo = faceInfoList.get(0);
+// faceRecognitionResDTO.setRect(faceInfo.getRect());
+ byte[] feature = faceEngineService.extractFaceFeature(rgbData, faceInfo, ExtractType.RECOGNIZE);
+ if (feature != null) {
+ List userCompareInfos = faceEngineService.faceRecognition(feature, UserRamCache.getUserList(), 0.8f);
+ if (CollectionUtil.isNotEmpty(userCompareInfos)) {
+ faceRecognitionResDTO = new FaceRecognitionResDTO();
+ faceRecognitionResDTO.setPersonId(userCompareInfos.get(0).getFaceId());
+ faceRecognitionResDTO.setName(userCompareInfos.get(0).getName());
+ faceRecognitionResDTO.setSimilar(userCompareInfos.get(0).getSimilar());
+ }
+ }
+ }
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+
+ // 人脸识别失败或者分数低
+ if (faceRecognitionResDTO == null || faceRecognitionResDTO.getSimilar() < Float.parseFloat(globalValue.getRecFaceThd())) {
+ // 2. 身份证比对
+ if(idCard!=null && idFile!=null){
+ try{
+ byte[] bytesFace = faceFile.getBytes();
+ ImageInfo imageFace = ImageFactory.getRGBData(bytesFace);
+ byte[] bytesId = idFile.getBytes();
+ ImageInfo imageId = ImageFactory.getRGBData(bytesId);
+ Float score = faceEngineService.compareFace(imageId,imageFace);
+ if(score > Float.parseFloat(globalValue.getRecIdThd())){
+ //身份证比对成功,访客
+ //----------------------------------------以下业务-----------------------------------------------------
+ log.debug("身份证人脸识别成功保存识别记录:"+sn);
+ TenDeviceEntity deviceEntity = tenDeviceService.findBySn(sn);
+
+ TenRecordEntity record = new TenRecordEntity();
+ record.setDeviceSn(sn);
+ record.setDeviceName(deviceEntity.getName());
+ record.setCellId(deviceEntity.getCellId());
+ record.setPersonId(0l);
+ //['刷卡', '刷脸', '密码', '远程', '二维码','指纹','掌静脉','身份证']
+ //1,2,3,4,5,6,7
+ record.setOpenType(8);
+ record.setRecordTime(now);
+ record.setTenantId(deviceEntity.getTenantId());
+
+ String scoreString = String.format("%.2f", score);
+ record.setScore(Float.parseFloat(scoreString));
+ record.setIdCard(idCard);
+ record.setName(name);
+
+ try {
+ //保存图片
+ String dirDate = DateUtils.format(new Date(),DateUtils.DATE_YEAR_MONTH);
+ if (faceFile !=null && !faceFile.isEmpty() && faceFile.getSize() > 0) {
+ String userFileUrl = globalValue.getImagesDir() + "/record/" +
+ dirDate + "/";
+ String fileName = userFileUrl + UUIDUtil.uuid() + ".jpg";
+ InputStream inputStream = faceFile.getInputStream();
+ PutObjectOptions putObjectOptions = new PutObjectOptions(inputStream.available(), -1);
+ putObjectOptions.setContentType(faceFile.getContentType());
+ minioClient.putObject(
+ minioConfig.getBucketName(), fileName, inputStream, putObjectOptions);
+ inputStream.close();
+ record.setRecordFace(fileName);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ log.error("保存照片失败。。。。。。。。。。。。。。。。。。。。。");
+ }
+
+ try {
+ //保存图片
+ String dirDate = DateUtils.format(new Date(),DateUtils.DATE_YEAR_MONTH);
+ if (idFile !=null && !idFile.isEmpty() && idFile.getSize() > 0) {
+ String userFileUrl = globalValue.getImagesDir() + "/record/" +
+ dirDate + "/";
+ String fileName = userFileUrl + UUIDUtil.uuid() + ".jpg";
+ InputStream inputStream = idFile.getInputStream();
+ PutObjectOptions putObjectOptions = new PutObjectOptions(inputStream.available(), -1);
+ putObjectOptions.setContentType(idFile.getContentType());
+ minioClient.putObject(
+ minioConfig.getBucketName(), fileName, inputStream, putObjectOptions);
+ inputStream.close();
+ record.setDepth(fileName);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ log.error("保存照片失败。。。。。。。。。。。。。。。。。。。。。");
+ }
+
+// tenRecordService.saveServer(record);
+ recordSaveSyncService.offerQueue(record);
+ faceRecognitionResDTO = new FaceRecognitionResDTO();
+ faceRecognitionResDTO.setName(name);
+ faceRecognitionResDTO.setSimilar(score);
+
+ log.debug("身份证比对成功---------------------------------------------:"+sn);
+ return R.ok("身份证比对成功").put("data",faceRecognitionResDTO);
+ }else{
+ //身份证比对失败
+ return R.error("陌生人,禁止通行");
+ }
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ }else{
+ return R.error("陌生人,禁止通行");
+ }
+ }else{
+ //人脸识别成功,
+ TenPersonEntity tenPersonEntity = tenPersonService.getByIdWithDelete(Long.parseLong(faceRecognitionResDTO.getPersonId()));
+
+ //----------------------------------------以下业务-----------------------------------------------------
+ log.debug("人脸识别成功:"+sn);
+ TenDeviceEntity deviceEntity = tenDeviceService.findBySn(sn);
+ boolean passFlag = false;
+ if(tenPersonEntity.getPersonType() == Constant.PERSON_TYPE_GUEST){
+ //访客,直接判断有效期
+ if(now.getTime() >= tenPersonEntity.getLiveStart().getTime() && now.getTime() <= tenPersonEntity.getLiveEnd().getTime()){
+
+ }else{
+ //不在时间段内
+ return R.error("不在有效期,禁止通行");
+ }
+ }else{
+ //其他人员,判断标签配置的通行时间段
+ //判断通行时间段
+ List labelList = tenDeviceService.findLabelList(deviceEntity.getDeviceId());
+ boolean hasLabel = false;
+ if (labelList.size()>0) {
+ TenLabelEntity personLabel = tenLabelService.getById(tenPersonEntity.getLabelId());
+ for(TenLabelEntity labelEntity: labelList){
+ if(labelEntity.getLabelId().intValue() == personLabel.getLabelId().intValue()){
+ hasLabel = true;
+ break;
+ }
+ }
+ if(hasLabel){
+ boolean isInTime1 = false;
+ if(personLabel.getOpenPeriod1()!=null && personLabel.getOpenPeriod1().length()>0){
+ isInTime1 = TimeUtils.isIn(personLabel.getOpenPeriod1());
+ }
+
+ boolean isInTime2 = false;
+ if(personLabel.getOpenPeriod2()!=null && personLabel.getOpenPeriod2().length()>0){
+ isInTime2 = TimeUtils.isIn(personLabel.getOpenPeriod2());
+ }
+
+ boolean isInTime3 = false;
+ if(personLabel.getOpenPeriod3()!=null && personLabel.getOpenPeriod3().length()>0){
+ isInTime2 = TimeUtils.isIn(personLabel.getOpenPeriod3());
+ }
+
+ if (isInTime1 || isInTime2 || isInTime3) {
+
+ }else{
+ //不在时间段内
+ return R.error("不在通行时间段内,禁止通行");
+ }
+
+ }else {
+ //未绑定人员标签,禁止通行
+ return R.error("设备未绑定人员标签,禁止通行");
+ }
+ }else{
+ //未绑定标签,禁止通行
+ return R.error("设备未绑定标签,禁止通行");
+ }
+ }
+
+ //在时间段内,通行
+ TenRecordEntity record = new TenRecordEntity();
+ record.setDeviceSn(sn);
+ record.setDeviceName(deviceEntity.getName());
+ record.setCellId(deviceEntity.getCellId());
+ record.setPersonId(tenPersonEntity.getPersonId());
+ //['刷卡', '刷脸', '密码', '远程', '二维码','指纹','掌静脉']
+ //1,2,3,4,5,6,7
+ record.setOpenType(2);
+ record.setRecordTime(now);
+ record.setTenantId(deviceEntity.getTenantId());
+
+
+ String scoreString = String.format("%.2f", faceRecognitionResDTO.getSimilar());
+ record.setScore(Float.parseFloat(scoreString));
+// record.setScore(faceRecognitionResDTO.getSimilar());
+ record.setIdCard(tenPersonEntity.getIdCard());
+ record.setName(tenPersonEntity.getName());
+
+ try {
+ //保存图片
+ String dirDate = DateUtils.format(new Date(),DateUtils.DATE_YEAR_MONTH);
+ if (faceFile !=null && !faceFile.isEmpty() && faceFile.getSize() > 0) {
+ String userFileUrl = globalValue.getImagesDir() + "/record/" +
+ dirDate + "/";
+ String fileName = userFileUrl + UUIDUtil.uuid() + ".jpg";
+ InputStream inputStream = faceFile.getInputStream();
+ PutObjectOptions putObjectOptions = new PutObjectOptions(inputStream.available(), -1);
+ putObjectOptions.setContentType(faceFile.getContentType());
+ minioClient.putObject(
+ minioConfig.getBucketName(), fileName, inputStream, putObjectOptions);
+ inputStream.close();
+ record.setRecordFace(fileName);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ log.error("保存照片失败。。。。。。。。。。。。。。。。。。。。。");
+ }
+// tenRecordService.saveServer(record);
+ recordSaveSyncService.offerQueue(record);
+ log.debug("保存记录成功---------------------------------------------:"+sn);
+ return R.ok("人脸比对成功").put("data",faceRecognitionResDTO);
+ }
+ }else{
+ if(icCard !=null && icCard.length()>0){
+ TenDeviceEntity deviceEntity = tenDeviceService.findBySn(sn);
+ TenPersonEntity tenPersonEntity = tenPersonService.findByIcCardTop(icCard,deviceEntity.getTenantId()+"");
+ if(tenPersonEntity!=null){
+
+ //----------------------------------------以下业务-----------------------------------------------------
+ //判断通行时间段
+ List labelList = tenDeviceService.findLabelList(deviceEntity.getDeviceId());
+ boolean hasLabel = false;
+ if (labelList.size()>0) {
+ TenLabelEntity personLabel = tenLabelService.getById(tenPersonEntity.getLabelId());
+ for(TenLabelEntity labelEntity: labelList){
+ if(labelEntity.getLabelId().intValue() == personLabel.getLabelId().intValue()){
+ hasLabel = true;
+ break;
+ }
+ }
+ if(hasLabel){
+ boolean isInTime1 = false;
+ if(personLabel.getOpenPeriod1()!=null && personLabel.getOpenPeriod1().length()>0){
+ isInTime1 = TimeUtils.isIn(personLabel.getOpenPeriod1());
+ }
+
+ boolean isInTime2 = false;
+ if(personLabel.getOpenPeriod2()!=null && personLabel.getOpenPeriod2().length()>0){
+ isInTime2 = TimeUtils.isIn(personLabel.getOpenPeriod2());
+ }
+
+ boolean isInTime3 = false;
+ if(personLabel.getOpenPeriod3()!=null && personLabel.getOpenPeriod3().length()>0){
+ isInTime2 = TimeUtils.isIn(personLabel.getOpenPeriod3());
+ }
+ if (isInTime1 || isInTime2 || isInTime3) {
+ log.debug("刷卡成功保存识别记录:"+sn);
+ TenRecordEntity record = new TenRecordEntity();
+ record.setDeviceSn(sn);
+ record.setDeviceName(deviceEntity.getName());
+ record.setCellId(deviceEntity.getCellId());
+ record.setPersonId(tenPersonEntity.getPersonId());
+ //['刷卡', '刷脸', '密码', '远程', '二维码','指纹','掌静脉']
+ //1,2,3,4,5,6,7
+ record.setOpenType(1);
+ record.setRecordTime(now);
+ record.setTenantId(deviceEntity.getTenantId());
+
+ record.setIdCard(tenPersonEntity.getIdCard());
+ record.setName(tenPersonEntity.getName());
+ record.setScore(1.0f);
+
+// tenRecordService.saveServer(record);
+ recordSaveSyncService.offerQueue(record);
+ FaceRecognitionResDTO idRes= new FaceRecognitionResDTO();
+ idRes.setName(tenPersonEntity.getName());
+ idRes.setSimilar(1.0f);
+ log.debug("卡号比对成功---------------------------------------------:"+sn);
+ return R.ok("卡号比对成功").put("data",idRes);
+
+ }else{
+ //不在时间段内
+ return R.error("不在通行时间段内,禁止通行");
+ }
+ }else {
+ //未绑定人员标签,禁止通行
+ return R.error("设备未绑定人员标签,禁止通行");
+ }
+ }else{
+ //未绑定标签,禁止通行
+ return R.error("设备未绑定标签,禁止通行");
+ }
+ }else{
+ //卡号未录入,没有身份证
+ return R.error("陌生人,禁止通行");
+ }
+ }else{
+ //没有卡号,没有身份证,人脸比对失败
+ return R.error("陌生人,禁止通行");
+ }
+ }
+ return R.error("陌生人,禁止通行");
+ }
+
+
+
+ @PostMapping("/updatePersonByIdCard")
+ @ApiOperation("设备修改人员")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "dev_id", value = "sn", paramType = "query", dataType = "String", required = true),
+ @ApiImplicitParam(name = "appKey", value = "appkey", paramType = "query", dataType = "String", required = true),
+ @ApiImplicitParam(name = "timestamp", value = "timestamp", paramType = "query", dataType = "String", required = true),
+ @ApiImplicitParam(name = "sign", value = "sign", paramType = "query", dataType = "String", required = true),
+ })
+ public R updatePersonByIdCard(@RequestParam("jsonString") String jsonString, @RequestParam(value = "orgImage",required = false) MultipartFile orgImage) {
+ JSONObject jsonContent = JSONObject.parseObject(jsonString);
+ String sn = jsonContent.getString("dev_id");
+ String appKey = jsonContent.getString("appKey");
+ String timestamp = jsonContent.getString("timestamp");
+ String sign = jsonContent.getString("sign");
+ //鉴权
+ R res = authService.auth(sn,appKey,timestamp,sign);
+ if((Integer) res.get("code") != 0){
+ return res;
+ }
+ log.debug("设备端注册修改人员:"+sn);
+
+ String feature = null;
+ //-----------------算法检测照片-------------------------------------------------------------
+ try {
+ byte[] bytes = orgImage.getBytes();
+ //-------------------------------------------------------------------------
+ ImageInfo rgbData = ImageFactory.getRGBData(bytes);
+ List faceInfoList = faceEngineService.detectFaces(rgbData);
+ if (CollectionUtil.isNotEmpty(faceInfoList)) {
+ FaceInfo faceInfo = faceInfoList.get(0);
+ FaceRecognitionResDTO faceRecognitionResDTO = new FaceRecognitionResDTO();
+ faceRecognitionResDTO.setRect(faceInfo.getRect());
+ byte[] featureBytes = faceEngineService.extractFaceFeature(rgbData, faceInfo, ExtractType.REGISTER);
+ if (featureBytes != null) {
+ feature = Base64.getEncoder().encodeToString(featureBytes);
+ }else{
+ return R.error("图片不合格,未检测到人脸");
+ }
+ }else{
+ return R.error("图片不合格,未检测到人脸");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ TenDeviceEntity deviceEntity = tenDeviceService.findBySn(sn);
+//----------------------------------------以下业务-----------------------------------------------------
+ JSONObject personJson = jsonContent.getJSONObject("data");
+ /**
+ * "data": {
+ * "personType": 5001,
+ * "name": "13",
+ * "mobile": "15895458456",
+ * "idCard": "610113200102020013",
+ * "gender": 1,
+ * "liveEnd": "2023-07-19 22:00:00",
+ * "liveStart": "2023-07-19 00:00:00",
+ * "deptId": 38
+ * }
+ */
+ TenPersonEntity tenPersonJson = JSONObject.toJavaObject(personJson,TenPersonEntity.class);
+
+ List personEntityList = tenPersonService.findByIdCardList(tenPersonJson.getIdCard(),deviceEntity.getTenantId()+"");
+ TenPersonEntity personEntity = null;
+ if(personEntityList.size()>0){
+ //如果人员查询到,取第一个
+ if(tenPersonJson.getPersonType().intValue() == Constant.PERSON_TYPE_GUEST){
+ return R.error("已是常驻人员");
+ }
+ personEntity = personEntityList.get(0);
+
+ }else{
+ personEntity = new TenPersonEntity();
+ }
+
+ personEntity.setFeature(feature);
+ personEntity.setIdCard(tenPersonJson.getIdCard());
+ personEntity.setGender(tenPersonJson.getGender());
+ personEntity.setName(tenPersonJson.getName());
+ personEntity.setDeptId(tenPersonJson.getDeptId());
+
+
+ Date now = new Date();
// long id = new SnowflakeIdWorker().nextId();
-// tenPerson.setPersonId(id);
+// personEntity.setPersonId(id);
// tenPerson.setUuid(UUIDUtil.uuid());
-// tenPerson.setTenantId(deviceEntity.getTenantId());
-// tenPerson.setCreateBy(sn);
-// tenPerson.setRegisterType(Constant.RESGISTER_TYPE_Device);
-// tenPerson.setStatus(Constant.PESON_SUATUS_NOMOR);
-// tenPerson.setCreateTime(now);
-// tenPerson.setLastUpdateTime(now);
-//
-// tenPerson.setCellId(deviceEntity.getCellId());
-//
-//
-// String orgImageBase64 = personJson.getString("orgImageBase64");
-// if(orgImageBase64!=null && orgImageBase64.length()>0){
-// try {
-// //保存原始图片
-// String userFileUrl = globalValue.getImagesDir() + "/" +
-// tenPerson.getCellId().toString() + "/" +
-// tenPerson.getPersonId().toString() + "/";
-// String orgImageFileName = userFileUrl + "o_" + UUIDUtil.uuid() + ".jpg";
-//
-// byte[] b = Base64.getDecoder().decode(orgImageBase64.replace("\n",""));
-// InputStream inputStream = new ByteArrayInputStream(b);
-// PutObjectOptions putObjectOptions = new PutObjectOptions(inputStream.available(), -1);
-// putObjectOptions.setContentType("image/jpeg");
-// minioClient.putObject(
-// minioConfig.getBucketName(), orgImageFileName, inputStream, putObjectOptions);
-// inputStream.close();
-//
-// tenPerson.setOrgImage(orgImageFileName);
-// tenPerson.setFaceImage(orgImageFileName);
-//
-// } catch (Exception e) {
-// return R.error(e.getMessage());
-// }
-// }
-//
-// //处理类型:
-// //1. 不是固定类型,给一个默认的家属类型
-// if(tenPerson.getPersonType()>10000){
-// tenPerson.setLabelId(tenPerson.getPersonType());
-// tenPerson.setPersonType(Constant.PERSON_TYPE_MEMBER);//
-// } else if (tenPerson.getPersonType() == Constant.PERSON_TYPE_OWNER
-// || tenPerson.getPersonType() == Constant.PERSON_TYPE_TENANT
-// || tenPerson.getPersonType() == Constant.PERSON_TYPE_MEMBER) {
-// TenLabelEntity labelEntity = tenLabelService.getOne(new QueryWrapper()
-// .eq("type",tenPerson.getPersonType())
-// .eq("tenant_id",deviceEntity.getTenantId()));
-// if(labelEntity!=null){
-// tenPerson.setLabelId(labelEntity.getLabelId().intValue());
-// }
+ personEntity.setTenantId(deviceEntity.getTenantId());
+ personEntity.setCreateBy(sn);
+ personEntity.setRegisterType(Constant.RESGISTER_TYPE_Device);
+ personEntity.setStatus(Constant.PESON_SUATUS_NOMOR);
+ personEntity.setCreateTime(now);
+ personEntity.setLastUpdateTime(now);
+
+ personEntity.setCellId(deviceEntity.getCellId());
+
+// if (orgImage.isEmpty() || orgImage.getSize() == 0 || sourceFile.isEmpty() || sourceFile.getSize() == 0) {
+// return R.error("文件不能为空");
// }
+ if (orgImage!=null && orgImage.getSize() != 0) {
+ try {
+ //保存原始图片
+ String userFileUrl = globalValue.getImagesDir() + "/org/";
+ String orgImageFileName = userFileUrl + "o_" + UUIDUtil.uuid() + ".jpg";
+
+ InputStream inputStream = orgImage.getInputStream();
+ PutObjectOptions putObjectOptions = new PutObjectOptions(inputStream.available(), -1);
+ putObjectOptions.setContentType(orgImage.getContentType());
+ minioClient.putObject(
+ minioConfig.getBucketName(), orgImageFileName, inputStream, putObjectOptions);
+ inputStream.close();
+
+ personEntity.setOrgImage(orgImageFileName);
+ personEntity.setFaceImage(orgImageFileName);
+
+ } catch (Exception e) {
+ return R.error(e.getMessage());
+ }
+ }
+
+ //处理类型:
+ //1. 不是固定类型,给一个默认的家属类型
+ if(tenPersonJson.getPersonType()>10000){
+ personEntity.setLabelId(tenPersonJson.getPersonType());
+ personEntity.setPersonType(Constant.PERSON_TYPE_MEMBER);//
+ } else if (tenPersonJson.getPersonType() == Constant.PERSON_TYPE_OWNER
+ || tenPersonJson.getPersonType() == Constant.PERSON_TYPE_TENANT
+ || tenPersonJson.getPersonType() == Constant.PERSON_TYPE_MEMBER) {
+ TenLabelEntity labelEntity = tenLabelService.getOne(new QueryWrapper()
+ .eq("type",tenPersonJson.getPersonType())
+ .eq("tenant_id",deviceEntity.getTenantId()));
+ if(labelEntity!=null){
+ personEntity.setLabelId(labelEntity.getLabelId().intValue());
+ }
+ } else if (tenPersonJson.getPersonType() == Constant.PERSON_TYPE_GUEST) {
+ personEntity.setPersonType(Constant.PERSON_TYPE_GUEST);
+ personEntity.setLiveStart(tenPersonJson.getLiveStart());
+ personEntity.setLiveEnd(tenPersonJson.getLiveEnd());
+ }
// int resSave = tenPersonService.save3d(tenPerson);
// if (resSave==1) {
// return R.error("添加失败");
// }
-// JSONObject personRes = new JSONObject();
-// personRes.put("uid",tenPerson.getPersonId());
-// personRes.put("last_update_stamp",DateUtils.format(tenPerson.getLastUpdateTime(),DateUtils.DATE_TIME_PATTERN));
-// return R.ok().put("data",personRes);
-//
-// }
+ if(personEntity.getPersonId() == null){
+ //新增
+ long id = new SnowflakeIdWorker().nextId();
+ personEntity.setPersonId(id);
+ personEntity.setUuid(UUIDUtil.uuid());
+ tenPersonService.saveByIdCard(personEntity);
+ }else{
+ //修改
+ tenPersonService.updateByIdCard(personEntity);
+ }
+ //特征保存到内存
+ UserRamCache.removeUser(personEntity.getPersonId()+"");
+ log.debug("内存删除人员:"+personEntity.getPersonId()+" 姓名:"+personEntity.getName());
+ UserRamCache.UserInfo userInfo = new UserCompareInfo();
+ userInfo.setFaceId(personEntity.getPersonId()+"");
+ userInfo.setName(personEntity.getName());
+ userInfo.setFaceFeature(Base64.getDecoder().decode(personEntity.getFeature()));
+ UserRamCache.addUser(userInfo);
+ log.debug("内存增加人员:"+personEntity.getPersonId()+" 姓名:"+personEntity.getName());
+ //--------------------------------------------------------------------------
+ JSONObject personRes = new JSONObject();
+ personRes.put("uid",personEntity.getPersonId());
+ personRes.put("last_update_stamp",DateUtils.format(personEntity.getLastUpdateTime(),DateUtils.DATE_TIME_PATTERN));
+ return R.ok().put("data",personRes);
+ }
-// @PostMapping("/updatePersonV2")
-// @ApiOperation("设备添加人员")
-// @ApiImplicitParams({
-// @ApiImplicitParam(name = "dev_id", value = "sn", paramType = "query", dataType = "String", required = true),
-// @ApiImplicitParam(name = "appKey", value = "appkey", paramType = "query", dataType = "String", required = true),
-// @ApiImplicitParam(name = "timestamp", value = "timestamp", paramType = "query", dataType = "String", required = true),
-// @ApiImplicitParam(name = "sign", value = "sign", paramType = "query", dataType = "String", required = true),
-// })
-// public R updatePersonV2(@RequestBody JSONObject jsonContent) {
-// String sn = jsonContent.getString("dev_id");
-// String appKey = jsonContent.getString("appKey");
-// String timestamp = jsonContent.getString("timestamp");
-// String sign = jsonContent.getString("sign");
-// //鉴权
-// R res = authService.auth(sn,appKey,timestamp,sign);
-// if((Integer) res.get("code") != 0){
-// return res;
-// }
-// log.debug("设备端修改人员:"+sn);
-// TenDeviceEntity deviceEntity = tenDeviceService.findBySn(sn);
-////----------------------------------------以下业务-----------------------------------------------------
-// JSONObject personJson = jsonContent.getJSONObject("data");
-//
-//
-// TenPersonEntity tenPerson = JSONObject.toJavaObject(personJson,TenPersonEntity.class);
-// tenPerson.setPersonId(personJson.getLong("uid"));
-//
-// if(tenPerson.getIdCard()!=null){
-// if(tenPerson.getIdCard().length() == 15){
-// String id18 = Convert.toEighteen(tenPerson.getIdCard());
-// tenPerson.setIdCard(id18);
-// }
-// }
-//
-// if (tenPerson.getRoomId()!=null) {
-// TenRoomEntity roomEntity = tenRoomService.getById(tenPerson.getRoomId(),tenPerson.getCellId());
-// if(roomEntity!=null){
-// tenPerson.setBuildId(roomEntity.getBuildId());
-// }
-// }
-//
-// Date now = new Date();
-//// long id = new SnowflakeIdWorker().nextId();
-//// tenPerson.setPersonId(id);
-//// tenPerson.setUuid(UUIDUtil.uuid());
-// tenPerson.setTenantId(deviceEntity.getTenantId());
-//// tenPerson.setCreateBy(sn);
-//// tenPerson.setRegisterType(Constant.RESGISTER_TYPE_Device);
-// tenPerson.setStatus(Constant.PESON_SUATUS_NOMOR);
-//// tenPerson.setCreateTime(now);
-// tenPerson.setLastUpdateTime(now);
-//
-// tenPerson.setCellId(deviceEntity.getCellId());
-//
-//
-// String orgImageBase64 = personJson.getString("orgImageBase64");
-// if(orgImageBase64!=null && orgImageBase64.length()>0){
-// try {
-// //保存原始图片
-// String userFileUrl = globalValue.getImagesDir() + "/" +
-// tenPerson.getCellId().toString() + "/" +
-// tenPerson.getPersonId().toString() + "/";
-// String orgImageFileName = userFileUrl + "o_" + UUIDUtil.uuid() + ".jpg";
-//
-// byte[] b = Base64.getDecoder().decode(orgImageBase64.replace("\n",""));
-// InputStream inputStream = new ByteArrayInputStream(b);
-// PutObjectOptions putObjectOptions = new PutObjectOptions(inputStream.available(), -1);
-// putObjectOptions.setContentType("image/jpeg");
-// minioClient.putObject(
-// minioConfig.getBucketName(), orgImageFileName, inputStream, putObjectOptions);
-// inputStream.close();
-//
-// tenPerson.setOrgImage(orgImageFileName);
-// tenPerson.setFaceImage(orgImageFileName);
-//
-// } catch (Exception e) {
-// return R.error(e.getMessage());
-// }
-// }
-//
-// //处理类型:
-// //1. 不是固定类型,给一个默认的家属类型
-// if(tenPerson.getPersonType()>10000){
-// tenPerson.setLabelId(tenPerson.getPersonType());
-// tenPerson.setPersonType(Constant.PERSON_TYPE_MEMBER);//
-// } else if (tenPerson.getPersonType() == Constant.PERSON_TYPE_OWNER
-// || tenPerson.getPersonType() == Constant.PERSON_TYPE_TENANT
-// || tenPerson.getPersonType() == Constant.PERSON_TYPE_MEMBER) {
-// TenLabelEntity labelEntity = tenLabelService.getOne(new QueryWrapper()
-// .eq("type",tenPerson.getPersonType())
-// .eq("tenant_id",deviceEntity.getTenantId()));
-// if(labelEntity!=null){
-// tenPerson.setLabelId(labelEntity.getLabelId().intValue());
-// }
-// }
-// int resSave = tenPersonService.update3d(tenPerson);
-// if (resSave==1) {
-// return R.error("添加失败");
-// }
-// JSONObject personRes = new JSONObject();
-// personRes.put("uid",tenPerson.getPersonId());
-// personRes.put("last_update_stamp",DateUtils.format(tenPerson.getLastUpdateTime(),DateUtils.DATE_TIME_PATTERN));
-// return R.ok().put("data",personRes);
-//
-// }
+ /**
+ * 查询住户列表
+ */
+ @PostMapping("/personList")
+ @ApiOperation(value = "查询住户列表", response = TenPersonEntity.class)
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "limit", value = "每页条数", paramType = "query", dataType = "String", required = true),
+ @ApiImplicitParam(name = "page", value = "页码", paramType = "query", dataType = "String", required = true),
+ @ApiImplicitParam(name = "name", value = "姓名", paramType = "query", dataType = "String", required = true),
+ @ApiImplicitParam(name = "gender", value = "性别", paramType = "query", dataType = "String", required = true),
+ @ApiImplicitParam(name = "status", value = "状态", paramType = "query", dataType = "String", required = true),
+ @ApiImplicitParam(name = "mobile", value = "手机号", paramType = "query", dataType = "String", required = true),
+ @ApiImplicitParam(name = "idCard", value = "证件号", paramType = "query", dataType = "String", required = true),
+ @ApiImplicitParam(name = "personType", value = "类型", paramType = "query", dataType = "String", required = true),
+ })
+ public R personList(@RequestParam Map params) {
+ JSONObject jsonContent = JSONObject.parseObject((String)params.get("jsonString"));
+ String sn = jsonContent.getString("dev_id");
+ String appKey = jsonContent.getString("appKey");
+ String timestamp = jsonContent.getString("timestamp");
+ String sign = jsonContent.getString("sign");
+ //鉴权
+ R res = authService.auth(sn,appKey,timestamp,sign);
+ if((Integer) res.get("code") != 0){
+ return res;
+ }
+ TenDeviceEntity deviceEntity = tenDeviceService.findBySn(sn);
+
+ log.debug("设备端注册修改人员:"+sn);
+ String tenantId = deviceEntity.getTenantId() + "";
+ params.put("tenantId", tenantId + "");
+ //小区管理员
+ params.put("cellId", deviceEntity.getCellId().toString());
+ List personTypeList = new ArrayList<>();
+// List tenLabel = tenLabelService.list(new QueryWrapper()
+// .eq("tenant_id",deviceEntity.getTenantId()));
+ personTypeList.add(Constant.PERSON_TYPE_OWNER);
+ personTypeList.add(Constant.PERSON_TYPE_MEMBER);
+ personTypeList.add(Constant.PERSON_TYPE_TENANT);
+ params.put("personTypeList",personTypeList);
+ PageUtils page = tenPersonService.queryPage(params);
+
+ for(TenPersonEntity entity: (List)page.getList()){
+ if(entity.getOrgImage()!=null && entity.getOrgImage().length()>0){
+ entity.setOrgImage(globalValue.getMinioEndpoint()+"/"+globalValue.getMinioBucketName()+"/"+entity.getOrgImage());
+ }
+ }
+
+ return R.ok().put("data", page);
+ }
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/httpapi/service/RecordSaveSyncService.java b/shapelight-admin/src/main/java/net/shapelight/modules/httpapi/service/RecordSaveSyncService.java
new file mode 100644
index 0000000..da81d65
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/httpapi/service/RecordSaveSyncService.java
@@ -0,0 +1,44 @@
+package net.shapelight.modules.httpapi.service;
+
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import net.shapelight.modules.ten.entity.TenRecordEntity;
+import net.shapelight.modules.ten.service.TenRecordService;
+import org.apache.commons.io.FileUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+
+@Component
+@Order(2)
+@Slf4j
+public class RecordSaveSyncService implements ApplicationRunner {
+ @Autowired
+ private TenRecordService tenRecordService;
+
+ private final ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>();
+
+ public void offerQueue(TenRecordEntity frameIndex) {
+ queue.offer(frameIndex);
+ }
+
+
+ @Override
+ public void run(ApplicationArguments args) throws Exception {
+ while (true) {
+ TenRecordEntity record = queue.poll();
+ if (record != null) {
+ log.debug("异步保存识别记录................................");
+ tenRecordService.saveServer(record);
+ }
+ Thread.sleep(100);
+ }
+ }
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/job/task/DeleteRecordTask.java b/shapelight-admin/src/main/java/net/shapelight/modules/job/task/DeleteRecordTask.java
new file mode 100644
index 0000000..f4e93fe
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/job/task/DeleteRecordTask.java
@@ -0,0 +1,62 @@
+package net.shapelight.modules.job.task;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import io.minio.MinioClient;
+import lombok.extern.slf4j.Slf4j;
+import net.shapelight.common.config.GlobalValue;
+import net.shapelight.common.config.MinioConfig;
+import net.shapelight.common.utils.DateUtils;
+import net.shapelight.common.utils.RedisUtils;
+import net.shapelight.modules.sys.entity.SysUserEntity;
+import net.shapelight.modules.sys.service.SysUserService;
+import net.shapelight.modules.ten.entity.TenCellEntity;
+import net.shapelight.modules.ten.entity.TenRecordEntity;
+import net.shapelight.modules.ten.service.TenCellService;
+import net.shapelight.modules.ten.service.TenRecordService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.*;
+
+@Component("deleteRecordTask")
+@Slf4j
+public class DeleteRecordTask implements ITask {
+
+ @Autowired
+ private SysUserService sysUserService;
+ @Autowired
+ private TenCellService tenCellService;
+ @Autowired
+ private TenRecordService tenRecordService;
+ @Autowired
+ private RedisUtils redisUtils;
+ @Autowired
+ private GlobalValue globalValue;
+ @Autowired
+ private MinioClient minioClient;
+ @Autowired
+ private MinioConfig minioConfig;
+
+ @Override
+ public void run(String params){
+ log.debug("执行定时任务开始:删除"+params+"天之前的数据及文件................................");
+
+ List recordList = tenRecordService.getDaysIntervalRecords(params,globalValue.getTenantId());
+ for(TenRecordEntity record: recordList) {
+ try {
+ minioClient.removeObject(minioConfig.getBucketName(), record.getRecordFace());
+ minioClient.removeObject(minioConfig.getBucketName(), record.getDepth());
+ log.debug("删除记录照片:" + record.getRecordFace());
+ } catch (Exception e) {
+ log.error("照片不存在:" + record.getRecordFace());
+ e.printStackTrace();
+ }
+ }
+ tenRecordService.deleteDaysIntervalRecords(params,globalValue.getTenantId());
+ log.debug("批量删除"+params+"天之前的记录数据");
+ log.debug("执行定时任务结束:删除"+params+"天之前的数据及文件................................");
+ }
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/job/task/FaceRestartTask.java b/shapelight-admin/src/main/java/net/shapelight/modules/job/task/FaceRestartTask.java
new file mode 100644
index 0000000..ccdfaf9
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/job/task/FaceRestartTask.java
@@ -0,0 +1,64 @@
+package net.shapelight.modules.job.task;
+
+import io.minio.MinioClient;
+import lombok.extern.slf4j.Slf4j;
+import net.shapelight.common.config.GlobalValue;
+import net.shapelight.common.config.MinioConfig;
+import net.shapelight.common.utils.RedisUtils;
+import net.shapelight.modules.face.entity.UserCompareInfo;
+import net.shapelight.modules.face.service.FaceEngineService;
+import net.shapelight.modules.face.util.Base64Util;
+import net.shapelight.modules.face.util.UserRamCache;
+import net.shapelight.modules.sys.service.SysUserService;
+import net.shapelight.modules.ten.entity.TenPersonEntity;
+import net.shapelight.modules.ten.entity.TenRecordEntity;
+import net.shapelight.modules.ten.service.TenCellService;
+import net.shapelight.modules.ten.service.TenPersonService;
+import net.shapelight.modules.ten.service.TenRecordService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component("faceRestartTask")
+@Slf4j
+public class FaceRestartTask implements ITask {
+
+ @Autowired
+ private FaceEngineService faceEngineService;
+ @Autowired
+ private TenPersonService tenPersonService;
+
+ @Override
+ public void run(String params){
+ log.debug("faceEngin restart .............................................");
+
+ //clear all face
+ UserRamCache.clear();
+
+ int count = tenPersonService.findCount();
+ int pageSize = 1000;
+ int page = count/pageSize;
+ if(count%1000!=0){
+ page = page+1;
+ }
+ int faceCount = 0;
+ for (int i = 0; i < page; i++) {
+ int start = i*1000;
+ List listPage = tenPersonService.listPage(start,1000);
+ for(TenPersonEntity personEntity: listPage){
+ if(personEntity.getFeature()!=null && personEntity.getFeature().length()>0){
+ UserRamCache.UserInfo userInfo = new UserCompareInfo();
+ userInfo.setFaceId(personEntity.getPersonId()+"");
+ userInfo.setName(personEntity.getName());
+ userInfo.setFaceFeature(Base64Util.base64ToBytes(personEntity.getFeature()));
+ //这边注册到内存缓存中
+ UserRamCache.addUser(userInfo);
+ faceCount++;
+ }
+ }
+ }
+ log.debug("初始化人脸库完成,共 "+faceCount+" 人");
+ log.debug("faceEngin restart end.............................................");
+ }
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/job/task/PersonProcessTask.java b/shapelight-admin/src/main/java/net/shapelight/modules/job/task/PersonProcessTask.java
index 93fb643..126f8e4 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/job/task/PersonProcessTask.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/job/task/PersonProcessTask.java
@@ -3,8 +3,11 @@
package net.shapelight.modules.job.task;
import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
import net.shapelight.common.utils.Constant;
import net.shapelight.common.utils.DateUtils;
+import net.shapelight.modules.face.entity.UserCompareInfo;
+import net.shapelight.modules.face.util.UserRamCache;
import net.shapelight.modules.nettyapi.service.ServerApiService;
import net.shapelight.modules.sys.entity.SysDbBakEntity;
import net.shapelight.modules.sys.service.SysDbBakService;
@@ -19,6 +22,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.*;
+import java.util.Base64;
import java.util.Date;
import java.util.List;
@@ -27,6 +31,7 @@ import java.util.List;
*/
@Component("personProcessTask")
@Data
+@Slf4j
public class PersonProcessTask implements ITask {
private Logger logger = LoggerFactory.getLogger(getClass());
@@ -39,22 +44,25 @@ public class PersonProcessTask implements ITask {
@Override
public void run(String params) {
- logger.debug("personProcessTask定时任务正在执行,参数为:{}", params);
+ logger.debug("personProcessTask定时任务正在执行.................................");
//1. 遍历人员表,找出所有过期的访客并设置为过期不可用
List guestList = tenPersonService.getAllExpireGuest();
for (TenPersonEntity guest : guestList) {
guest.setStatus(Constant.PESON_SUATUS_GUEST_DATE_OUT);
//修改人员表
tenPersonService.updateStatusById(guest);
+ //特征保存到内存
+ UserRamCache.removeUser(guest.getPersonId()+"");
+ log.debug("内存删除人员:"+guest.getPersonId()+" 姓名:"+guest.getName());
//修改同步表
- List syncEntityList = tenPersonSyncService.findByPersonId(guest.getPersonId(),guest.getTenantId());
- for(TenPersonSyncEntity syncEntity: syncEntityList){
- syncEntity.setState(Constant.PERSON_SYNC_DELETE);
- tenPersonSyncService.updateById(syncEntity);
- }
+// List syncEntityList = tenPersonSyncService.findByPersonId(guest.getPersonId(),guest.getTenantId());
+// for(TenPersonSyncEntity syncEntity: syncEntityList){
+// syncEntity.setState(Constant.PERSON_SYNC_DELETE);
+// tenPersonSyncService.updateById(syncEntity);
+// }
}
//断开说有设备
- serverApiService.closeAll();
- logger.debug("personProcessTask定时任务执行完毕");
+// serverApiService.closeAll();
+ logger.debug("personProcessTask定时任务执行完毕....................");
}
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/nettyapi/config/StartInit.java b/shapelight-admin/src/main/java/net/shapelight/modules/nettyapi/config/StartInit.java
index fc897b8..2fad6b9 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/nettyapi/config/StartInit.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/nettyapi/config/StartInit.java
@@ -14,7 +14,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
-@WebListener
+//@WebListener
@Slf4j
public class StartInit implements ServletContextListener {
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/sys/controller/SysDeviceAppController.java b/shapelight-admin/src/main/java/net/shapelight/modules/sys/controller/SysDeviceAppController.java
index 0c7419e..f7978a2 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/sys/controller/SysDeviceAppController.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/sys/controller/SysDeviceAppController.java
@@ -11,6 +11,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
+import net.shapelight.common.annotation.SysLog;
import net.shapelight.common.config.GlobalValue;
import net.shapelight.common.config.MinioConfig;
import net.shapelight.common.utils.Constant;
@@ -77,6 +78,7 @@ public class SysDeviceAppController {
/**
* 保存
*/
+ @SysLog("添加设备App")
@ApiOperation(value = "添加")
@PostMapping("/save")
@RequiresPermissions("sys:deviceapp")
@@ -89,6 +91,7 @@ public class SysDeviceAppController {
/**
* 修改
*/
+ @SysLog("修改设备App")
@PostMapping("/update")
@RequiresPermissions("sys:deviceapp")
@ApiOperation(value = "修改")
@@ -101,6 +104,7 @@ public class SysDeviceAppController {
/**
* 删除
*/
+ @SysLog("删除设备App")
@PostMapping("/delete")
@RequiresPermissions("sys:deviceapp")
@ApiOperation(value = "删除")
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/sys/controller/SysDeviceController.java b/shapelight-admin/src/main/java/net/shapelight/modules/sys/controller/SysDeviceController.java
index e6475f0..ad4c891 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/sys/controller/SysDeviceController.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/sys/controller/SysDeviceController.java
@@ -9,6 +9,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
+import net.shapelight.common.annotation.SysLog;
import net.shapelight.common.utils.RedisUtils;
import net.shapelight.common.utils.StringUtils;
import net.shapelight.modules.nettyapi.service.ServerApiService;
@@ -79,6 +80,7 @@ public class SysDeviceController {
/**
* 保存
*/
+ @SysLog("添加设备")
@PostMapping("/save")
@RequiresPermissions("sys:device")
@ApiOperation(value = "保存")
@@ -101,6 +103,7 @@ public class SysDeviceController {
/**
* 修改
*/
+ @SysLog("修改设备")
@PostMapping("/update")
@RequiresPermissions("sys:device")
@ApiOperation(value = "修改")
@@ -114,6 +117,7 @@ public class SysDeviceController {
/**
* 停用
*/
+ @SysLog("停用设备")
@PostMapping("/stop")
@RequiresPermissions("sys:device")
@ApiOperation(value = "修改")
@@ -139,6 +143,7 @@ public class SysDeviceController {
/**
* 删除
*/
+ @SysLog("删除设备")
@PostMapping("/delete")
@RequiresPermissions("sys:device")
@ApiOperation(value = "删除")
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/sys/controller/SysDeviceTypeController.java b/shapelight-admin/src/main/java/net/shapelight/modules/sys/controller/SysDeviceTypeController.java
index 98002b1..2abf40f 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/sys/controller/SysDeviceTypeController.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/sys/controller/SysDeviceTypeController.java
@@ -9,6 +9,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
+import net.shapelight.common.annotation.SysLog;
import net.shapelight.modules.sys.entity.SysDeviceAppEntity;
import net.shapelight.modules.sys.entity.SysDeviceEntity;
import net.shapelight.modules.sys.entity.SysDeviceTypeEntity;
@@ -85,6 +86,7 @@ public class SysDeviceTypeController {
/**
* 保存
*/
+ @SysLog("添加设备类型")
@PostMapping("/save")
@RequiresPermissions("sys:devicetype")
@ApiOperation(value = "保存")
@@ -97,6 +99,7 @@ public class SysDeviceTypeController {
/**
* 修改
*/
+ @SysLog("修改设备类型")
@PostMapping("/update")
@RequiresPermissions("sys:devicetype")
@ApiOperation(value = "修改")
@@ -109,6 +112,7 @@ public class SysDeviceTypeController {
/**
* 删除
*/
+ @SysLog("删除设备类型")
@PostMapping("/delete")
@RequiresPermissions("sys:devicetype")
@ApiOperation(value = "删除")
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenCellController.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenCellController.java
index 65b444e..d682fec 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenCellController.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenCellController.java
@@ -7,6 +7,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
+import net.shapelight.common.annotation.SysLog;
import net.shapelight.common.utils.Constant;
import net.shapelight.common.utils.SnowflakeIdWorker;
import net.shapelight.modules.sys.controller.AbstractController;
@@ -90,6 +91,7 @@ public class TenCellController extends AbstractController {
/**
* 保存
*/
+ @SysLog("添加小区")
@PostMapping("/save")
@ApiOperation("添加小区")
//@RequiresPermissions("ten:cell:save")
@@ -112,6 +114,7 @@ public class TenCellController extends AbstractController {
/**
* 修改
*/
+ @SysLog("修改小区")
@PostMapping("/update")
@ApiOperation("修改小区")
@RequiresPermissions("ten:cell")
@@ -126,6 +129,7 @@ public class TenCellController extends AbstractController {
/**
* 删除
*/
+ @SysLog("删除小区")
@PostMapping("/delete")
@ApiOperation("删除小区")
@RequiresPermissions("ten:cell")
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenCellDeptController.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenCellDeptController.java
index 95060f0..1c58d1e 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenCellDeptController.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenCellDeptController.java
@@ -6,6 +6,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.ApiOperation;
+import net.shapelight.common.annotation.SysLog;
import net.shapelight.common.utils.Constant;
import net.shapelight.common.utils.TreeUtils;
import net.shapelight.modules.sys.controller.AbstractController;
@@ -90,6 +91,7 @@ public class TenCellDeptController extends AbstractController {
/**
* 保存
*/
+ @SysLog("添加组织")
@PostMapping("/save")
@RequiresPermissions("ten:celldept")
public R save(@RequestBody TenCellDeptEntity tenCellDept){
@@ -117,6 +119,7 @@ public class TenCellDeptController extends AbstractController {
/**
* 修改
*/
+ @SysLog("修改组织")
@PostMapping("/update")
@RequiresPermissions("ten:celldept")
public R update(@RequestBody TenCellDeptEntity tenCellDept){
@@ -143,6 +146,7 @@ public class TenCellDeptController extends AbstractController {
/**
* 删除
*/
+ @SysLog("删除组织")
@PostMapping("/delete")
@RequiresPermissions("ten:celldept")
public R delete(@RequestBody Long[] deptIds){
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenDeviceController.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenDeviceController.java
index ea19882..4e710e3 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenDeviceController.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenDeviceController.java
@@ -7,6 +7,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
+import net.shapelight.common.annotation.SysLog;
import net.shapelight.common.utils.*;
//import net.shapelight.modules.dev.mqtt.CmdProcess;
//import net.shapelight.modules.dev.mqtt.EmqHttpApi;
@@ -20,6 +21,7 @@ import net.shapelight.modules.sys.service.SysDeviceAppService;
import net.shapelight.modules.sys.service.SysDeviceService;
import net.shapelight.modules.sys.service.SysDeviceTypeService;
import net.shapelight.modules.sys.service.SysUserRoleService;
+import net.shapelight.modules.ten.entity.TenLabelEntity;
import net.shapelight.modules.ten.entity.TenUserScopeEntity;
import net.shapelight.modules.ten.service.TenCellService;
import net.shapelight.modules.ten.service.TenUserScopeService;
@@ -97,12 +99,15 @@ public class TenDeviceController extends AbstractController {
@ApiOperation(value = "查询设备信息",response = TenDeviceEntity.class)
public R info(@PathVariable("deviceId") Long deviceId){
TenDeviceEntity tenDevice = tenDeviceService.getById(deviceId);
+ List labelList = tenDeviceService.findLabelList(deviceId);
+ tenDevice.setLabelList(labelList);
return R.ok().put("data", tenDevice);
}
/**
* 保存
*/
+ @SysLog("添加设备")
@PostMapping("/save")
// @RequiresPermissions("ten:device:save")
@ApiOperation(value = "添加设备")
@@ -127,6 +132,7 @@ public class TenDeviceController extends AbstractController {
/**
* 修改
*/
+ @SysLog("修改设备")
@PostMapping("/update")
// @RequiresPermissions("ten:device:update")
@ApiOperation(value = "修改设备")
@@ -141,6 +147,7 @@ public class TenDeviceController extends AbstractController {
/**
* 删除
*/
+ @SysLog("删除设备")
@PostMapping("/delete")
// @RequiresPermissions("ten:device:delete")
@ApiOperation(value = "删除设备")
@@ -416,6 +423,7 @@ public class TenDeviceController extends AbstractController {
// }
+ @SysLog("升级设备App")
@PostMapping("/updateApp")
@ApiOperation(value = "升级app版本")
public R updateApp(@RequestBody SysDeviceAppEntity app){
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenLabelController.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenLabelController.java
index 6285d77..d5ddb07 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenLabelController.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenLabelController.java
@@ -11,6 +11,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
+import net.shapelight.common.annotation.SysLog;
import net.shapelight.modules.sys.controller.AbstractController;
import net.shapelight.modules.ten.service.TenPersonService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
@@ -81,6 +82,7 @@ public class TenLabelController extends AbstractController {
/**
* 保存
*/
+ @SysLog("添加人员类型")
@PostMapping("/save")
@RequiresPermissions("ten:label")
@ApiOperation(value = "保存标签")
@@ -103,6 +105,7 @@ public class TenLabelController extends AbstractController {
/**
* 修改
*/
+ @SysLog("修改人员类型")
@PostMapping("/update")
@RequiresPermissions("ten:label")
@ApiOperation(value = "修改标签")
@@ -128,6 +131,7 @@ public class TenLabelController extends AbstractController {
* 删除
*/
+ @SysLog("删除人员类型")
@PostMapping("/delete")
@RequiresPermissions("ten:label")
@ApiOperation(value = "删除标签")
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenPersonController.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenPersonController.java
index d367190..b9f4836 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenPersonController.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenPersonController.java
@@ -13,6 +13,7 @@ import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
+import net.shapelight.common.annotation.SysLog;
import net.shapelight.common.config.GlobalValue;
import net.shapelight.common.config.MinioConfig;
import net.shapelight.common.utils.*;
@@ -24,6 +25,8 @@ import net.shapelight.commons.engine.sdk.palm.OutArg;
import net.shapelight.modules.app.entity.AppUserEntity;
import net.shapelight.modules.app.service.AppUserService;
import net.shapelight.modules.excel.model.PersonModel;
+import net.shapelight.modules.face.entity.UserCompareInfo;
+import net.shapelight.modules.face.util.UserRamCache;
import net.shapelight.modules.nettyapi.service.ServerApiService;
import net.shapelight.modules.sys.controller.AbstractController;
import net.shapelight.modules.sys.entity.SysUserEntity;
@@ -327,6 +330,7 @@ public class TenPersonController extends AbstractController {
/**
* 保存
*/
+ @SysLog("添加人员")
@PostMapping("/save")
@RequiresPermissions("ten:person")
@ApiOperation(value = "保存人员信息")
@@ -409,6 +413,7 @@ public class TenPersonController extends AbstractController {
/**
* 修改
*/
+ @SysLog("修改人员")
@PostMapping("/update")
@RequiresPermissions("ten:person")
@ApiOperation(value = "修改人员信息")
@@ -525,6 +530,7 @@ public class TenPersonController extends AbstractController {
/**
* 修改状态,审核人员 停用禁用
*/
+ @SysLog("修改人员状态")
@PostMapping("/updateStatus")
@RequiresPermissions("ten:person")
@ApiOperation(value = "修改状态")
@@ -533,71 +539,84 @@ public class TenPersonController extends AbstractController {
tenPerson.setLastUpdateBy(getUser().getUsername());
tenPerson.setLastUpdateTime(new Date());
tenPersonService.updateStatusById(tenPerson);
+ //特征保存到内存
+ UserRamCache.removeUser(tenPerson.getPersonId()+"");
+ log.debug("内存删除人员:"+tenPerson.getPersonId()+" 姓名:"+tenPerson.getName());
+ if(tenPerson.getStatus().intValue() == 0){
+ TenPersonEntity entity = tenPersonService.getByIdWithDelete(tenPerson.getPersonId());
+ UserRamCache.UserInfo userInfo = new UserCompareInfo();
+ userInfo.setFaceId(entity.getPersonId()+"");
+ userInfo.setName(entity.getName());
+ userInfo.setFaceFeature(Base64.getDecoder().decode(entity.getFeature()));
+ UserRamCache.addUser(userInfo);
+ log.debug("内存增加人员:"+entity.getPersonId()+" 姓名:"+entity.getName());
+ }
+
//一下推送
//状态为正常时,添加到同步表并推送
- List devList = tenDeviceService.findByCellId(tenPerson.getCellId());
- if(tenPerson.getStatus().intValue() == Constant.PESON_SUATUS_NOMOR){
- //状态是0正常,发送推送
- for (TenDeviceVo dev : devList) {
- //添加到同步表,下发设备通知
- TenPersonSyncEntity syncEntity = tenPersonSyncService.findByDeviceIdAndPersonId(dev.getDeviceId(),tenPerson.getPersonId(),tenPerson.getTenantId());
- if(syncEntity==null){
- syncEntity = new TenPersonSyncEntity();
- syncEntity.setPersonId(tenPerson.getPersonId());
- syncEntity.setTenantId(tenPerson.getTenantId());
- syncEntity.setDeviceSn(dev.getSn());
- syncEntity.setDeviceId(dev.getDeviceId());
- syncEntity.setState(Constant.PERSON_SYNC_ADD);
- syncEntity.setLastUpdateTime(tenPerson.getLastUpdateTime());
- tenPersonSyncService.insert(syncEntity);
-
- //下发通知
- List list = new ArrayList<>();
- TenPersonOperationVo vo = new TenPersonOperationVo();
- vo.setUid(syncEntity.getPersonId());
- vo.setOperation(Constant.PERSON_SYNC_ADD);
- vo.setLast_update_stamp(syncEntity.getLastUpdateTime());
- list.add(vo);
- serverApiService.personOperation(dev.getSn(),list);
- }else{
- syncEntity.setState(Constant.PERSON_SYNC_MODIFY);
- syncEntity.setLastUpdateTime(tenPerson.getLastUpdateTime());
- tenPersonSyncService.updateById(syncEntity);
-
- //下发通知
- List list = new ArrayList<>();
- TenPersonOperationVo vo = new TenPersonOperationVo();
- vo.setUid(syncEntity.getPersonId());
- vo.setOperation(Constant.PERSON_SYNC_MODIFY);
- vo.setLast_update_stamp(syncEntity.getLastUpdateTime());
- list.add(vo);
- serverApiService.personOperation(dev.getSn(),list);
- }
- }
- }
- //状态为其他时,删除同步表中的数据,并推送
- else{
- for (TenDeviceVo dev : devList) {
- //添加到同步表,下发设备通知
- TenPersonSyncEntity syncEntity = tenPersonSyncService.findByDeviceIdAndPersonId(dev.getDeviceId(),tenPerson.getPersonId(),tenPerson.getTenantId());
- if(syncEntity!=null){
- syncEntity.setState(Constant.PERSON_SYNC_DELETE);
- syncEntity.setLastUpdateTime(tenPerson.getLastUpdateTime());
- tenPersonSyncService.updateById(syncEntity);
- //下发通知
- List list = new ArrayList<>();
- TenPersonOperationVo vo = new TenPersonOperationVo();
- vo.setUid(syncEntity.getPersonId());
- vo.setOperation(Constant.PERSON_SYNC_DELETE);
- vo.setLast_update_stamp(syncEntity.getLastUpdateTime());
- list.add(vo);
- int flag = serverApiService.personOperation(dev.getSn(),list);
- if(flag!= -1){
- tenPersonSyncService.removeByPersonSyncId(syncEntity.getPersonSyncId(),syncEntity.getTenantId());
- }
- }
- }
- }
+// List devList = tenDeviceService.findByCellId(tenPerson.getCellId());
+// if(tenPerson.getStatus().intValue() == Constant.PESON_SUATUS_NOMOR){
+// //状态是0正常,发送推送
+// for (TenDeviceVo dev : devList) {
+// //添加到同步表,下发设备通知
+// TenPersonSyncEntity syncEntity = tenPersonSyncService.findByDeviceIdAndPersonId(dev.getDeviceId(),tenPerson.getPersonId(),tenPerson.getTenantId());
+// if(syncEntity==null){
+// syncEntity = new TenPersonSyncEntity();
+// syncEntity.setPersonId(tenPerson.getPersonId());
+// syncEntity.setTenantId(tenPerson.getTenantId());
+// syncEntity.setDeviceSn(dev.getSn());
+// syncEntity.setDeviceId(dev.getDeviceId());
+// syncEntity.setState(Constant.PERSON_SYNC_ADD);
+// syncEntity.setLastUpdateTime(tenPerson.getLastUpdateTime());
+// tenPersonSyncService.insert(syncEntity);
+//
+// //下发通知
+// List list = new ArrayList<>();
+// TenPersonOperationVo vo = new TenPersonOperationVo();
+// vo.setUid(syncEntity.getPersonId());
+// vo.setOperation(Constant.PERSON_SYNC_ADD);
+// vo.setLast_update_stamp(syncEntity.getLastUpdateTime());
+// list.add(vo);
+// serverApiService.personOperation(dev.getSn(),list);
+// }else{
+// syncEntity.setState(Constant.PERSON_SYNC_MODIFY);
+// syncEntity.setLastUpdateTime(tenPerson.getLastUpdateTime());
+// tenPersonSyncService.updateById(syncEntity);
+//
+// //下发通知
+// List list = new ArrayList<>();
+// TenPersonOperationVo vo = new TenPersonOperationVo();
+// vo.setUid(syncEntity.getPersonId());
+// vo.setOperation(Constant.PERSON_SYNC_MODIFY);
+// vo.setLast_update_stamp(syncEntity.getLastUpdateTime());
+// list.add(vo);
+// serverApiService.personOperation(dev.getSn(),list);
+// }
+// }
+// }
+// //状态为其他时,删除同步表中的数据,并推送
+// else{
+// for (TenDeviceVo dev : devList) {
+// //添加到同步表,下发设备通知
+// TenPersonSyncEntity syncEntity = tenPersonSyncService.findByDeviceIdAndPersonId(dev.getDeviceId(),tenPerson.getPersonId(),tenPerson.getTenantId());
+// if(syncEntity!=null){
+// syncEntity.setState(Constant.PERSON_SYNC_DELETE);
+// syncEntity.setLastUpdateTime(tenPerson.getLastUpdateTime());
+// tenPersonSyncService.updateById(syncEntity);
+// //下发通知
+// List list = new ArrayList<>();
+// TenPersonOperationVo vo = new TenPersonOperationVo();
+// vo.setUid(syncEntity.getPersonId());
+// vo.setOperation(Constant.PERSON_SYNC_DELETE);
+// vo.setLast_update_stamp(syncEntity.getLastUpdateTime());
+// list.add(vo);
+// int flag = serverApiService.personOperation(dev.getSn(),list);
+// if(flag!= -1){
+// tenPersonSyncService.removeByPersonSyncId(syncEntity.getPersonSyncId(),syncEntity.getTenantId());
+// }
+// }
+// }
+// }
return R.ok();
}
@@ -645,6 +664,7 @@ public class TenPersonController extends AbstractController {
/**
* 删除
*/
+ @SysLog("删除人员")
@PostMapping("/delete")
@RequiresPermissions("ten:person")
@ApiOperation(value = "删除")
@@ -734,6 +754,7 @@ public class TenPersonController extends AbstractController {
+ @SysLog("批量导入人员")
@PostMapping("/uploadZip")
@ApiOperation("上传人员信息zip文件")
public R uploadZip(MultipartFile file) {
@@ -819,7 +840,13 @@ public class TenPersonController extends AbstractController {
}else if(regRes == -23){
return R.error("过曝丢弃,错误码:"+regRes);
}else if(regRes == -24){
- return R.error("未检测到手掌,错误码:"+regRes);
+ return R.error("未检测到手掌,请保持距离15-25厘米,错误码:"+regRes);
+ }else if(regRes == -27){
+ return R.error("光线过暗,错误码:"+regRes);
+ }else if(regRes == -28){
+ return R.error("光线过亮,错误码:"+regRes);
+ }else if(regRes == -29){
+ return R.error("对比对过低,错误码:"+regRes);
}else if(regRes == -33){
return R.error("提取ROI图像失败,错误码:"+regRes);
}else{
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenRecordController.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenRecordController.java
index b7bf09d..8e510b9 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenRecordController.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/controller/TenRecordController.java
@@ -10,6 +10,8 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import net.shapelight.common.annotation.SysLog;
import net.shapelight.common.config.GlobalValue;
import net.shapelight.common.utils.Constant;
import net.shapelight.common.utils.DateUtils;
@@ -21,6 +23,12 @@ import net.shapelight.modules.ten.entity.TenUserScopeEntity;
import net.shapelight.modules.ten.service.TenCellService;
import net.shapelight.modules.ten.service.TenUserScopeService;
import org.apache.commons.io.FileUtils;
+import org.apache.poi.hssf.usermodel.*;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.unit.DataUnit;
@@ -32,6 +40,8 @@ import net.shapelight.common.utils.PageUtils;
import net.shapelight.common.utils.R;
import org.springframework.web.multipart.MultipartFile;
+import javax.servlet.http.HttpServletResponse;
+
/**
*
@@ -40,6 +50,7 @@ import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("ten/record")
@Api(value="开门记录",tags="开门记录接口")
+@Slf4j
public class TenRecordController extends AbstractController {
@Autowired
private TenRecordService tenRecordService;
@@ -51,6 +62,8 @@ public class TenRecordController extends AbstractController {
private TenUserScopeService tenUserScopeService;
@Autowired
private GlobalValue globalValue;
+ @Autowired
+ private HttpServletResponse response;
/**
* 列表
@@ -160,64 +173,21 @@ public class TenRecordController extends AbstractController {
* 处理历史图片转存
* 输入年月,年月格式 2021-10
*/
- @PostMapping("/removeImages")
- public R removeImages(@RequestParam("yearMonth") String yearMonth){
- String tenantId = getUser().getTenantId()+"";
- int count = 0;
- String[] yearMonthArray = yearMonth.split("-");
- int year = Integer.parseInt(yearMonthArray[0]);
- int month = Integer.parseInt(yearMonthArray[1]);
- //yyyy-MM-dd
- String yearMonthLastDay = DateUtils.getLastDayOfMonth(year,month);
- String start = yearMonth+"-01 00:00:0l";
- String end = yearMonthLastDay+" 23:59:59";
-
- List monthRecords = tenRecordService.getMonthRecords(start,end,tenantId);
-
- for(TenRecordEntity recordEntity: monthRecords){
- if (recordEntity.getRecordFace()!=null && recordEntity.getRecordFace().length()>0) {
- String srcFileStr = globalValue.getMinioPath()+"/"+recordEntity.getRecordFace();
- try {
- File srcFile = new File(srcFileStr);
- if(srcFile.exists()){
- // images/836267246392180742/836268331420876805/b8c6fa0e9cf54f56ae9189024f0e9058.jpg
- String userDir = recordEntity.getRecordFace().split("/")[2];
- String disPath = "imagebak/"+yearMonth+"/"+userDir;
- File disPathFile = new File(disPath);
- FileUtils.forceMkdir(disPathFile);
-
- FileUtils.copyFileToDirectory(srcFile,disPathFile);
- FileUtils.deleteQuietly(srcFile);
- count++;
- }
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- }
-
- return R.ok().put("data",count);
- }
-
-
-
- @PostMapping("/copy3dZip")
- public R copy3dZip(@RequestParam("yearMonth") String yearMonth){
- String tenantId = getUser().getTenantId()+"";
- int count = 0;
- String[] yearMonthArray = yearMonth.split("-");
- int year = Integer.parseInt(yearMonthArray[0]);
- int month = Integer.parseInt(yearMonthArray[1]);
- //yyyy-MM-dd
- String yearMonthLastDay = DateUtils.getLastDayOfMonth(year,month);
- String start = yearMonth+"-01 00:00:0l";
- String end = yearMonthLastDay+" 23:59:59";
-
- List monthRecords = tenRecordService.getMonthRecords(start,end,tenantId);
-
- for(TenRecordEntity recordEntity: monthRecords){
-
- //识别照片
+// @PostMapping("/removeImages")
+// public R removeImages(@RequestParam("yearMonth") String yearMonth){
+// String tenantId = getUser().getTenantId()+"";
+// int count = 0;
+// String[] yearMonthArray = yearMonth.split("-");
+// int year = Integer.parseInt(yearMonthArray[0]);
+// int month = Integer.parseInt(yearMonthArray[1]);
+// //yyyy-MM-dd
+// String yearMonthLastDay = DateUtils.getLastDayOfMonth(year,month);
+// String start = yearMonth+"-01 00:00:0l";
+// String end = yearMonthLastDay+" 23:59:59";
+//
+// List monthRecords = tenRecordService.getMonthRecords(start,end,tenantId);
+//
+// for(TenRecordEntity recordEntity: monthRecords){
// if (recordEntity.getRecordFace()!=null && recordEntity.getRecordFace().length()>0) {
// String srcFileStr = globalValue.getMinioPath()+"/"+recordEntity.getRecordFace();
// try {
@@ -237,33 +207,314 @@ public class TenRecordController extends AbstractController {
// e.printStackTrace();
// }
// }
+// }
+//
+// return R.ok().put("data",count);
+// }
+//
+//
+//
+// @PostMapping("/copy3dZip")
+// public R copy3dZip(@RequestParam("yearMonth") String yearMonth){
+// String tenantId = getUser().getTenantId()+"";
+// int count = 0;
+// String[] yearMonthArray = yearMonth.split("-");
+// int year = Integer.parseInt(yearMonthArray[0]);
+// int month = Integer.parseInt(yearMonthArray[1]);
+// //yyyy-MM-dd
+// String yearMonthLastDay = DateUtils.getLastDayOfMonth(year,month);
+// String start = yearMonth+"-01 00:00:0l";
+// String end = yearMonthLastDay+" 23:59:59";
+//
+// List monthRecords = tenRecordService.getMonthRecords(start,end,tenantId);
+//
+// for(TenRecordEntity recordEntity: monthRecords){
+//
+// //识别照片
+//// if (recordEntity.getRecordFace()!=null && recordEntity.getRecordFace().length()>0) {
+//// String srcFileStr = globalValue.getMinioPath()+"/"+recordEntity.getRecordFace();
+//// try {
+//// File srcFile = new File(srcFileStr);
+//// if(srcFile.exists()){
+//// // images/836267246392180742/836268331420876805/b8c6fa0e9cf54f56ae9189024f0e9058.jpg
+//// String userDir = recordEntity.getRecordFace().split("/")[2];
+//// String disPath = "imagebak/"+yearMonth+"/"+userDir;
+//// File disPathFile = new File(disPath);
+//// FileUtils.forceMkdir(disPathFile);
+////
+//// FileUtils.copyFileToDirectory(srcFile,disPathFile);
+//// FileUtils.deleteQuietly(srcFile);
+//// count++;
+//// }
+//// }catch (Exception e){
+//// e.printStackTrace();
+//// }
+//// }
+//
+// //3d数据,zip
+// if (recordEntity.getSourceFile()!=null && recordEntity.getSourceFile().length()>0) {
+// String srcFileStr = globalValue.getMinioPath()+"/"+recordEntity.getSourceFile();
+// try {
+// File srcFile = new File(srcFileStr);
+// if(srcFile.exists()){
+// // images/836267246392180742/836268331420876805/b8c6fa0e9cf54f56ae9189024f0e9058.jpg
+// String userDir = recordEntity.getRecordFace().split("/")[2];
+// String disPath = "imagebak/"+yearMonth+"/"+userDir;
+// File disPathFile = new File(disPath);
+// FileUtils.forceMkdir(disPathFile);
+//
+// FileUtils.copyFileToDirectory(srcFile,disPathFile);
+//// FileUtils.deleteQuietly(srcFile);
+// count++;
+// }
+// }catch (Exception e){
+// e.printStackTrace();
+// }
+// }
+// }
+//
+// return R.ok().put("data",count);
+// }
- //3d数据,zip
- if (recordEntity.getSourceFile()!=null && recordEntity.getSourceFile().length()>0) {
- String srcFileStr = globalValue.getMinioPath()+"/"+recordEntity.getSourceFile();
- try {
- File srcFile = new File(srcFileStr);
- if(srcFile.exists()){
- // images/836267246392180742/836268331420876805/b8c6fa0e9cf54f56ae9189024f0e9058.jpg
- String userDir = recordEntity.getRecordFace().split("/")[2];
- String disPath = "imagebak/"+yearMonth+"/"+userDir;
- File disPathFile = new File(disPath);
- FileUtils.forceMkdir(disPathFile);
- FileUtils.copyFileToDirectory(srcFile,disPathFile);
-// FileUtils.deleteQuietly(srcFile);
- count++;
- }
- }catch (Exception e){
- e.printStackTrace();
- }
- }
+
+
+
+ /**
+ * 下载考勤统计
+ */
+ @SysLog("下载通行记录")
+ @GetMapping("/downloadRecord")
+ @RequiresPermissions("ten:record")
+ @ApiOperation("下载识别记录")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name="dateStart",value = "日期开始",paramType = "query",dataType = "String",required = true),
+ @ApiImplicitParam(name="dateEnd",value = "日期结束",paramType = "query",dataType = "String",required = true),
+ })
+ public void downloadRecord(@RequestParam Map params) {
+ String tenantId = getUser().getTenantId()+"";
+ params.put("tenantId",tenantId+"");
+ SysUserEntity user = getUser();
+ List roleIdList = sysUserRoleService.queryRoleIdList(user.getUserId());
+ //小区管理员
+ if(roleIdList.get(0).longValue() == Constant.ROLE_TEN_CELL){
+ TenUserScopeEntity scope = tenUserScopeService.getOne(new QueryWrapper().eq("user_id",user.getUserId()));
+ params.put("cellId",scope.getCellId().toString());
+ }
+ String startTime = (String)params.get("recordTimeStart");
+ String endTime = (String)params.get("recordTimeEnd");
+
+ List dataList = tenRecordService.findListAll(params);
+
+
+ HSSFWorkbook workbook = new HSSFWorkbook();
+
+ HSSFCellStyle cellStyle = workbook.createCellStyle();
+ cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
+ cellStyle.setBorderLeft(BorderStyle.THIN);//左边框
+ cellStyle.setBorderTop(BorderStyle.THIN);//上边框
+ cellStyle.setBorderRight(BorderStyle.THIN);//右边框
+
+
+ HSSFCellStyle biaoTi1 = workbook.createCellStyle();
+ biaoTi1.setAlignment(HorizontalAlignment.CENTER); // 居中
+ HSSFFont font = workbook.createFont();
+ font.setFontName("宋体");
+ font.setFontHeightInPoints((short) 14);// 字体大小
+ font.setBold(true);
+ biaoTi1.setFont(font);
+
+
+ HSSFCellStyle biaoTi2 = workbook.createCellStyle();
+ HSSFFont font2 = workbook.createFont();
+ font2.setFontName("宋体");
+ font2.setFontHeightInPoints((short) 11);// 字体大小
+ font2.setBold(true);
+ biaoTi2.setFont(font2);
+
+
+ HSSFCellStyle biaoTi3 = workbook.createCellStyle();
+ biaoTi3.setBorderBottom(BorderStyle.THIN); //下边框
+ biaoTi3.setBorderLeft(BorderStyle.THIN);//左边框
+ biaoTi3.setBorderTop(BorderStyle.THIN);//上边框
+ biaoTi3.setBorderRight(BorderStyle.THIN);//右边框
+ biaoTi3.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.index);
+ biaoTi3.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+
+
+ HSSFCellStyle juzhong = workbook.createCellStyle();
+ //垂直居中
+ juzhong.setVerticalAlignment(juzhong.getVerticalAlignmentEnum().CENTER);
+
+
+ HSSFCellStyle biaoTiRiQi = workbook.createCellStyle();
+ biaoTiRiQi.setBorderBottom(BorderStyle.THIN); //下边框
+ biaoTiRiQi.setBorderLeft(BorderStyle.THIN);//左边框
+ biaoTiRiQi.setBorderTop(BorderStyle.THIN);//上边框
+ biaoTiRiQi.setBorderRight(BorderStyle.THIN);//右边框
+ biaoTiRiQi.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.index);
+ biaoTiRiQi.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+
+
+ HSSFSheet sheet = workbook.createSheet("记录");
+ //第一行
+ HSSFRow row1 = sheet.createRow(0);
+ //第一单元格
+ HSSFCell cell = row1.createCell(0);
+ //设置单元格内容
+ cell.setCellValue("通行记录");
+ //合并单元格CellRangeAddress构造参数依次表示起始行,截至行,起始列, 截至列
+ // 合并单元格
+ CellRangeAddress cellRangeBiaoti = new CellRangeAddress(0, 0, 0, 7); // 起始行, 终止行, 起始列, 终止列
+ sheet.addMergedRegion(cellRangeBiaoti);
+ cell.setCellStyle(biaoTi1);
+
+
+ // 第二行
+ HSSFRow row2 = sheet.createRow(1);
+ //创建单元格并设置单元格内容
+ HSSFCell cellProjectName = row2.createCell(0);
+ cellProjectName.setCellValue("时间段:" + startTime + " - " + endTime);
+ cellProjectName.setCellStyle(biaoTi2);
+
+ // 第三行
+// HSSFRow row3 = sheet.createRow(2);
+// //创建单元格并设置单元格内容
+// HSSFCell cellDateUnit = row3.createCell(0);
+// cellDateUnit.setCellValue("时间段:" + startTime + " - " + endTime);
+// cellDateUnit.setCellStyle(biaoTi2);
+
+ //
+ //姓名,身份证号,设备名称,出入方式,组织,标签,开门方式,识别时间
+ // 第四行
+ HSSFRow row4 = sheet.createRow(2);
+ //创建单元格并设置单元格内容
+ HSSFCell xingming = row4.createCell(0);
+ xingming.setCellValue("姓名");
+// CellRangeAddress cellRangeXingming = new CellRangeAddress(3, 4, 0, 0);
+// sheet.addMergedRegion(cellRangeXingming);
+ xingming.setCellStyle(biaoTi3);
+// ExcelUtil.setCellRangeBorder(BorderStyle.THIN, cellRangeXingming, sheet);
+
+ HSSFCell deptNamecell = row4.createCell(1);
+ deptNamecell.setCellValue("身份证号");
+// CellRangeAddress cellRangeDeptName = new CellRangeAddress(3, 4, 1, 1);
+// sheet.addMergedRegion(cellRangeDeptName);
+ deptNamecell.setCellStyle(biaoTi3);
+
+ HSSFCell jobNumber = row4.createCell(2);
+ jobNumber.setCellValue("设备名称");
+// CellRangeAddress cellRangejobNumber = new CellRangeAddress(3, 4, 2, 2);
+// sheet.addMergedRegion(cellRangejobNumber);
+ jobNumber.setCellStyle(biaoTi3);
+
+ HSSFCell idNumber = row4.createCell(3);
+ idNumber.setCellValue("出入方式");
+// CellRangeAddress cellRangejobNumber = new CellRangeAddress(3, 4, 2, 2);
+// sheet.addMergedRegion(cellRangejobNumber);
+ idNumber.setCellStyle(biaoTi3);
+
+ HSSFCell checkDays = row4.createCell(4);
+ checkDays.setCellValue("组织");
+// CellRangeAddress cellRangecheckDays = new CellRangeAddress(3, 4, 3, 3);
+// sheet.addMergedRegion(cellRangecheckDays);
+ checkDays.setCellStyle(biaoTi3);
+
+ HSSFCell dutyOnOkCell = row4.createCell(5);
+ dutyOnOkCell.setCellValue("标签");
+// CellRangeAddress cellRangeDutyOnOk = new CellRangeAddress(3, 4, 4, 4);
+// sheet.addMergedRegion(cellRangeDutyOnOk);
+ dutyOnOkCell.setCellStyle(biaoTi3);
+
+ HSSFCell dutyOnLateCell = row4.createCell(6);
+ dutyOnLateCell.setCellValue("开门方式");
+// CellRangeAddress cellRangeWubie = new CellRangeAddress(3, 4, 5, 5);
+// sheet.addMergedRegion(cellRangeWubie);
+ dutyOnLateCell.setCellStyle(biaoTi3);
+
+ HSSFCell dutyOnNoCell = row4.createCell(7);
+ dutyOnNoCell.setCellValue("识别时间");
+// CellRangeAddress cellRangeOnNo = new CellRangeAddress(3, 4, 6, 6);
+// sheet.addMergedRegion(cellRangeOnNo);
+ dutyOnNoCell.setCellStyle(biaoTi3);
+
+
+
+
+
+ //创建数据行
+ for(int i = 0;i {
List findAllSn();
+ List findLabelList(@Param("deviceId")Long deviceId);
+
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/dao/TenDeviceLabelDao.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/dao/TenDeviceLabelDao.java
new file mode 100644
index 0000000..d90b4a4
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/dao/TenDeviceLabelDao.java
@@ -0,0 +1,14 @@
+package net.shapelight.modules.ten.dao;
+
+import net.shapelight.modules.ten.entity.TenDeviceLabelEntity;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 设备标签关联表
+ *
+ */
+@Mapper
+public interface TenDeviceLabelDao extends BaseMapper {
+
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/dao/TenLabelDao.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/dao/TenLabelDao.java
index a0edc66..49e83d9 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/dao/TenLabelDao.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/dao/TenLabelDao.java
@@ -12,6 +12,6 @@ import org.apache.ibatis.annotations.Param;
@Mapper
public interface TenLabelDao extends BaseMapper {
String getLabelName(@Param("labelId")Long labelId);
- String getLabelTypeName(@Param("type")Long type, @Param("tenantId")Long tenantId);
+// String getLabelTypeName(@Param("type")Long type, @Param("tenantId")Long tenantId);
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/dao/TenPersonDao.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/dao/TenPersonDao.java
index 274fd2d..b3623d7 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/dao/TenPersonDao.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/dao/TenPersonDao.java
@@ -2,6 +2,7 @@ package net.shapelight.modules.ten.dao;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import net.shapelight.modules.ten.entity.TenLabelEntity;
import net.shapelight.modules.ten.entity.TenPersonEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.shapelight.modules.vo.TenPersonIdUpdateAllVo;
@@ -118,5 +119,16 @@ public interface TenPersonDao {
List findByIdCardAndDept(@Param("idCard")String idCard, @Param("deptId")Long deptId);
+ List listPage(@Param("start")int start, @Param("count")int count);
+
+ int findCount();
+
+ int findByIdCardCount(@Param("idCard")String idCard, @Param("tenantId")String tenantId);
+
+ TenPersonEntity findByIcCardTop(@Param("icCard")String icCard, @Param("tenantId")String tenantId);
+
+ List findByIdCardList(@Param("idCard")String idCard, @Param("tenantId")String tenantId);
+
+ List getAllIdCard(@Param("tenantId")String tenantId);
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/dao/TenRecordDao.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/dao/TenRecordDao.java
index e97de99..d5fba4d 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/dao/TenRecordDao.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/dao/TenRecordDao.java
@@ -2,6 +2,7 @@ package net.shapelight.modules.ten.dao;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import net.shapelight.modules.ten.entity.TenLabelEntity;
import net.shapelight.modules.ten.entity.TenRecordEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@@ -14,7 +15,7 @@ import java.util.Map;
*
*/
@Mapper
-public interface TenRecordDao {
+public interface TenRecordDao{
int insert(TenRecordEntity tenRecordEntity);
int deleteById(@Param("recordId") Long id, @Param("tenantId") Long tenantId);
@@ -46,4 +47,10 @@ public interface TenRecordDao {
List getMonthRecords(@Param("start") String start, @Param("end") String end, @Param("tenantId") String tenantId);
IPage findPageDeptRecord(Page page, @Param("params") Map params);
+
+ List getDaysIntervalRecords(@Param("days") String days, @Param("tenantId") String tenantId);
+
+ void deleteDaysIntervalRecords(@Param("days") String days, @Param("tenantId") String tenantId);
+
+ List findListAll(@Param("cellIds") List cellIds, @Param("params") Map params);
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenDeviceEntity.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenDeviceEntity.java
index af7f33f..0fe417d 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenDeviceEntity.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenDeviceEntity.java
@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;
+import java.util.List;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
@@ -260,4 +261,9 @@ public class TenDeviceEntity extends BaseEntity implements Serializable {
private String lat;
private String lon;
+ //-----------------------------------
+ @TableField(exist=false)
+ @ApiModelProperty("绑定的员工组")
+ private List LabelList;
+
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenDeviceLabelEntity.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenDeviceLabelEntity.java
new file mode 100644
index 0000000..73adbf4
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenDeviceLabelEntity.java
@@ -0,0 +1,33 @@
+package net.shapelight.modules.ten.entity;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 设备标签关联表
+ *
+ */
+@Data
+@TableName("ten_device_label")
+public class TenDeviceLabelEntity implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ @TableId
+ private Long deviceLabelId;
+ /**
+ * 设备id
+ */
+ private Long deviceId;
+ /**
+ * 标签id
+ */
+ private Long labelId;
+
+}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenLabelEntity.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenLabelEntity.java
index 4df566f..363ddaf 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenLabelEntity.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenLabelEntity.java
@@ -60,4 +60,13 @@ public class TenLabelEntity extends BaseEntity implements Serializable {
@JsonSerialize(using = ToStringSerializer.class)
private Long tenantId;
+ @ApiModelProperty("开门时间段1")
+ private String openPeriod1;
+
+ @ApiModelProperty("开门时间段2")
+ private String openPeriod2;
+
+ @ApiModelProperty("开门时间段3")
+ private String openPeriod3;
+
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenPersonEntity.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenPersonEntity.java
index d1d3a52..eb5c6a9 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenPersonEntity.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenPersonEntity.java
@@ -366,4 +366,11 @@ public class TenPersonEntity extends BaseEntity implements Serializable {
private String pvRight;
private Integer featureType;
+ //-----------------后台识别,保存特征
+ @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
+ private String feature;
+ private String ic;
+ private String householder;
+ private String relation;
+
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenRecordEntity.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenRecordEntity.java
index fb6c060..77a9dd6 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenRecordEntity.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/entity/TenRecordEntity.java
@@ -185,4 +185,7 @@ cameraParam 否 string 相机参数
@TableField(exist = false)
private String sourceFileStr;
+ private String idCard;
+ private String name;
+
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenDeviceLabelService.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenDeviceLabelService.java
new file mode 100644
index 0000000..4f73426
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenDeviceLabelService.java
@@ -0,0 +1,16 @@
+package net.shapelight.modules.ten.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import net.shapelight.common.utils.PageUtils;
+import net.shapelight.modules.ten.entity.TenDeviceLabelEntity;
+
+import java.util.Map;
+
+/**
+ * 设备标签关联表
+ *
+ */
+public interface TenDeviceLabelService extends IService {
+
+}
+
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenDeviceService.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenDeviceService.java
index f7dc8d0..b2c16dd 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenDeviceService.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenDeviceService.java
@@ -2,13 +2,11 @@ package net.shapelight.modules.ten.service;
import com.baomidou.mybatisplus.extension.service.IService;
import net.shapelight.common.utils.PageUtils;
-import net.shapelight.modules.ten.entity.TenDeviceAlertEntity;
-import net.shapelight.modules.ten.entity.TenDeviceEntity;
-import net.shapelight.modules.ten.entity.TenPersonEntity;
-import net.shapelight.modules.ten.entity.TenRecordEntity;
+import net.shapelight.modules.ten.entity.*;
import net.shapelight.modules.vo.TenDeviceVo;
import net.shapelight.modules.vo.TenPersonIdUpdateVo;
import net.shapelight.modules.vo.TenPersonVo;
+import org.apache.ibatis.annotations.Param;
import java.io.Serializable;
import java.util.Collection;
@@ -69,6 +67,8 @@ public interface TenDeviceService extends IService {
List queryList(Map params);
+ List findLabelList(Long deviceId);
+
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenLabelService.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenLabelService.java
index 652012d..e64ca91 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenLabelService.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenLabelService.java
@@ -13,5 +13,7 @@ import java.util.Map;
public interface TenLabelService extends IService {
PageUtils queryPage(Map params);
+
+ TenLabelEntity findLabelByName(String name, String tenantId);
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenPersonService.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenPersonService.java
index 0aad896..6e4cbc9 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenPersonService.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenPersonService.java
@@ -3,10 +3,7 @@ package net.shapelight.modules.ten.service;
import com.baomidou.mybatisplus.extension.service.IService;
import net.shapelight.common.utils.PageUtils;
import net.shapelight.modules.excel.model.PersonModel;
-import net.shapelight.modules.ten.entity.TenBuildEntity;
-import net.shapelight.modules.ten.entity.TenCellEntity;
-import net.shapelight.modules.ten.entity.TenPersonEntity;
-import net.shapelight.modules.ten.entity.TenRoomEntity;
+import net.shapelight.modules.ten.entity.*;
import net.shapelight.modules.vo.TenPersonIdUpdateAllVo;
import net.shapelight.modules.vo.TenPersonIdUpdateVo;
import net.shapelight.modules.vo.TenPersonMonthCountVo;
@@ -148,5 +145,22 @@ public interface TenPersonService {
List findByIdCardAndDept(String idCard,
Long deptId);
+ List listPage(int start, int count);
+
+ int findCount();
+
+ TenLabelEntity findLabelByName(String name, String tenantId);
+
+ int findByIdCardCount(String idCard, String tenantId);
+
+ TenPersonEntity findByIcCardTop(String icCard, String tenantId);
+
+ List findByIdCardList(String idCard, String tenantId);
+
+ int saveByIdCard(TenPersonEntity entity);
+ int updateByIdCard(TenPersonEntity entity);
+
+ List getAllIdCard(String tenantId);
+
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenRecordService.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenRecordService.java
index 8b4dda2..ff2af45 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenRecordService.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/TenRecordService.java
@@ -1,8 +1,10 @@
package net.shapelight.modules.ten.service;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import net.shapelight.common.utils.PageUtils;
import net.shapelight.modules.ten.entity.TenRecordEntity;
+import org.apache.ibatis.annotations.Param;
import java.io.Serializable;
import java.util.Collection;
@@ -44,5 +46,13 @@ public interface TenRecordService {
PageUtils queryPageDeptRecord(Map params);
+ boolean saveServer(TenRecordEntity entity);
+
+ List getDaysIntervalRecords(String days, String tenantId);
+
+ void deleteDaysIntervalRecords(String days, String tenantId);
+
+ List findListAll(Map params);
+
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenDeviceLabelServiceImpl.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenDeviceLabelServiceImpl.java
new file mode 100644
index 0000000..43a3730
--- /dev/null
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenDeviceLabelServiceImpl.java
@@ -0,0 +1,20 @@
+package net.shapelight.modules.ten.service.impl;
+
+import org.springframework.stereotype.Service;
+import java.util.Map;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import net.shapelight.common.utils.PageUtils;
+import net.shapelight.common.utils.Query;
+
+import net.shapelight.modules.ten.dao.TenDeviceLabelDao;
+import net.shapelight.modules.ten.entity.TenDeviceLabelEntity;
+import net.shapelight.modules.ten.service.TenDeviceLabelService;
+
+
+@Service("tenDeviceLabelService")
+public class TenDeviceLabelServiceImpl extends ServiceImpl implements TenDeviceLabelService {
+
+
+}
\ No newline at end of file
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenDeviceServiceImpl.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenDeviceServiceImpl.java
index 68f9e21..40ea954 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenDeviceServiceImpl.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenDeviceServiceImpl.java
@@ -55,6 +55,8 @@ public class TenDeviceServiceImpl extends ServiceImpl params) {
@@ -148,6 +150,9 @@ public class TenDeviceServiceImpl extends ServiceImpl labelList = this.findLabelList(dev.getDeviceId());
+ dev.setLabelList(labelList);
}
return new PageUtils(page);
}
@@ -409,29 +414,46 @@ public class TenDeviceServiceImpl extends ServiceImpl()
+ .eq("device_id",deviceEntity.getDeviceId()));
+ //2. 添加数据
+ List addList = new ArrayList<>();
+ if(deviceEntity.getLabelList().size()>0){
+ for(TenLabelEntity labelEntity: deviceEntity.getLabelList()){
+ TenDeviceLabelEntity dl = new TenDeviceLabelEntity();
+ dl.setDeviceId(deviceEntity.getDeviceId());
+ dl.setLabelId(labelEntity.getLabelId());
+ addList.add(dl);
+ }
+ tenDeviceLabelService.saveBatch(addList);
+ }
+
+
//在同步表中插入所有信息
- List list = tenPersonService.findAllPersonIdUpdateAll(deviceEntity.getCellId(),
- deviceEntity.getBuildId(),
- deviceEntity.getRoomId());
-// List sList = new ArrayList<>();
- //1.删除设备关联的人
- //2.批量添加
- List saveList = new ArrayList<>();
- for (TenPersonIdUpdateAllVo vo : list) {
- TenPersonSyncEntity entity = new TenPersonSyncEntity();
- entity.setDeviceId(deviceEntity.getDeviceId());
- entity.setDeviceSn(deviceEntity.getSn());
- entity.setLastUpdateTime(vo.getLast_update_stamp());
- entity.setPersonId(vo.getUid());
- entity.setState(0);
- entity.setTenantId(deviceEntity.getTenantId());
-// sList.add(entity);
- saveList.add(entity);
-// tenPersonSyncService.insert(entity);
- }
- if (saveList.size() > 0) {
- tenPersonSyncService.insertBatch(saveList, deviceEntity.getTenantId());
- }
+// List list = tenPersonService.findAllPersonIdUpdateAll(deviceEntity.getCellId(),
+// deviceEntity.getBuildId(),
+// deviceEntity.getRoomId());
+//// List sList = new ArrayList<>();
+// //1.删除设备关联的人
+// //2.批量添加
+// List saveList = new ArrayList<>();
+// for (TenPersonIdUpdateAllVo vo : list) {
+// TenPersonSyncEntity entity = new TenPersonSyncEntity();
+// entity.setDeviceId(deviceEntity.getDeviceId());
+// entity.setDeviceSn(deviceEntity.getSn());
+// entity.setLastUpdateTime(vo.getLast_update_stamp());
+// entity.setPersonId(vo.getUid());
+// entity.setState(0);
+// entity.setTenantId(deviceEntity.getTenantId());
+//// sList.add(entity);
+// saveList.add(entity);
+//// tenPersonSyncService.insert(entity);
+// }
+// if (saveList.size() > 0) {
+// tenPersonSyncService.insertBatch(saveList, deviceEntity.getTenantId());
+// }
// tenPersonSyncService.saveBatch(sList);
}
@@ -440,6 +462,22 @@ public class TenDeviceServiceImpl extends ServiceImpl0){
+ tenDeviceLabelService.remove(new QueryWrapper()
+ .eq("device_id",tenDevice.getDeviceId()));
+ //2. 添加数据
+ List addList = new ArrayList<>();
+ if(tenDevice.getLabelList() != null && tenDevice.getLabelList().size()>0){
+ for(TenLabelEntity labelEntity: tenDevice.getLabelList()){
+ TenDeviceLabelEntity dl = new TenDeviceLabelEntity();
+ dl.setDeviceId(tenDevice.getDeviceId());
+ dl.setLabelId(labelEntity.getLabelId());
+ addList.add(dl);
+ }
+ tenDeviceLabelService.saveBatch(addList);
+ }
+ }
}
public List getNotSync(Long cellId) {
@@ -448,4 +486,9 @@ public class TenDeviceServiceImpl extends ServiceImpl findLabelList(Long deviceId) {
+ return baseMapper.findLabelList(deviceId);
+ }
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenLabelServiceImpl.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenLabelServiceImpl.java
index 9964e80..631f17f 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenLabelServiceImpl.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenLabelServiceImpl.java
@@ -1,5 +1,8 @@
package net.shapelight.modules.ten.service.impl;
+import net.shapelight.modules.ten.entity.TenCellEntity;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -17,6 +20,7 @@ import net.shapelight.modules.ten.service.TenLabelService;
public class TenLabelServiceImpl extends ServiceImpl implements TenLabelService {
@Override
+ @CacheEvict(value = "TenLabel", allEntries = true)
public PageUtils queryPage(Map params) {
String tenantId = (String)params.get("tenantId");
IPage page = this.page(
@@ -28,4 +32,9 @@ public class TenLabelServiceImpl extends ServiceImpl().eq("name", name).eq("tenant_id",tenantId));
+ }
}
diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenPersonServiceImpl.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenPersonServiceImpl.java
index ca7b51c..8691659 100644
--- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenPersonServiceImpl.java
+++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenPersonServiceImpl.java
@@ -1,7 +1,12 @@
package net.shapelight.modules.ten.service.impl;
+import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.metadata.Sheet;
+import com.arcsoft.face.FaceInfo;
+import com.arcsoft.face.enums.ExtractType;
+import com.arcsoft.face.toolkit.ImageFactory;
+import com.arcsoft.face.toolkit.ImageInfo;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.minio.MinioClient;
import io.minio.PutObjectOptions;
@@ -18,6 +23,11 @@ import net.shapelight.modules.app.service.AppUserService;
//import net.shapelight.modules.dev.mqtt.CmdProcess;
import net.shapelight.modules.excel.listener.PersonExcelListener;
import net.shapelight.modules.excel.model.PersonModel;
+import net.shapelight.modules.face.dto.FaceRecognitionResDTO;
+import net.shapelight.modules.face.entity.UserCompareInfo;
+import net.shapelight.modules.face.service.FaceEngineService;
+import net.shapelight.modules.face.util.Base64Util;
+import net.shapelight.modules.face.util.UserRamCache;
import net.shapelight.modules.nettyapi.service.ServerApiService;
import net.shapelight.modules.ten.entity.*;
import net.shapelight.modules.ten.service.*;
@@ -86,6 +96,10 @@ public class TenPersonServiceImpl implements TenPersonService {
private TenPersonExtractService tenPersonExtractService;
@Autowired
private TenCellDeptService tenCellDeptService;
+ @Autowired
+ private FaceEngineService faceEngineService;
+ @Autowired
+ private TenLabelService tenLabelService;
@Override
@@ -234,9 +248,7 @@ public class TenPersonServiceImpl implements TenPersonService {
@Transactional(rollbackFor = Exception.class)
@CacheEvict(value = "TenPerson", allEntries = true)
public int save(TenPersonEntity entity) {
- String userFileUrl = globalValue.getImagesDir() + "/" +
- entity.getCellId().toString() + "/" +
- entity.getPersonId().toString() + "/";
+ String userFileUrl = globalValue.getImagesDir() + "/org/";
try {
//保存原始图片
String tempOrgImageFile = entity.getOrgImageTemp();
@@ -255,48 +267,94 @@ public class TenPersonServiceImpl implements TenPersonService {
//判断人脸照片是否合格
//1.保存到本地
InputStream tempInputStream = minioClient.getObject(minioConfig.getBucketName(), tempOrgImageFile);
- String tempPath = globalValue.getStaticLocations() + "/";//+globalValue.getTempDir()+"/";
- String tempOrgFilePath = tempPath + tempOrgImageFile;
- int index;
- byte[] bytes = new byte[1024];
- File outFile = new File(tempOrgFilePath);
- FileOutputStream downloadFile = new FileOutputStream(outFile);
- while ((index = tempInputStream.read(bytes)) != -1) {
- downloadFile.write(bytes, 0, index);
- downloadFile.flush();
+ //----------------算法检测----------------------------------------------
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = tempInputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, length);
}
- downloadFile.close();
- tempInputStream.close();
- //2.测试上传的文件
- String tempFaceFileName = UUIDUtil.uuid() + ".jpg";
- String tempFaceFilePath = tempPath + tempFaceFileName;
- String osName = System.getProperty("os.name");//获取指定键(即os.name)的系统属性,如:Windows 7。
- if (!Pattern.matches("Windows.*", osName)) {
-// if (Pattern.matches("Windows.*", osName)) {
- int res = PicSDK.getFace(tempOrgFilePath, tempFaceFilePath);
- if (res != 0) {
+ byte[] bytes = outputStream.toByteArray();
+ outputStream.close();
+ tempInputStream.close();
+ //-------------------------------------------------------------------------
+ ImageInfo rgbData = ImageFactory.getRGBData(bytes);
+ List faceInfoList = faceEngineService.detectFaces(rgbData);
+ if (CollectionUtil.isNotEmpty(faceInfoList)) {
+ FaceInfo faceInfo = faceInfoList.get(0);
+ FaceRecognitionResDTO faceRecognitionResDTO = new FaceRecognitionResDTO();
+ faceRecognitionResDTO.setRect(faceInfo.getRect());
+ byte[] featureBytes = faceEngineService.extractFaceFeature(rgbData, faceInfo, ExtractType.REGISTER);
+ if (featureBytes != null) {
+// UserRamCache.UserInfo userInfo = new UserCompareInfo();
+// userInfo.setFaceId(faceAddReqDTO.getName());
+// userInfo.setName(faceAddReqDTO.getName());
+// userInfo.setFaceFeature(feature);
+// //这边注册到内存缓存中,也可以根据业务,注册到数据库中
+// UserRamCache.addUser(userInfo);
+ entity.setFeature(Base64.getEncoder().encodeToString(featureBytes));
+ }else{
log.error("图片不合格,未检测到人脸");
return 2;
}
- //保存底片文件到oss
- InputStream inputStream = new FileInputStream(tempFaceFilePath);
- PutObjectOptions putObjectOptions = new PutObjectOptions(inputStream.available(), -1);
- putObjectOptions.setContentType("image/jpeg");
- minioClient.putObject(
- minioConfig.getBucketName(), faceImageFileName, inputStream, putObjectOptions);
- inputStream.close();
- } else {
- minioClient.copyObject(
- minioConfig.getBucketName(),
- faceImageFileName,
- null,
- null,
- minioConfig.getBucketName(),
- tempOrgImageFile,
- null,
- null);
+ }else{
+ log.error("图片不合格,未检测到人脸");
+ return 2;
}
+
+
+// String tempPath = globalValue.getStaticLocations() + "/";//+globalValue.getTempDir()+"/";
+// String tempOrgFilePath = tempPath + tempOrgImageFile;
+// int index;
+// byte[] bytes = new byte[1024];
+// File outFile = new File(tempOrgFilePath);
+// FileOutputStream downloadFile = new FileOutputStream(outFile);
+// while ((index = tempInputStream.read(bytes)) != -1) {
+// downloadFile.write(bytes, 0, index);
+// downloadFile.flush();
+// }
+// downloadFile.close();
+// tempInputStream.close();
+// //2.测试上传的文件
+// String tempFaceFileName = UUIDUtil.uuid() + ".jpg";
+// String tempFaceFilePath = tempPath + tempFaceFileName;
+
+// String osName = System.getProperty("os.name");//获取指定键(即os.name)的系统属性,如:Windows 7。
+// if (!Pattern.matches("Windows.*", osName)) {
+//// if (Pattern.matches("Windows.*", osName)) {
+// int res = PicSDK.getFace(tempOrgFilePath, tempFaceFilePath);
+// if (res != 0) {
+// log.error("图片不合格,未检测到人脸");
+// return 2;
+// }
+// //保存底片文件到oss
+// InputStream inputStream = new FileInputStream(tempFaceFilePath);
+// PutObjectOptions putObjectOptions = new PutObjectOptions(inputStream.available(), -1);
+// putObjectOptions.setContentType("image/jpeg");
+// minioClient.putObject(
+// minioConfig.getBucketName(), faceImageFileName, inputStream, putObjectOptions);
+// inputStream.close();
+// } else {
+// minioClient.copyObject(
+// minioConfig.getBucketName(),
+// faceImageFileName,
+// null,
+// null,
+// minioConfig.getBucketName(),
+// tempOrgImageFile,
+// null,
+// null);
+// }
+ minioClient.copyObject(
+ minioConfig.getBucketName(),
+ faceImageFileName,
+ null,
+ null,
+ minioConfig.getBucketName(),
+ tempOrgImageFile,
+ null,
+ null);
//拷贝临时文件正式文件
minioClient.copyObject(
minioConfig.getBucketName(),
@@ -313,7 +371,7 @@ public class TenPersonServiceImpl implements TenPersonService {
//删除临时文件oss
minioClient.removeObject(minioConfig.getBucketName(), tempOrgImageFile);
//删除本地临时文件
- new File(tempFaceFilePath).delete();
+// new File(tempFaceFilePath).delete();
} catch (Exception e) {
entity.setOrgImage("");
entity.setFaceImage("");
@@ -394,6 +452,13 @@ public class TenPersonServiceImpl implements TenPersonService {
// }
// }
int flag = tenPersonDao.insert(entity);
+ //特征保存到内存
+ UserRamCache.UserInfo userInfo = new UserCompareInfo();
+ userInfo.setFaceId(entity.getPersonId()+"");
+ userInfo.setName(entity.getName());
+ userInfo.setFaceFeature(Base64.getDecoder().decode(entity.getFeature()));
+ UserRamCache.addUser(userInfo);
+ log.debug("内存增加人员:"+entity.getPersonId()+" 姓名:"+entity.getName());
////访客添加失效redisKey
// if(entity.getPersonType() == Constant.PERSON_TYPE_GUEST){
@@ -826,6 +891,9 @@ public class TenPersonServiceImpl implements TenPersonService {
//删除人员
tenPersonDao.logicDeleteById(personId, cellId);
+ //基础人脸库
+ UserRamCache.removeUser(personId+"");
+ log.debug("内存移除人员:"+personId);
//记录所有人员id
personIds.add(personId);
@@ -833,41 +901,41 @@ public class TenPersonServiceImpl implements TenPersonService {
//配置同步信息并推送
- List