Merge branch 'master' of http://47.109.37.87:3000/by2025/SmartParks
# Conflicts: # ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/RocketMqConstants.java # ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/consumer/FaceCaptureConsumer.java # ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/consumer/FaceCompareConsumer.java
This commit is contained in:
@@ -140,6 +140,12 @@
|
||||
<version>3.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.drewnoakes</groupId>
|
||||
<artifactId>metadata-extractor</artifactId>
|
||||
<version>2.18.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
|
@@ -0,0 +1,75 @@
|
||||
package org.dromara.sis.config;
|
||||
|
||||
import org.apache.rocketmq.client.producer.DefaultMQProducer;
|
||||
import org.apache.rocketmq.spring.core.RocketMQTemplate;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author lsm
|
||||
* @apiNote RocketMQClusterConfig
|
||||
* @since 2025/8/26
|
||||
*/
|
||||
@Configuration
|
||||
public class RocketMQClusterConfig {
|
||||
|
||||
// 从配置文件中读取 cluster 的配置
|
||||
@Value("${rocketmq.cluster1.name-server}")
|
||||
private String nameServer1;
|
||||
|
||||
@Value("${rocketmq.cluster1.producer.group}")
|
||||
private String producerGroup1;
|
||||
|
||||
// 为第一个集群创建生产者实例
|
||||
@Bean({"clusterProducerOne"})
|
||||
public DefaultMQProducer clusterProducerOne() throws Exception {
|
||||
DefaultMQProducer producer = new DefaultMQProducer(producerGroup1);
|
||||
producer.setNamesrvAddr(nameServer1);
|
||||
// 设置发送超时时间
|
||||
producer.setSendMsgTimeout(5000);
|
||||
// 设置重试次数
|
||||
producer.setRetryTimesWhenSendFailed(2);
|
||||
producer.setRetryTimesWhenSendAsyncFailed(2);
|
||||
return producer;
|
||||
}
|
||||
|
||||
// 使用上面的生产者实例创建 RocketMQTemplate
|
||||
@Bean("rocketMQTemplateClusterOne")
|
||||
public RocketMQTemplate rocketMQTemplateClusterOne(@Qualifier("clusterProducerOne") DefaultMQProducer producer) {
|
||||
RocketMQTemplate template = new RocketMQTemplate();
|
||||
template.setProducer(producer);
|
||||
return template;
|
||||
}
|
||||
|
||||
|
||||
// 从配置文件中读取 cluster 的配置
|
||||
// @Value("${rocketmq.cluster2.name-server}")
|
||||
// private String nameServer2;
|
||||
//
|
||||
// @Value("${rocketmq.cluster2.producer.group}")
|
||||
// private String producerGroup2;
|
||||
//
|
||||
// // 为第二个集群创建生产者实例
|
||||
// @Bean({"clusterProducerTwo"})
|
||||
// public DefaultMQProducer clusterProducerTwo() throws Exception {
|
||||
// DefaultMQProducer producer = new DefaultMQProducer(producerGroup2);
|
||||
// producer.setNamesrvAddr(nameServer2);
|
||||
// // 设置发送超时时间
|
||||
// producer.setSendMsgTimeout(5000);
|
||||
// // 设置重试次数
|
||||
// producer.setRetryTimesWhenSendFailed(2);
|
||||
// producer.setRetryTimesWhenSendAsyncFailed(2);
|
||||
// return producer;
|
||||
// }
|
||||
//
|
||||
// // 使用上面的生产者实例创建 RocketMQTemplate
|
||||
// @Bean("rocketMQTemplateClusterTwo")
|
||||
// public RocketMQTemplate rocketMQTemplateClusterTwo(@Qualifier("clusterProducerTwo") DefaultMQProducer producer) {
|
||||
// RocketMQTemplate template = new RocketMQTemplate();
|
||||
// template.setProducer(producer);
|
||||
// return template;
|
||||
// }
|
||||
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
package org.dromara.sis.controller;
|
||||
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.date.DateField;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.sis.domain.bo.SisPersonLibImgBo;
|
||||
import org.dromara.sis.domain.vo.SisPersonLibImgVo;
|
||||
import org.dromara.sis.sdk.e8.E8PlatformApi;
|
||||
import org.dromara.sis.sdk.e8.domain.QueryDto;
|
||||
import org.dromara.sis.sdk.e8.domain.accessControl.req.AccessRecordFindReq;
|
||||
import org.dromara.sis.sdk.e8.domain.accessControl.res.AccessRecordFindRes;
|
||||
import org.dromara.sis.service.ISisPersonLibImgService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yuyongle
|
||||
* @version 1.0
|
||||
* @description:
|
||||
* @date 2025/8/27 15:57
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/visitor")
|
||||
public class SisVisitorController {
|
||||
private final E8PlatformApi e8PlatformApi;
|
||||
|
||||
/**
|
||||
* 查询人员通行记录
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<AccessRecordFindRes> list(QueryDto dto) {
|
||||
|
||||
TableDataInfo tableDataInfo = new TableDataInfo();
|
||||
List<AccessRecordFindRes> accessRecordFindResList = new ArrayList<>();
|
||||
AccessRecordFindRes accessRecordFindRes = new AccessRecordFindRes();
|
||||
accessRecordFindRes.setDeviceName("4#岗亭09");
|
||||
accessRecordFindRes.setDoorName("4#岗亭09");
|
||||
accessRecordFindRes.setDeviceType(1102);
|
||||
accessRecordFindRes.setReaderName("");
|
||||
accessRecordFindRes.setGatewayType(1);
|
||||
accessRecordFindRes.setCustomerName("德隆吴鹏");
|
||||
accessRecordFindRes.setOrganFullPath("主楼11楼");
|
||||
accessRecordFindRes.setPictureUrl("https://bpic.588ku.com/back_list_pic/23/04/21/ef5e2a3dd5cfc336fdcf2fd000474f0f.jpg");
|
||||
accessRecordFindRes.setCardType(34);
|
||||
accessRecordFindRes.setRecordType(2);
|
||||
accessRecordFindRes.setActionTime(new Date());
|
||||
accessRecordFindResList.add(accessRecordFindRes);
|
||||
tableDataInfo.setRows(accessRecordFindResList);
|
||||
tableDataInfo.setTotal(1);
|
||||
tableDataInfo.setCode(200);
|
||||
return tableDataInfo;
|
||||
|
||||
// dto.setPageIndex(1);
|
||||
// dto.setMaxResultCount(20);
|
||||
//
|
||||
// // 10秒内
|
||||
// String starTime = DateUtil.format(DateUtil.offset(new Date(), DateField.SECOND, -10), "yyyy-MM-dd HH:mm:ss");
|
||||
// String endTime = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
|
||||
//
|
||||
// AccessRecordFindReq lift = new AccessRecordFindReq();
|
||||
// lift.setStartTime(starTime);
|
||||
// lift.setEndTime(endTime);
|
||||
// lift.setRecordType(2);
|
||||
// // 9号电梯
|
||||
// lift.setDeviceId(550757939925061L);
|
||||
// dto.setQueryDto(lift);
|
||||
//// TableDataInfo<AccessRecordFindRes> nineLiftList = e8PlatformApi.getPageAccessRecordList(dto);
|
||||
// TableDataInfo<AccessRecordFindRes> pageAccessRecordList = new TableDataInfo();
|
||||
//
|
||||
// return e8PlatformApi.getPageAccessRecordList(dto);
|
||||
//如果pageAccessRecordList报错就捕获并封装
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
package org.dromara.sis.rocketmq.consumer;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.common.message.MessageExt;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.dromara.sis.rocketmq.RocketMqConstants;
|
||||
import org.dromara.sis.rocketmq.producer.ProducerService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author lsm
|
||||
* @apiNote MeterRecordConsumer
|
||||
* @since 2025/8/25
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@RocketMQMessageListener(
|
||||
topic = RocketMqConstants.TOPIC,
|
||||
consumerGroup = RocketMqConstants.METER_GROUP,
|
||||
selectorExpression = RocketMqConstants.METER_RECORD,
|
||||
nameServer = "${rocketmq.cluster1.name-server}"
|
||||
)
|
||||
public class MeterRecordConsumer implements RocketMQListener<MessageExt> {
|
||||
|
||||
private final ProducerService producerService;
|
||||
|
||||
@Override
|
||||
public void onMessage(MessageExt ext) {
|
||||
try {
|
||||
if (ext.getBody() == null) {
|
||||
log.info("仪表上报消息数据,不转发!");
|
||||
} else {
|
||||
producerService.defaultSend(RocketMqConstants.TOPIC, RocketMqConstants.METER_RECORD, new String(ext.getBody()));
|
||||
log.info("转发仪表上报数据处理成功");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("转发仪表上报数据处理失败,", e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
package org.dromara.sis.rocketmq.producer;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.common.message.Message;
|
||||
import org.apache.rocketmq.spring.core.RocketMQTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author lsm
|
||||
* @apiNote ProducerService
|
||||
* @since 2025/8/26
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ProducerService {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("rocketMQTemplateClusterOne")
|
||||
private RocketMQTemplate rocketMQTemplateClusterOne;
|
||||
|
||||
// @Autowired
|
||||
// @Qualifier("rocketMQTemplateClusterTwo")
|
||||
// private RocketMQTemplate rocketMQTemplateClusterTwo;
|
||||
|
||||
/**
|
||||
* 向mq写入消息
|
||||
*
|
||||
* @param topic 消息topic
|
||||
* @param tag 消息tag
|
||||
* @param msg 消息
|
||||
*/
|
||||
public void defaultSend(String topic, String tag, String msg) {
|
||||
try {
|
||||
String destination = topic + ":" + tag;
|
||||
// 使用 RocketMQTemplate 的同步发送方法
|
||||
rocketMQTemplateClusterOne.syncSend(destination, msg);
|
||||
|
||||
log.info("发送RocketMQOne消息成功, nameServer:{}", rocketMQTemplateClusterOne.getProducer().getNamesrvAddr());
|
||||
} catch (Exception e) {
|
||||
log.error("发送RocketMQOne消息失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 向mq写入消息
|
||||
*
|
||||
* @param topic 消息topic
|
||||
* @param tag 消息tag
|
||||
* @param msg 消息
|
||||
*/
|
||||
// public void clusterSend(String topic, String tag, String msg) {
|
||||
// try {
|
||||
// String destination = topic + ":" + tag;
|
||||
// // 使用 RocketMQTemplate 的同步发送方法
|
||||
// rocketMQTemplateClusterTwo.syncSend(destination, msg);
|
||||
//
|
||||
// log.info("发送RocketMQTwo消息成功, nameServer:{}", rocketMQTemplateClusterTwo.getProducer().getNamesrvAddr());
|
||||
// } catch (Exception e) {
|
||||
// log.error("发送RocketMQTwo消息失败", e);
|
||||
// }
|
||||
// }
|
||||
}
|
@@ -1,17 +1,21 @@
|
||||
package org.dromara.sis.sdk.e8.utils;
|
||||
|
||||
import com.drew.imaging.ImageMetadataReader;
|
||||
import com.drew.imaging.ImageProcessingException;
|
||||
import com.drew.metadata.Metadata;
|
||||
import com.drew.metadata.MetadataException;
|
||||
import com.drew.metadata.exif.ExifIFD0Directory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.imageio.IIOImage;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageWriteParam;
|
||||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.*;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.stream.MemoryCacheImageOutputStream;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* @author lsm
|
||||
@@ -22,7 +26,8 @@ import java.io.IOException;
|
||||
public class ImageUtil {
|
||||
|
||||
public byte[] compressImageToRequirements(byte[] imageData) throws IOException {
|
||||
BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageData));
|
||||
// 读取图片并处理方向
|
||||
BufferedImage image = readAndFixOrientation(imageData);
|
||||
|
||||
// 第一步:调整分辨率(不超过1000x1000)
|
||||
if (image.getWidth() > 1000 || image.getHeight() > 1000) {
|
||||
@@ -91,6 +96,124 @@ public class ImageUtil {
|
||||
return resizedImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取图片并处理 EXIF 方向信息
|
||||
*/
|
||||
private BufferedImage readAndFixOrientation(byte[] imageData) throws IOException {
|
||||
try {
|
||||
// 使用 metadata-extractor 读取 EXIF 方向信息
|
||||
Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageData));
|
||||
ExifIFD0Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
|
||||
|
||||
int orientation = 1; // 默认正常方向
|
||||
if (directory != null && directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
|
||||
orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
|
||||
}
|
||||
|
||||
// 读取图片
|
||||
ImageInputStream input = ImageIO.createImageInputStream(new ByteArrayInputStream(imageData));
|
||||
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
|
||||
|
||||
if (!readers.hasNext()) {
|
||||
throw new IOException("No ImageReader found for image data");
|
||||
}
|
||||
|
||||
ImageReader reader = readers.next();
|
||||
reader.setInput(input);
|
||||
BufferedImage image = reader.read(0);
|
||||
reader.dispose();
|
||||
|
||||
// 根据方向信息旋转图片
|
||||
return rotateImageAccordingToOrientation(image, orientation);
|
||||
} catch (ImageProcessingException e) {
|
||||
throw new IOException("Failed to process image metadata", e);
|
||||
} catch (MetadataException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据方向信息旋转图片
|
||||
*/
|
||||
private BufferedImage rotateImageAccordingToOrientation(BufferedImage image, int orientation) {
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
|
||||
return switch (orientation) {
|
||||
case 1 -> // 正常
|
||||
image;
|
||||
case 2 -> // 水平翻转
|
||||
flipImage(image, true, false);
|
||||
case 3 -> // 旋转180度
|
||||
rotateImage(image, 180);
|
||||
case 4 -> // 垂直翻转
|
||||
flipImage(image, false, true);
|
||||
case 5 -> {
|
||||
image = flipImage(image, true, false);
|
||||
yield rotateImage(image, 270);
|
||||
}
|
||||
case 6 -> // 旋转90度
|
||||
rotateImage(image, 90);
|
||||
case 7 -> {
|
||||
image = flipImage(image, true, false);
|
||||
yield rotateImage(image, 90);
|
||||
}
|
||||
case 8 -> // 旋转270度
|
||||
rotateImage(image, 270);
|
||||
default -> image;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 旋转图片
|
||||
*/
|
||||
private BufferedImage rotateImage(BufferedImage image, double degrees) {
|
||||
double radians = Math.toRadians(degrees);
|
||||
double sin = Math.abs(Math.sin(radians));
|
||||
double cos = Math.abs(Math.cos(radians));
|
||||
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
|
||||
int newWidth = (int) Math.floor(width * cos + height * sin);
|
||||
int newHeight = (int) Math.floor(height * cos + width * sin);
|
||||
|
||||
BufferedImage rotated = new BufferedImage(newWidth, newHeight, image.getType());
|
||||
Graphics2D g = rotated.createGraphics();
|
||||
|
||||
g.translate((newWidth - width) / 2, (newHeight - height) / 2);
|
||||
g.rotate(Math.toRadians(degrees), width / 2.0, height / 2.0);
|
||||
g.drawRenderedImage(image, null);
|
||||
g.dispose();
|
||||
|
||||
return rotated;
|
||||
}
|
||||
|
||||
/**
|
||||
* 翻转图片
|
||||
*/
|
||||
private BufferedImage flipImage(BufferedImage image, boolean horizontal, boolean vertical) {
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
|
||||
BufferedImage flipped = new BufferedImage(width, height, image.getType());
|
||||
Graphics2D g = flipped.createGraphics();
|
||||
|
||||
if (horizontal && vertical) {
|
||||
g.drawImage(image, width, height, -width, -height, null);
|
||||
} else if (horizontal) {
|
||||
g.drawImage(image, width, 0, -width, height, null);
|
||||
} else if (vertical) {
|
||||
g.drawImage(image, 0, height, width, -height, null);
|
||||
} else {
|
||||
g.drawImage(image, 0, 0, null);
|
||||
}
|
||||
|
||||
g.dispose();
|
||||
return flipped;
|
||||
}
|
||||
|
||||
|
||||
private byte[] compressWithQuality(BufferedImage image, float quality) throws IOException {
|
||||
// 获取JPEG编码器
|
||||
ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next();
|
||||
|
@@ -153,7 +153,7 @@ public class SisAlarmEventProcessServiceImpl implements ISisAlarmEventProcessSer
|
||||
return null;
|
||||
}
|
||||
// 加载附件列表
|
||||
List<SisAlarmEventAttachmentsVo> sisAlarmEventAttachmentsVos = sisAlarmEventAttachmentsService.queryListByAlarmId(alarmId);
|
||||
List<SisAlarmEventAttachmentsVo> sisAlarmEventAttachmentsVos = sisAlarmEventAttachmentsService.queryListByAlarmId(sisAlarmEventProcessVo.getId());
|
||||
sisAlarmEventProcessVo.setAttachments(sisAlarmEventAttachmentsVos);
|
||||
return sisAlarmEventProcessVo;
|
||||
}
|
||||
|
Reference in New Issue
Block a user