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> snPersonsList = tenPersonSyncService.findGroupDevicePersons(personIds, tenantId); - for (Map snPersons : snPersonsList) { - String sn = snPersons.get("deviceSn"); - TenDeviceEntity deviceEntity = tenDeviceService.findBySn(sn); - if(deviceEntity==null){ - continue; - } - String[] persons = snPersons.get("plist").split(","); - List list = new ArrayList<>(); - for (String personStr : persons) { - String[] personInfoStr = personStr.split("_"); - Long personId = Long.parseLong(personInfoStr[0]); - Date lastUpdateTime = DateUtils.stringToDate(personInfoStr[1], DateUtils.DATE_TIME_PATTERN); - - TenPersonSyncEntity syncEntity = tenPersonSyncService.findByDeviceIdAndPersonId(deviceEntity.getDeviceId(), personId, tenantId); - syncEntity.setLastUpdateTime(lastUpdateTime); - syncEntity.setState(Constant.PERSON_SYNC_DELETE); - tenPersonSyncService.updateById(syncEntity); - } - //下发通知 - List allDelete = tenPersonSyncService.findDeviceAllDeletePersons(deviceEntity.getDeviceId(), deviceEntity.getTenantId()); - for (TenPersonSyncEntity syncEntity : allDelete) { - 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(sn, list); - if (flag == 0) { - //下发成功,删除状态为删除的同步人员 - tenPersonSyncService.removeAllDeletePersons(deviceEntity.getDeviceId(), tenantId); - } - } +// List> snPersonsList = tenPersonSyncService.findGroupDevicePersons(personIds, tenantId); +// for (Map snPersons : snPersonsList) { +// String sn = snPersons.get("deviceSn"); +// TenDeviceEntity deviceEntity = tenDeviceService.findBySn(sn); +// if(deviceEntity==null){ +// continue; +// } +// String[] persons = snPersons.get("plist").split(","); +// List list = new ArrayList<>(); +// for (String personStr : persons) { +// String[] personInfoStr = personStr.split("_"); +// Long personId = Long.parseLong(personInfoStr[0]); +// Date lastUpdateTime = DateUtils.stringToDate(personInfoStr[1], DateUtils.DATE_TIME_PATTERN); +// +// TenPersonSyncEntity syncEntity = tenPersonSyncService.findByDeviceIdAndPersonId(deviceEntity.getDeviceId(), personId, tenantId); +// syncEntity.setLastUpdateTime(lastUpdateTime); +// syncEntity.setState(Constant.PERSON_SYNC_DELETE); +// tenPersonSyncService.updateById(syncEntity); +// } +// //下发通知 +// List allDelete = tenPersonSyncService.findDeviceAllDeletePersons(deviceEntity.getDeviceId(), deviceEntity.getTenantId()); +// for (TenPersonSyncEntity syncEntity : allDelete) { +// 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(sn, list); +// if (flag == 0) { +// //下发成功,删除状态为删除的同步人员 +// tenPersonSyncService.removeAllDeletePersons(deviceEntity.getDeviceId(), tenantId); +// } +// } return true; } @@ -931,9 +999,10 @@ public class TenPersonServiceImpl implements TenPersonService { TenPersonEntity oldPerson = tenPersonDao.selectById(entity.getPersonId(), entity.getCellId()); - String userFileUrl = globalValue.getImagesDir() + "/" + - entity.getCellId().toString() + "/" + - entity.getPersonId().toString() + "/"; +// String userFileUrl = globalValue.getImagesDir() + "/" + +// entity.getCellId().toString() + "/" + +// entity.getPersonId().toString() + "/"; + String userFileUrl = globalValue.getImagesDir() + "/org/"; try { //保存原始图片 String tempOrgImageFile = entity.getOrgImageTemp(); @@ -953,48 +1022,97 @@ 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(); - } - 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)) { - int res = PicSDK.getFace(tempOrgFilePath, tempFaceFilePath); - if (res != 0) { + //----------------算法检测---------------------------------------------- + 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) { +// 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 "图片不合格,未检测到人脸"; } - //保存底片文件到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 "图片不合格,未检测到人脸"; } + + + + +// 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)) { +// int res = PicSDK.getFace(tempOrgFilePath, tempFaceFilePath); +// if (res != 0) { +// log.error("图片不合格,未检测到人脸"); +// return "图片不合格,未检测到人脸"; +// } +// //保存底片文件到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(), @@ -1011,7 +1129,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(""); @@ -1357,23 +1475,36 @@ public class TenPersonServiceImpl implements TenPersonService { // } } - tenPersonDao.updateById(entity); - //配置同步数据 - List syncEntitys = tenPersonSyncService.findByPersonId(entity.getPersonId(), entity.getTenantId()); - for (TenPersonSyncEntity syncEn : syncEntitys) { - syncEn.setLastUpdateTime(entity.getLastUpdateTime()); - syncEn.setState(2); - tenPersonSyncService.updateById(syncEn); - //下发通知 - List list = new ArrayList<>(); - TenPersonOperationVo vo = new TenPersonOperationVo(); - vo.setUid(entity.getPersonId()); - vo.setOperation(2); - vo.setLast_update_stamp(entity.getLastUpdateTime()); - list.add(vo); - serverApiService.personOperation(syncEn.getDeviceSn(), list); + //特征保存到内存 + if(entity.getFeature()!=null && entity.getFeature().length()>0){ + UserRamCache.removeUser(entity.getPersonId()+""); + log.debug("内存删除人员:"+entity.getPersonId()+" 姓名:"+entity.getName()); + 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 syncEntitys = tenPersonSyncService.findByPersonId(entity.getPersonId(), entity.getTenantId()); + for (TenPersonSyncEntity syncEn : syncEntitys) { + syncEn.setLastUpdateTime(entity.getLastUpdateTime()); + syncEn.setState(2); + tenPersonSyncService.updateById(syncEn); + //下发通知 + List list = new ArrayList<>(); + TenPersonOperationVo vo = new TenPersonOperationVo(); + vo.setUid(entity.getPersonId()); + vo.setOperation(2); + vo.setLast_update_stamp(entity.getLastUpdateTime()); + list.add(vo); + serverApiService.personOperation(syncEn.getDeviceSn(), list); + } } + tenPersonDao.updateById(entity); + + // List devList = tenDeviceService.findByCellId(entity.getCellId()); // for (TenDeviceVo dev : devList) { // CmdProcess.publishPersonChange(dev.getSn()); @@ -1853,10 +1984,11 @@ public class TenPersonServiceImpl implements TenPersonService { public List processUploadFile(Map> fileMap, String tenantId) { List excelFiles = fileMap.get("excel"); List imageFiles = fileMap.get("image"); + List idCardList = this.getAllIdCard(tenantId); List list = new ArrayList<>(); for (String excelFileStr : excelFiles) { BufferedInputStream excelStream = null; - PersonExcelListener listener = new PersonExcelListener(imageFiles, this, this.tenCellDeptService,tenantId); + PersonExcelListener listener = new PersonExcelListener(imageFiles, this, this.tenCellDeptService,this.faceEngineService,idCardList,tenantId); try { excelStream = new BufferedInputStream(new FileInputStream(excelFileStr)); EasyExcelFactory.readBySax(excelStream, new Sheet(1, 1, PersonModel.class), listener); @@ -1911,7 +2043,7 @@ public class TenPersonServiceImpl implements TenPersonService { TenPersonEntity tenPerson = new TenPersonEntity(); - TenCellEntity cellEntity = findCellByCellName(personModel.getCellName(), personModel.getTenantId()); +// TenCellEntity cellEntity = findCellByCellName(personModel.getCellName(), personModel.getTenantId()); // TenBuildEntity tenBuildEntity = findBuildByNameAndUnit(personModel.getBuildName(), // personModel.getBuildUnit().replace("单元", ""), // cellEntity.getCellId()); @@ -1919,13 +2051,19 @@ public class TenPersonServiceImpl implements TenPersonService { // tenBuildEntity.getBuildId(), // cellEntity.getCellId()); - tenPerson.setCellId(cellEntity.getCellId()); + tenPerson.setCellId(personModel.getCellId()); // tenPerson.setBuildId(tenBuildEntity.getBuildId()); // tenPerson.setRoomId(tenRoomEntity.getRoomId()); tenPerson.setDeptId(personModel.getDeptId()); + tenPerson.setLabelId(personModel.getLabelId()); + + tenPerson.setIc(personModel.getIc()); + tenPerson.setHouseholder(personModel.getHouseholder()); + tenPerson.setRelation(personModel.getRelation()); - cellId = cellEntity.getCellId(); + +// cellId = cellEntity.getCellId(); tenPerson.setName(personModel.getName()); if (personModel.getGender().equals("男")) { @@ -1948,155 +2086,84 @@ public class TenPersonServiceImpl implements TenPersonService { tenPerson.setLastUpdateTime(now); tenPerson.setRegisterType(Constant.RESGISTER_TYPE_FILE); - String userFileUrl = globalValue.getImagesDir() + "/" + - tenPerson.getCellId().toString() + "/" + - tenPerson.getPersonId().toString() + "/"; +// String userFileUrl = globalValue.getImagesDir() + "/" + +// tenPerson.getCellId().toString() + "/" + +// tenPerson.getPersonId().toString() + "/"; + String userFileUrl = globalValue.getImagesDir() + "/org/"; String orgImageFileName = userFileUrl + "o_" + UUIDUtil.uuid() + ".jpg"; - String faceImageFileName = userFileUrl + "s_" + UUIDUtil.uuid() + ".jpg"; +// String faceImageFileName = userFileUrl + "s_" + UUIDUtil.uuid() + ".jpg"; - try { - //1. 保存原始图片 - InputStream inputStream = new FileInputStream(personModel.getOrgImage()); + if(personModel.getOrgImage()!=null){ + try { + //1. 保存原始图片 + InputStream inputStream = new FileInputStream(personModel.getOrgImage()); // File inFile = new File(personModel.getOrgImage()); // log.info("开始保存原图"+tenPerson.getOrgImage()+"-"+personModel.getOrgImage()); // log.info("文件大小"+inFile.length()); - PutObjectOptions putObjectOptions = new PutObjectOptions(inputStream.available(), -1); + PutObjectOptions putObjectOptions = new PutObjectOptions(inputStream.available(), -1); // PutObjectOptions putObjectOptions = new PutObjectOptions(inFile.length(), -1); - putObjectOptions.setContentType("image/jpg"); - minioClient.putObject( - minioConfig.getBucketName(), orgImageFileName, inputStream, putObjectOptions); - inputStream.close(); - tenPerson.setOrgImage(orgImageFileName); + putObjectOptions.setContentType("image/jpg"); + minioClient.putObject( + minioConfig.getBucketName(), orgImageFileName, inputStream, putObjectOptions); + inputStream.close(); + tenPerson.setOrgImage(orgImageFileName); // log.info("原图"+tenPerson.getOrgImage()+"-"+personModel.getOrgImage()); - - - //2. 截取人脸图片 - //检测图片人脸 - -//-------------------------------------------------------------------- - String tempPath = ""; - if (Pattern.matches("Linux.*", System.getProperty("os.name"))) { - tempPath = personModel.getOrgImage().substring(0, personModel.getOrgImage().lastIndexOf("/") + 1); - } else if (Pattern.matches("Windows.*", System.getProperty("os.name"))) { - tempPath = personModel.getOrgImage().substring(0, personModel.getOrgImage().lastIndexOf("\\") + 1); - } - String tempFaceFileName = UUIDUtil.uuid() + ".jpg"; - String tempFaceFilePath = tempPath + tempFaceFileName; - - - String osName = System.getProperty("os.name");//获取指定键(即os.name)的系统属性,如:Windows 7。 -// if (!Pattern.matches("Windows.*", osName)) { -// int res = PicSDK.getFace(personModel.getOrgImage(), tempFaceFilePath); -// if (res != 0) { -// return; -// } else { -// //1. 保存人脸图片 -// InputStream inputStreamFace = new FileInputStream(tempFaceFilePath); -// PutObjectOptions putObjectOptionsFace = new PutObjectOptions(inputStreamFace.available(), -1); -// putObjectOptions.setContentType("image/jpg"); -// minioClient.putObject( -// minioConfig.getBucketName(), faceImageFileName, inputStreamFace, putObjectOptionsFace); -// inputStreamFace.close(); -// tenPerson.setFaceImage(faceImageFileName); -// } -// } else { -// //windows 保存原始头像 -// tenPerson.setFaceImage(orgImageFileName); -// } - - tenPerson.setFaceImage(orgImageFileName); - - -// int res = PicSDK.getFace(personModel.getOrgImage(), tempFaceFilePath); -// if (res != 0) { -// return; -// } else { -// //1. 保存人脸图片 -// InputStream inputStreamFace = new FileInputStream(tempFaceFilePath); -// PutObjectOptions putObjectOptionsFace = new PutObjectOptions(inputStreamFace.available(), -1); -// putObjectOptions.setContentType("image/jpg"); -// minioClient.putObject( -// minioConfig.getBucketName(), faceImageFileName, inputStreamFace, putObjectOptionsFace); -// inputStreamFace.close(); -// tenPerson.setFaceImage(faceImageFileName); -// } - - -// //1. 保存人脸图片 -// InputStream inputStreamFace = new FileInputStream(tempFaceFilePath); -// PutObjectOptions putObjectOptionsFace = new PutObjectOptions(inputStreamFace.available(), -1); -// putObjectOptions.setContentType("image/jpg"); -// minioClient.putObject( -// minioConfig.getBucketName(), faceImageFileName, inputStreamFace, putObjectOptionsFace); -// inputStreamFace.close(); -// tenPerson.setFaceImage(faceImageFileName); - - -// tenPerson.setFaceImage(orgImageFileName); + tenPerson.setFaceImage(orgImageFileName); //-------------------------------------------------------------------- //--------------------------------处理图片大小流的方式------------------------------------------------------ - if (tenPerson.getOrgImage() != null && !tenPerson.getOrgImage().isEmpty()) { -// String orgFileStr = "/root/minio/data/cell/" + tenPerson.getOrgImage(); -// String orgFileStr = "/home/server001/minio/data/cell/"+ tenPerson.getOrgImage(); - InputStream is = null; - InputStream orgInputStream = null; - try { - orgInputStream = minioClient.getObject(minioConfig.getBucketName(), tenPerson.getOrgImage()); - BufferedImage sourceImg = ImageIO.read(orgInputStream); - int w = sourceImg.getWidth(); - int h = sourceImg.getHeight(); - if (w > 1080 || h > 1080) { - sourceImg = ThumbnailsUtils.resizeImageOne(sourceImg,1080,1080); - byte[] data = ImageUtils.imageToBytes(sourceImg); - is = new ByteArrayInputStream(data); - int rl = is.available(); - PutObjectOptions putObjectOptionsResize = new PutObjectOptions(rl, -1L); - putObjectOptionsResize.setContentType("image/jpeg"); - this.minioClient.putObject(this.minioConfig - .getBucketName(), tenPerson.getOrgImage(), is, putObjectOptionsResize); - } - } catch (Exception e) { - log.error(e.getMessage()); - } finally { - if(is!=null){ - is.close(); - } - if(orgInputStream!=null){ - orgInputStream.close(); - } - } - } -//--------------------------------处理图片大小------------------------------------------------------ - - -//--------------------------------处理图片大小------------------------------------------------------ // if (tenPerson.getOrgImage() != null && !tenPerson.getOrgImage().isEmpty()) { -// String orgFileStr = "/root/minio/data/cell/" + tenPerson.getOrgImage(); +//// String orgFileStr = "/root/minio/data/cell/" + tenPerson.getOrgImage(); //// String orgFileStr = "/home/server001/minio/data/cell/"+ tenPerson.getOrgImage(); +// InputStream is = null; +// InputStream orgInputStream = null; // try { -// File picture = new File(orgFileStr); -// BufferedImage sourceImg = ImageIO.read(new FileInputStream(picture)); +// orgInputStream = minioClient.getObject(minioConfig.getBucketName(), tenPerson.getOrgImage()); +// BufferedImage sourceImg = ImageIO.read(orgInputStream); // int w = sourceImg.getWidth(); // int h = sourceImg.getHeight(); // if (w > 1080 || h > 1080) { -// Thumbnails.of(orgFileStr) -// .size(1080, 1080) -// .toFile(orgFileStr); +// sourceImg = ThumbnailsUtils.resizeImageOne(sourceImg,1080,1080); +// byte[] data = ImageUtils.imageToBytes(sourceImg); +// is = new ByteArrayInputStream(data); +// int rl = is.available(); +// PutObjectOptions putObjectOptionsResize = new PutObjectOptions(rl, -1L); +// putObjectOptionsResize.setContentType("image/jpeg"); +// this.minioClient.putObject(this.minioConfig +// .getBucketName(), tenPerson.getOrgImage(), is, putObjectOptionsResize); // } // } catch (Exception e) { // log.error(e.getMessage()); +// } finally { +// if(is!=null){ +// is.close(); +// } +// if(orgInputStream!=null){ +// orgInputStream.close(); +// } // } // } //--------------------------------处理图片大小------------------------------------------------------ - } catch (Exception e) { - e.printStackTrace(); - tenPerson.setStatus(Constant.PESON_SUATUS_NOMOR); - log.error("上传图片失败" + e.getMessage()); - continue; + } catch (Exception e) { + e.printStackTrace(); + tenPerson.setStatus(Constant.PESON_SUATUS_NOMOR); + log.error("上传图片失败" + e.getMessage()); + continue; + } } + + tenPerson.setFeature(personModel.getFeature()); tenPersonDao.insert(tenPerson); + //特征保存到内存 + if(tenPerson.getFeature()!=null && tenPerson.getFeature().length()>0){ + UserRamCache.UserInfo userInfo = new UserCompareInfo(); + userInfo.setFaceId(tenPerson.getPersonId()+""); + userInfo.setName(tenPerson.getName()); + userInfo.setFaceFeature(Base64.getDecoder().decode(tenPerson.getFeature())); + UserRamCache.addUser(userInfo); + log.debug("内存增加人员:"+tenPerson.getPersonId()+" 姓名:"+tenPerson.getName()); + } //门禁表 // if (personModel.getDoorCard() != null && personModel.getDoorCard().length() > 0) { @@ -2109,39 +2176,39 @@ public class TenPersonServiceImpl implements TenPersonService { //添加到同步表, - List devList = tenDeviceService.findByCellId(cellEntity.getCellId()); - for (TenDeviceVo dev : devList) { - TenPersonSyncEntity syncEntity = new TenPersonSyncEntity(); - syncEntity.setPersonId(tenPerson.getPersonId()); - syncEntity.setTenantId(tenPerson.getTenantId()); - syncEntity.setDeviceSn(dev.getSn()); - syncEntity.setDeviceId(dev.getDeviceId()); - syncEntity.setState(1); - syncEntity.setLastUpdateTime(tenPerson.getLastUpdateTime()); - tenPersonSyncService.insert(syncEntity); - } +// List devList = tenDeviceService.findByCellId(tenPerson.getCellId()); +// for (TenDeviceVo dev : devList) { +// TenPersonSyncEntity syncEntity = new TenPersonSyncEntity(); +// syncEntity.setPersonId(tenPerson.getPersonId()); +// syncEntity.setTenantId(tenPerson.getTenantId()); +// syncEntity.setDeviceSn(dev.getSn()); +// syncEntity.setDeviceId(dev.getDeviceId()); +// syncEntity.setState(1); +// syncEntity.setLastUpdateTime(tenPerson.getLastUpdateTime()); +// tenPersonSyncService.insert(syncEntity); +// } } } //下发设备通知 - List devList = tenDeviceService.findByCellId(cellId); - for (TenDeviceVo deviceVo : devList) { - List operationList = tenPersonSyncService.findDeviceAllAddPersons(deviceVo.getDeviceId(), deviceVo.getTenantId()); - List voList = new ArrayList<>(); - for (TenPersonSyncEntity syncEntity : operationList) { - TenPersonOperationVo vo = new TenPersonOperationVo(); - vo.setUid(syncEntity.getPersonId()); - vo.setOperation(syncEntity.getState()); - vo.setLast_update_stamp(syncEntity.getLastUpdateTime()); - voList.add(vo); - } - - int flag = serverApiService.personOperation(deviceVo.getSn(), voList); - if (flag == 0) { - //下发成功,删除状态为删除的同步人员 -// tenPersonSyncService.removeAllDeletePersons(deviceEntity.getDeviceId(),tenantId); - } - } +// List devList = tenDeviceService.findByCellId(cellId); +// for (TenDeviceVo deviceVo : devList) { +// List operationList = tenPersonSyncService.findDeviceAllAddPersons(deviceVo.getDeviceId(), deviceVo.getTenantId()); +// List voList = new ArrayList<>(); +// for (TenPersonSyncEntity syncEntity : operationList) { +// TenPersonOperationVo vo = new TenPersonOperationVo(); +// vo.setUid(syncEntity.getPersonId()); +// vo.setOperation(syncEntity.getState()); +// vo.setLast_update_stamp(syncEntity.getLastUpdateTime()); +// voList.add(vo); +// } +// +// int flag = serverApiService.personOperation(deviceVo.getSn(), voList); +// if (flag == 0) { +// //下发成功,删除状态为删除的同步人员 +//// tenPersonSyncService.removeAllDeletePersons(deviceEntity.getDeviceId(),tenantId); +// } +// } } @@ -2416,4 +2483,58 @@ public class TenPersonServiceImpl implements TenPersonService { public List findByIdCardAndDept(String idCard, Long deptId) { return tenPersonDao.findByIdCardAndDept(idCard,deptId); } + + @Override + public List listPage(int start, int count) { + return tenPersonDao.listPage(start, count); + } + + @Override + public int findCount() { + return tenPersonDao.findCount(); + } + + @Override + public TenLabelEntity findLabelByName(String name, String tenantId) { + return tenLabelService.findLabelByName(name,tenantId); + } + + @Override + public int findByIdCardCount(String idCard, String tenantId) { + return tenPersonDao.findByIdCardCount(idCard, tenantId); + } + + @Override + public TenPersonEntity findByIcCardTop(String icCard, String tenantId) { + return tenPersonDao.findByIcCardTop(icCard, tenantId); + } + + @Override + public List findByIdCardList(String idCard, String tenantId) { + return tenPersonDao.findByIdCardList(idCard, tenantId); + } + + @Override + @Transactional(rollbackFor = Exception.class) + @CacheEvict(value = "TenPerson", allEntries = true) + public int saveByIdCard(TenPersonEntity entity) { + int flag = tenPersonDao.insert(entity); + return 1; + } + + + + + @Override + @Transactional(rollbackFor = Exception.class) + @CacheEvict(value = "TenPerson", allEntries = true) + public int updateByIdCard(TenPersonEntity entity) { + int flag = tenPersonDao.updateById(entity); + return 1; + } + + @Override + public List getAllIdCard(String tenantId) { + return tenPersonDao.getAllIdCard(tenantId); + } } diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenRecordServiceImpl.java b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenRecordServiceImpl.java index b288225..64ecc0e 100644 --- a/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenRecordServiceImpl.java +++ b/shapelight-admin/src/main/java/net/shapelight/modules/ten/service/impl/TenRecordServiceImpl.java @@ -9,6 +9,7 @@ import net.shapelight.common.utils.*; //import net.shapelight.modules.dev.mqtt.CmdProcess; //import net.shapelight.modules.dev.mqtt.EmqHttpApi; import net.shapelight.modules.ten.dao.TenBuildDao; +import net.shapelight.modules.ten.dao.TenLabelDao; import net.shapelight.modules.ten.entity.*; import net.shapelight.modules.ten.service.*; import net.shapelight.modules.vo.TenRecordVo; @@ -32,7 +33,7 @@ import org.springframework.transaction.annotation.Transactional; @Service("tenRecordService") -public class TenRecordServiceImpl implements TenRecordService { +public class TenRecordServiceImpl implements TenRecordService { @Autowired private TenCellService tenCellService; @@ -105,6 +106,7 @@ public class TenRecordServiceImpl implements TenRecordService { } TenCellEntity cell = tenCellService.getById(rec.getCellId()); person.setCellName(cell.getName()); + person.setIdCard(rec.getIdCard()); }else{ if(person.getDeptId()!=null){ @@ -475,4 +477,83 @@ public class TenRecordServiceImpl implements TenRecordService { } return new PageUtils(page); } + + @Override + public boolean saveServer(TenRecordEntity entity) { + long id = new SnowflakeIdWorker().nextId(); + entity.setRecordId(id); + int flag = tenRecordDao.insert(entity); + if (flag == 1) { + //推送到web实时刷新 + publishRecordToWeb(entity); + return true; + } + return false; + } + + @Override + public List getDaysIntervalRecords(String days, String tenantId) { + return tenRecordDao.getDaysIntervalRecords(days, tenantId); + } + + @Override + public void deleteDaysIntervalRecords(String days, String tenantId) { + tenRecordDao.deleteDaysIntervalRecords(days, tenantId); + } + + @Override + public List findListAll(Map params) { + List cellIds = new ArrayList<>(); + String cellId = (String) params.get("cellId"); + if (cellId != null && !cellId.isEmpty()) { + Long cellLong = Long.parseLong(cellId); + cellIds.add(cellLong); + } else { + List cells = tenCellService.queryAll(params); + for (TenCellEntity cell : cells) { + cellIds.add(cell.getCellId()); + } + } + if (cellIds.size() == 0) { + return new ArrayList<>(); + } + List page = tenRecordDao.findListAll(cellIds, params); + + for (TenRecordEntity rec : page) { + TenDeviceEntity dev = tenDeviceService.findBySn(rec.getDeviceSn()); + if(dev == null){ + rec.setDeviceName(rec.getDeviceSn()); + rec.setGateFlag(0); + }else{ + rec.setDeviceName(dev.getName()); + rec.setGateFlag(dev.getGateFlag()); + } + TenPersonEntity person = tenPersonService.getById(rec.getPersonId(), rec.getCellId()); + if (person == null) { + person = new TenPersonEntity(); + TenRoomEntity room = tenRoomService.getById(rec.getRoomId(),rec.getCellId()); + if(room!=null){ + person.setRoomName(room.getRoomName()); + TenBuildEntity build = tenBuildService.getById(room.getBuildId(),room.getCellId()); + person.setBuildName(build.getName()); + person.setBuildUnit(build.getUnit()); + } + TenCellEntity cell = tenCellService.getById(rec.getCellId()); + person.setCellName(cell.getName()); + person.setIdCard(rec.getIdCard()); + + }else{ + if(person.getDeptId()!=null){ + TenCellDeptEntity dept = tenCellDeptService.getById(person.getDeptId()); + if(dept!=null){ + person.setDeptName(dept.getName()); + String deptAllName = tenCellDeptService.getAllParentName(dept.getDeptId()); + person.setDeptAllName(deptAllName); + } + } + } + rec.setPerson(person); + } + return page; + } } diff --git a/shapelight-admin/src/main/java/net/shapelight/modules/vo/TenUserVo.java b/shapelight-admin/src/main/java/net/shapelight/modules/vo/TenUserVo.java index 69d1510..efa111d 100644 --- a/shapelight-admin/src/main/java/net/shapelight/modules/vo/TenUserVo.java +++ b/shapelight-admin/src/main/java/net/shapelight/modules/vo/TenUserVo.java @@ -50,4 +50,5 @@ public class TenUserVo { private Integer featureType; + } diff --git a/shapelight-admin/src/main/resources/4145009_c.shapelight.net.pfx b/shapelight-admin/src/main/resources/4145009_c.shapelight.net.pfx deleted file mode 100644 index b8ecf01..0000000 Binary files a/shapelight-admin/src/main/resources/4145009_c.shapelight.net.pfx and /dev/null differ diff --git a/shapelight-admin/src/main/resources/5362545_c.xitu3d.com.pfx b/shapelight-admin/src/main/resources/5362545_c.xitu3d.com.pfx deleted file mode 100644 index 15b7ff7..0000000 Binary files a/shapelight-admin/src/main/resources/5362545_c.xitu3d.com.pfx and /dev/null differ diff --git a/shapelight-admin/src/main/resources/7478041_c.xitu3d.com.pfx b/shapelight-admin/src/main/resources/7478041_c.xitu3d.com.pfx deleted file mode 100644 index 6876bd1..0000000 Binary files a/shapelight-admin/src/main/resources/7478041_c.xitu3d.com.pfx and /dev/null differ diff --git a/shapelight-admin/src/main/resources/application-dev.yml b/shapelight-admin/src/main/resources/application-dev.yml index 3120f31..c0dfdd4 100644 --- a/shapelight-admin/src/main/resources/application-dev.yml +++ b/shapelight-admin/src/main/resources/application-dev.yml @@ -3,14 +3,11 @@ spring: type: com.alibaba.druid.pool.DruidDataSource druid: driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://192.168.10.20:3306/cell_db_v10_pv_jd?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&rewriteBatchedStatements=true + url: jdbc:mysql://192.168.10.20:3306/cell_db_v10_pv_xianyang2?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&rewriteBatchedStatements=true username: user password: user@server001 -# url: jdbc:mysql://39.96.9.232:3306/cell_db_v8_http?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&rewriteBatchedStatements=true -# username: rootuser -# password: xtzg_db_USER@0325 - initial-size: 50 - max-active: 110 + initial-size: 150 + max-active: 1110 min-idle: 31 max-wait: 110000 pool-prepared-statements: true @@ -39,284 +36,3 @@ spring: wall: config: multi-statement-allow: true - - -#sharding.jdbc: -# data-sources: -# ds_master: -# driver-class-name: com.mysql.cj.jdbc.Driver -# url: jdbc:mysql://localhost:3306/cell_db?useUnicode=true&characterEncoding=utf-8&useSSL=true -# username: root -# password: root -# ds_slave_0: -# driver-class-name: com.mysql.cj.jdbc.Driver -# url: jdbc:mysql://localhost:3306/cell_db_0?useUnicode=true&characterEncoding=utf-8&useSSL=true -# username: root -# password: root -# master-slave-rule: -# name: ds_ms -# master-data-source-name: ds_master -# slave-data-source-names: ds_slave_0 -# load-balance-algorithm-type: round_robin - - - -#mybatis-plus: -# mapper-locations: classpath*:/com/hjc/sharding/*/mapper/xml/*Mapper.xml -# #实体扫描,多个package用逗号或者分号分隔 -# typeAliasesPackage: com.hjc.sharding.*.entity -# global-config: -# #主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID"; -# id-type: 2 -# #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断" -# field-strategy: 2 -# #驼峰下划线转换 -# db-column-underline: true -# #刷新mapper 调试神器 -# refresh-mapper: true -# #数据库大写下划线转换 -# #capital-mode: true -# #序列接口实现类配置 -# #key-generator: com.baomidou.springboot.xxx -# #逻辑删除配置(下面3个配置) -# logic-delete-value: 0 -# logic-not-delete-value: 1 -# #自定义SQL注入器 -# #sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector -# #自定义填充策略接口实现 -# #meta-object-handler: com.baomidou.springboot.xxx -# configuration: -# map-underscore-to-camel-case: true -# cache-enabled: fals - - - - -#sharding: -# jdbc: -# datasource: -# names: ds0 -# # 数据源ds0 -# ds0: -# type: com.alibaba.druid.pool.DruidDataSource -# driver-class-name: com.mysql.cj.jdbc.Driver -# url: jdbc:mysql://localhost:3306/cell_db -# username: root -# password: root -# config: -# sharding: -# props: -# sql.show: true -# tables: -# ten_person: #t_user表 -# key-generator-column-name: id #主键 -# actual-data-nodes: ds0.ten_person${0..1} #数据节点,均匀分布 -# table-strategy: #分表策略 -# inline: #行表达式 -# sharding-column: id -# algorithm-expression: ten_person${id % 2} #按模运算分配 - - - - -#spring: -# shardingsphere: -# datasource: -# names: ds0,ds1 -# ds0: -# type: com.alibaba.druid.pool.DruidDataSource -# driver-class-name: com.mysql.cj.jdbc.Driver -# jdbc-url: jdbc:mysql://localhost:3306/cell_db -# username: root -# password: root -# ds1: -# type: com.alibaba.druid.pool.DruidDataSource -# driver-class-name: com.mysql.cj.jdbc.Driver -# jdbc-url: jdbc:mysql://localhost:3306/cell_db_0 -# username: root -# password: root -# sharding: -# tables: -# t_order: -# actual-data-nodes: ds$->{0..1}.t_order$->{0..1} -# ## 指定分库规则 -# database-strategy: -# inline: -# sharding-column: user_id -# algorithm-expression: ds$->{user_id % 2} -# ## 指定分表规则 -# table-strategy: -# inline: -# sharding-column: order_id -# algorithm-expression: t_order$->{order_id % 2} -# -# t_order_item: -# actual-data-nodes: ds$->{0..1}.t_order_item$->{0..1} -# ## 通过hint方式自定义分库规则 -# database-strategy: -# hint: -# algorithmClassName: com.hujy.demo.hint.HintSharding -# ## 指定分表规则 -# table-strategy: -# inline: -# sharding-column: order_id -# algorithm-expression: t_order_item$->{order_id % 2} -# ## 生成分布式主键 -# key-generator: -# column: item_id -# type: SNOWFLAKE -# -# ## 绑定主表与子表,避免关联查询导致的全数据源路由 -# binding-tables: t_order,t_order_item -# -# ## 配置广播表:以广播的形式保存(如果只涉及查询的话可以不配置,会随机取一个数据源) -# broadcast-tables: t_config -# -# ## 打印sql -# props: -# sql: -# show: true - - - - -#spring: -# datasource: -# # 数据源:shard_one -# dataOne: -# type: com.alibaba.druid.pool.DruidDataSource -# druid: -# driver-class-name: com.mysql.cj.jdbc.Driver -# url: jdbc:mysql://localhost:3306/cell_db?useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false -# username: root -# password: root -# initial-size: 10 -# max-active: 100 -# min-idle: 10 -# max-wait: 60000 -# pool-prepared-statements: true -# max-pool-prepared-statement-per-connection-size: 20 -# time-between-eviction-runs-millis: 60000 -# min-evictable-idle-time-millis: 300000 -# max-evictable-idle-time-millis: 60000 -# validation-query: SELECT 1 FROM DUAL -# # validation-query-timeout: 5000 -# test-on-borrow: false -# test-on-return: false -# test-while-idle: true -# connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 -# # 数据源:shard_two -# dataTwo: -# type: com.alibaba.druid.pool.DruidDataSource -# druid: -# driverClassName: com.mysql.jdbc.Driver -# url: jdbc:mysql://localhost:3306/cell_db?useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false -# username: root -# password: root -# initial-size: 10 -# max-active: 100 -# min-idle: 10 -# max-wait: 60000 -# pool-prepared-statements: true -# max-pool-prepared-statement-per-connection-size: 20 -# time-between-eviction-runs-millis: 60000 -# min-evictable-idle-time-millis: 300000 -# max-evictable-idle-time-millis: 60000 -# validation-query: SELECT 1 FROM DUAL -# # validation-query-timeout: 5000 -# test-on-borrow: false -# test-on-return: false -# test-while-idle: true -# connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 -# # 数据源:shard_three -# dataThree: -# type: com.alibaba.druid.pool.DruidDataSource -# druid: -# driverClassName: com.mysql.jdbc.Driver -# url: jdbc:mysql://localhost:3306/cell_db?useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false -# username: root -# password: root -# initial-size: 10 -# max-active: 100 -# min-idle: 10 -# max-wait: 60000 -# pool-prepared-statements: true -# max-pool-prepared-statement-per-connection-size: 20 -# time-between-eviction-runs-millis: 60000 -# min-evictable-idle-time-millis: 300000 -# max-evictable-idle-time-millis: 60000 -# validation-query: SELECT 1 FROM DUAL -# # validation-query-timeout: 5000 -# test-on-borrow: false -# test-on-return: false -# test-while-idle: true -# connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 - - - - -#sharding: -# jdbc: -# type: com.alibaba.druid.pool.DruidDataSource -# driverClassName: com.mysql.cj.jdbc.Driver -# url: jdbc:mysql://localhost:3306/cell_db?useUnicode=true&characterEncoding=UTF-8 -# username: root -# password: root -# connectionProperties: config.decrypt=true;druid.stat.slowSqlMillis=3000;druid.stat.logSlowSql=true;druid.stat.mergeSql=true -# filters: stat -# maxActive: 100 -# initialSize: 1 -# maxWait: 15000 -# minIdle: 1 -# timeBetweenEvictionRunsMillis: 30000 -# minEvictableIdleTimeMillis: 180000 -# validationQuery: SELECT 'x' -# testWhileIdle: true -# testOnBorrow: false -# testOnReturn: false -# poolPreparedStatements: false -# maxPoolPreparedStatementPerConnectionSize: 20 -# removeAbandoned: true -# removeAbandonedTimeout: 600 -# logAbandoned: false -# connectionInitSqls: - -#mybatis-plus: -# # config-location: classpath:mybatis-config.xml -# mapper-locations: classpath*:mapper/*.xml -# type-aliases-package: net.shapelight.modules.*.entity -# global-config: -# id-type: 3 #1:数据库ID自增 2:用户输入id 3:全局唯一id(IdWorker) 4:全局唯一ID(uuid) -# db-column-underline: false -# refresh-mapper: true -# configuration: -# map-underscore-to-camel-case: true -# cache-enabled: true #配置的缓存的全局开关 -# lazyLoadingEnabled: true #延时加载的开关 -# multipleResultSetsEnabled: true #开启的话,延时加载一个属性时会加载该对象全部属性,否则按需加载属性 -# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql语句,调试用 - -#spring: -# shardingsphere: -# datasource: -# names: m1 #配置库的名字,随意 -# m1: #配置目前m1库的数据源信息 -# type: com.alibaba.druid.pool.DruidDataSource -# driverClassName: com.mysql.cj.jdbc.Driver -# url: jdbc:mysql://localhost:3306/cell_db?useUnicode=true&characterEncoding=UTF-8 -# username: root -# password: root -# sharding: -# tables: -# t_order: # 指定t_order表的数据分布情况,配置数据节点 -# actualDataNodes: m1.sys_db_bak_$->{1..2} -# tableStrategy: -# inline: # 指定t_order表的分片策略,分片策略包括分片键和分片算法 -# shardingColumn: id -# algorithmExpression: sys_db_bak_$->{order_id % 2 + 1} -# keyGenerator: # 指定t_order表的主键生成策略为SNOWFLAKE -# type: SNOWFLAKE #主键生成策略为SNOWFLAKE -# column: id #指定主键 -# props: -# sql: -# show: truearticle/details/103767507 diff --git a/shapelight-admin/src/main/resources/application.yml b/shapelight-admin/src/main/resources/application.yml index b09c296..8dcee26 100644 --- a/shapelight-admin/src/main/resources/application.yml +++ b/shapelight-admin/src/main/resources/application.yml @@ -5,11 +5,11 @@ server: max-threads: 1000 min-spare-threads: 30 max-connections: 2000 - port: 8018 + port: 9018 servlet: context-path: /cell http: - port: 8019 + port: 9019 # ssl: # key-store: classpath:4145009_c.shapelight.net.pfx # key-store-password: 8n8bU823 @@ -31,7 +31,7 @@ spring: enabled: true file-size-threshold: 1000MB redis: - database: 10 + database: 4 host: 192.168.10.20 port: 6379 password: 123456 # 密码(默认为空) @@ -42,23 +42,6 @@ spring: max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制) max-idle: 10 # 连接池中的最大空闲连接 min-idle: 5 # 连接池中的最小空闲连接 -# freemarker: -# suffix: .html -# request-context-attribute: request -# mvc: -# throw-exception-if-no-handler-found: true - mqtt: - username: admin - password: public - url: tcp://192.168.50.232:1883 - keepAliveInterval: 10 - client: - id: web-server - default: - topic: topic - api: http://192.168.50.232:8081 - - mvc: static-path-pattern: /files/** async: @@ -90,28 +73,18 @@ global: secretKey: admin@C501 bucketName: cell path: /root/minio/data/cell -# minio: -# endpoint: https://c.xitu3d.com:19000 -# port: 19000 -# accessKey: 7885444af42e4b30c518c5be17c8850b -# secretKey: 0fad3477fb9f60c7be75561db967e8d7 -# bucketName: cell device: appId: 8e9b941923abd appSecret: Mjk0ODIxOTcwMTQ0NjkwNzA1NDE0MzcyNjgxMTQ0MDc0MjE -# endpoint: https://c.shapelight.net:19000 -# port: 9000 -# accessKey: 7885444af42e4b30c518c5be17c8850b -# secretKey: 0fad3477fb9f60c7be75561db967e8d7 -# bucketName: cell wx: appid: wxf59991f23f1f5500 secret: 30b523b2bdd7b0739b7f06e9dc1519f8 tcp_server: - port: 8086 + port: 9017 app: key: 9894480ac52e4 secret: Mjk0ODUzNzA2Mzk3NzEzMjU2OTIwOTk1NzUzMDI5MTQwNDI + tenantId: 836266616957173761 shapelight: cluster: false #集群配置 true集群环境 false单机环境,还需打开pom.xml里的spring-session-data-redis注释 @@ -128,6 +101,18 @@ shapelight: # token有效时长,180天,单位秒 #expire: 15552000 header: token +# sdk配置--------------------------------------- +config: + arcface-sdk: + version: 4.1 + app-id: DEnAZa1bWXcaAxyWUg33QZaKCmMkNmrQxuKZJQGmZsHJ + sdk-key: vWbvUyStZeartSaM6QoTzPYWFpSaj4uhfDmRifSzCd6 + active-key: 82G1-11QA-713Y-8NB4 + active-file: + detect-pool-size: 5 + compare-pool-size: 5 + rec-face-thd: 0.8 + rec-id-thd: 0.5 #mybatis diff --git a/shapelight-admin/src/main/resources/libs/4.1/LINUX64/libarcsoft_face.so b/shapelight-admin/src/main/resources/libs/4.1/LINUX64/libarcsoft_face.so new file mode 100644 index 0000000..b4c51b2 Binary files /dev/null and b/shapelight-admin/src/main/resources/libs/4.1/LINUX64/libarcsoft_face.so differ diff --git a/shapelight-admin/src/main/resources/libs/4.1/LINUX64/libarcsoft_face_engine.so b/shapelight-admin/src/main/resources/libs/4.1/LINUX64/libarcsoft_face_engine.so new file mode 100644 index 0000000..cad9ed2 Binary files /dev/null and b/shapelight-admin/src/main/resources/libs/4.1/LINUX64/libarcsoft_face_engine.so differ diff --git a/shapelight-admin/src/main/resources/libs/4.1/LINUX64/libarcsoft_face_engine_jni.so b/shapelight-admin/src/main/resources/libs/4.1/LINUX64/libarcsoft_face_engine_jni.so new file mode 100644 index 0000000..e61ecf4 Binary files /dev/null and b/shapelight-admin/src/main/resources/libs/4.1/LINUX64/libarcsoft_face_engine_jni.so differ diff --git a/shapelight-admin/src/main/resources/libs/4.1/WIN64/libarcsoft_face.dll b/shapelight-admin/src/main/resources/libs/4.1/WIN64/libarcsoft_face.dll new file mode 100644 index 0000000..d0a4c97 Binary files /dev/null and b/shapelight-admin/src/main/resources/libs/4.1/WIN64/libarcsoft_face.dll differ diff --git a/shapelight-admin/src/main/resources/libs/4.1/WIN64/libarcsoft_face_engine.dll b/shapelight-admin/src/main/resources/libs/4.1/WIN64/libarcsoft_face_engine.dll new file mode 100644 index 0000000..db65b00 Binary files /dev/null and b/shapelight-admin/src/main/resources/libs/4.1/WIN64/libarcsoft_face_engine.dll differ diff --git a/shapelight-admin/src/main/resources/libs/4.1/WIN64/libarcsoft_face_engine_jni.dll b/shapelight-admin/src/main/resources/libs/4.1/WIN64/libarcsoft_face_engine_jni.dll new file mode 100644 index 0000000..0266b32 Binary files /dev/null and b/shapelight-admin/src/main/resources/libs/4.1/WIN64/libarcsoft_face_engine_jni.dll differ diff --git a/shapelight-admin/src/main/resources/mapper/ten/TenDeviceDao.xml b/shapelight-admin/src/main/resources/mapper/ten/TenDeviceDao.xml index de3994c..9d1a0e9 100644 --- a/shapelight-admin/src/main/resources/mapper/ten/TenDeviceDao.xml +++ b/shapelight-admin/src/main/resources/mapper/ten/TenDeviceDao.xml @@ -9,4 +9,12 @@ + + + + diff --git a/shapelight-admin/src/main/resources/mapper/ten/TenDeviceLabelDao.xml b/shapelight-admin/src/main/resources/mapper/ten/TenDeviceLabelDao.xml new file mode 100644 index 0000000..38cbc9f --- /dev/null +++ b/shapelight-admin/src/main/resources/mapper/ten/TenDeviceLabelDao.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/shapelight-admin/src/main/resources/mapper/ten/TenPersonDao.xml b/shapelight-admin/src/main/resources/mapper/ten/TenPersonDao.xml index 3e75544..49c37af 100644 --- a/shapelight-admin/src/main/resources/mapper/ten/TenPersonDao.xml +++ b/shapelight-admin/src/main/resources/mapper/ten/TenPersonDao.xml @@ -57,6 +57,11 @@ + + + + + feature_type, + + feature, + + + + ic, + + + householder, + + + relation, + @@ -433,6 +451,20 @@ #{featureType}, + + #{feature}, + + + + #{ic}, + + + #{householder}, + + + #{relation}, + + @@ -597,6 +629,19 @@ feature_type = #{featureType}, + + feature = #{feature}, + + + + ic = #{ic}, + + + householder = #{householder}, + + + relation = #{relation}, + @@ -1026,6 +1071,7 @@ where person_type = 5005 and live_end < NOW() and delete_flag = 0 + and status = 0 @@ -1306,5 +1352,37 @@ and id_card = #{idCard} + + + + + + + + + + + + diff --git a/shapelight-admin/src/main/resources/mapper/ten/TenRecordDao.xml b/shapelight-admin/src/main/resources/mapper/ten/TenRecordDao.xml index 012d62e..a926c4f 100644 --- a/shapelight-admin/src/main/resources/mapper/ten/TenRecordDao.xml +++ b/shapelight-admin/src/main/resources/mapper/ten/TenRecordDao.xml @@ -34,6 +34,9 @@ + + + @@ -107,6 +110,12 @@ camera_param, + + id_card, + + + name, + @@ -177,6 +186,12 @@ #{cameraParam}, + + #{idCard}, + + + #{name}, + @@ -227,6 +242,13 @@ xa_sync_image = #{xaSyncImage,jdbcType=TINYINT}, + + + id_card = #{idCard,jdbcType=VARCHAR}, + + + name = #{idCard,jdbcType=VARCHAR}, + where record_id = #{recordId,jdbcType=BIGINT} @@ -291,9 +313,6 @@ select r.* from ten_record_${params.tenantId} r - - left join ten_person t on r.person_id = t.person_id - where 1 = 1 and r.cell_id = #{params.cellId} @@ -304,6 +323,9 @@ and `name` like CONCAT('%', '${params.name}', '%') + + and `id_card` like CONCAT('%', '${params.idCard}', '%') + and `record_time` >= #{params.recordTimeStart} @@ -321,6 +343,37 @@ + + + + - + + delete from ten_record_${tenantId} + where DATE_SUB(CURDATE(), INTERVAL #{days} DAY) > record_time + diff --git a/shapelight-admin/src/test/java/gb/BinTest.java b/shapelight-admin/src/test/java/gb/BinTest.java index 9387224..958d3b9 100644 --- a/shapelight-admin/src/test/java/gb/BinTest.java +++ b/shapelight-admin/src/test/java/gb/BinTest.java @@ -1,11 +1,10 @@ package gb; import net.shapelight.modules.sys.service.SysDeviceLogService; +import org.apache.commons.io.FileUtils; -import java.io.ByteArrayOutputStream; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; +import java.time.LocalTime; import java.util.Base64; public class BinTest { @@ -47,13 +46,55 @@ public class BinTest { return new String(buf); } + + + + public static void listFiles(File srcDir){ + File[] files = srcDir.listFiles(); //列出所有的子文件 + for(File file :files) + { + if(file.isFile())//如果是文件,则输出文件名字 + { + String fileName = file.getAbsolutePath(); + //判断jpg图片 +// if (fileName.endsWith("jpg") || fileName.endsWith("jpeg") || fileName.endsWith("png")) + { + System.out.println(fileName); + +// try { +// String newName = fileName.substring(0,fileName.lastIndexOf(".jpg")); +// FileUtils.copyFile(file, new File(newName)); +// FileUtils.deleteQuietly(file); +// }catch (Exception e){ +// e.printStackTrace(); +// } + + + } + }else if(file.isDirectory())//如果是文件夹,则输出文件夹的名字,并递归遍历该文件夹 + { + listFiles(file);//递归遍历 + } + } + } public static void main(String args[]){ - String url = "/home/huangyifang/tempFiles/33.jpg"; - byte[] bin = getImageByte(url); +// String url = "/home/huangyifang/tempFiles/33.jpg"; +// byte[] bin = getImageByte(url); +// +// String binStr = bytesToHex2(bin); +// System.out.println(binStr); - String binStr = bytesToHex2(bin); - System.out.println(binStr); +// LocalTime start = LocalTime.of(9, 0); // 时间段开始时间 +// LocalTime end = LocalTime.of(18, 0); // 时间段结束时间 +// LocalTime time = LocalTime.now(); // 当前时间 +// +// boolean isWithinRange = time.isAfter(start) && time.isBefore(end); // 判断当前时间是否在时间段内 +// +// System.out.println(isWithinRange); + String fileDirName = "/home/huangyifang/gb/咸阳师范/信息录入正式材料 - 最新/信息录入正式材料"; + File fileDir = new File(fileDirName); + listFiles(fileDir); } diff --git a/version10.txt b/version10.txt new file mode 100644 index 0000000..e7b73a1 --- /dev/null +++ b/version10.txt @@ -0,0 +1,129 @@ +v4.0 +1.sys_device_type表 启用other字段,0表示2d,1表示3d,v4.0加入,空表示2d +2.ten_device表增加两个字段,识别阈值:recognize_score_3d,检测方式:detection_type +3.ten_person表增加5个字段:depth,face_model,source_file,camera_param +4.ten_record表增加8个字段:depth,source_file,duration,threshold,distance,score3d,temperature,camera_param + + +v4.0 数据库修改内容 +alter table ten_device_copy1 +ADD COLUMN recognize_score3d varchar(30) DEFAULT '62,65' COMMENT '3d识别阈值', +ADD COLUMN detection_type tinyint(1) DEFAULT 0 COMMENT '0:默认2d检测, 1:3d检测'; + + +alter table ten_person_copy1 +ADD COLUMN depth varchar(200) COMMENT '深度图片', +ADD COLUMN face_model varchar(200) COMMENT '脸模', +ADD COLUMN source_file varchar(200) COMMENT '源文件', +ADD COLUMN camera_param varchar(200) COMMENT '相机参数'; + +alter table ten_record_9999999999999 +ADD COLUMN depth varchar(200) COMMENT '深度图片', +ADD COLUMN source_file varchar(200) COMMENT '源文件', +ADD COLUMN camera_param varchar(200) COMMENT '相机参数', +ADD COLUMN duration int(11) COMMENT '耗时', +ADD COLUMN threshold varchar(50) COMMENT '阈值', +ADD COLUMN distance float COMMENT '距离', +ADD COLUMN score3d varchar(50) COMMENT '分数', +ADD COLUMN temperature float COMMENT '体温'; + + + + + +------------------------v8.0 http协议版本,数据库更新说明:先执行以下sql语句,在跑批处理程序----------------- +1.ten_device表增加字段:app_language,lat,lon +2.ten_person表增加字段:thd_feature,dept_id +3.ten_person表person_type字段默认5000 +4.sys_menu表增加4条参数2001,2002,2003,2004 +5.ten_company表增加type_id字段关联 +6.ten_label表type字段类型修改为int +7.增加表 ten_cell_dept +8.增加表 ten_device_operate_log +9.增加表 ten_company_type +10.页面修改角色 + + + +alter table ten_device ADD COLUMN app_language tinyint(1) DEFAULT 0 COMMENT 'app版本'; +alter table ten_device ADD COLUMN lat varchar(50) DEFAULT '' COMMENT '纬度'; +alter table ten_device ADD COLUMN lon varchar(50) DEFAULT '' COMMENT '经度'; + +alter table ten_person ADD COLUMN thd_feature varchar(10240) COMMENT '3d特征'; +alter table ten_person ADD COLUMN dept_id bigint(20) COMMENT '部门id'; +alter table ten_person ALTER COLUMN person_type SET DEFAULT 5000; + +INSERT INTO `sys_menu` VALUES (2001, 3, '设备Log', 'sys/deviceLog', 'sys:devicelog', 1, 'shebei', 6, 'system_devicelog'); +INSERT INTO `sys_menu` VALUES (2002, 1210, '操作记录', 'ten/deviceoperatelog', 'ten:deviceoperatelog', 1, 'shebei', 6, 'tenant_deviceoperatelog'); +INSERT INTO `sys_menu` VALUES (2003, 1234, '组织管理', 'ten/celldept', 'ten:celldept', 1, 'shebei', 6, 'tenant_celldept'); +INSERT INTO `sys_menu` VALUES (2004, 1220, '单位类别', 'ten/companytype', 'ten:companytype', 1, 'shebei', 6, 'tenant_companytype'); + +alter table ten_company ADD COLUMN type_id bigint(20) COMMENT '类别id'; + +ALTER TABLE ten_label MODIFY COLUMN type INT(11); + +CREATE TABLE `ten_cell_dept` ( + `dept_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '部门/楼栋', + `parent_id` bigint(20) DEFAULT NULL COMMENT '父级目录', + `cell_id` bigint(20) NOT NULL COMMENT '小区ID', + `name` varchar(200) DEFAULT NULL COMMENT '名称', + `lable` varchar(100) DEFAULT NULL COMMENT '标签', + `lat` varchar(50) DEFAULT '' COMMENT '纬度', + `lon` varchar(50) DEFAULT '' COMMENT '经度', + `other` varchar(200) DEFAULT '' COMMENT '其他', + `remark` varchar(100) DEFAULT '' COMMENT '备注', + `picture` varchar(1024) DEFAULT '' COMMENT '照片', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `create_by` varchar(100) DEFAULT '' COMMENT '创建人', + `last_update_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', + `last_update_by` varchar(100) DEFAULT '' COMMENT '更新人', + `delete_flag` tinyint(1) DEFAULT '0' COMMENT '0未删除1删除', + `tenant_id` bigint(20) unsigned zerofill DEFAULT '00000000000000000000' COMMENT '运营商ID', + `xa_sync` tinyint(1) DEFAULT '0' COMMENT '第三方是否同步1是0否默认0', + `p_id` int(18) DEFAULT NULL COMMENT '地址序号', + `dzbm` varchar(100) DEFAULT NULL COMMENT '地址编码', + `is_room` tinyint(1) DEFAULT '0' COMMENT '是否是户室0否1是', + `room_type` tinyint(1) DEFAULT '0' COMMENT '类型:自住,出租', + PRIMARY KEY (`dept_id`) +) ENGINE=InnoDB AUTO_INCREMENT=37291 DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `ten_company_type` ( + `type_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `name` varchar(100) DEFAULT '' COMMENT '标签名称', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `create_by` varchar(100) DEFAULT '' COMMENT '创建人', + `last_update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `last_update_by` varchar(100) DEFAULT '' COMMENT '更新人', + `delete_flag` tinyint(1) DEFAULT '0' COMMENT '0未删除1删除', + `tenant_id` bigint(20) NOT NULL COMMENT '运营商ID', + PRIMARY KEY (`type_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=10033 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='标签'; + +CREATE TABLE `ten_device_operate_log` ( + `log_id` bigint(20) NOT NULL AUTO_INCREMENT, + `sn` varchar(100) DEFAULT NULL, + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `operation` varchar(200) DEFAULT NULL COMMENT '用户操作', + `tenant_id` bigint(20) DEFAULT NULL COMMENT '运营商Id', + PRIMARY KEY (`log_id`) +) ENGINE=InnoDB AUTO_INCREMENT=667 DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `sys_device_log` ( + `log_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `sn` varchar(50) DEFAULT NULL, + `create_time` datetime DEFAULT NULL, + `log` varchar(16000) DEFAULT NULL, + PRIMARY KEY (`log_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=418 DEFAULT CHARSET=utf8mb4; + + +------------------------v9.0 考勤版本----------------- +1.增加表ten_rule +2.增加表ten_schedule +3.增加表ten_check +4.增加表ten_check_schedule +5.menu表增加2010,2011,2012,2013,2014五条记录 + + +------------------------v10.0 服务器SDK版本----------------- +蓝本:cell-v9-check-face, http协议设备注册接口允许照片和压缩包为空