feat(sis):
- 优化电梯控制逻辑,支持外部按键触发
This commit is contained in:
@@ -33,31 +33,35 @@ public class CleanLiftAuthRocketConsumer implements RocketMQListener<MessageExt>
|
||||
public void onMessage(MessageExt ext) {
|
||||
log.info("【消费者】接收消息:消息体 => {}", new String(ext.getBody()));
|
||||
|
||||
Long deviceId = Long.parseLong(ext.getUserProperty("deviceId"));
|
||||
Long groupId = Long.parseLong(ext.getUserProperty("groupId"));
|
||||
Long deviceFloorId = Long.parseLong(ext.getUserProperty("deviceFloorId"));
|
||||
|
||||
// 获取当前电梯信息
|
||||
SisElevatorInfoVo ele = sisElevatorInfoService.queryById(deviceId);
|
||||
|
||||
// 获取权限组下电梯⇄楼层关联信息
|
||||
List<SisElevatorFloorRefVo> groupRef = sisElevatorFloorRefService.queryByAuthGroupId(groupId);
|
||||
|
||||
// 取出当前电梯的楼层授权信息
|
||||
List<SisElevatorFloorRefVo> eleRef = groupRef.stream().filter(o -> Objects.equals(o.getElevatorId(), deviceId)).toList();
|
||||
|
||||
for (SisElevatorFloorRefVo ref : eleRef){
|
||||
if (ref.getUpChannel() != null && Objects.equals(ref.getFloorId(), deviceFloorId)){
|
||||
HikApiService.getInstance().controlGateway(ele.getControlIp(), ref.getUpChannel().intValue(), 3);
|
||||
}
|
||||
|
||||
if (ref.getDownChannel() != null && Objects.equals(ref.getFloorId(), deviceFloorId)){
|
||||
HikApiService.getInstance().controlGateway(ele.getControlIp(), ref.getDownChannel().intValue(), 3);
|
||||
}
|
||||
|
||||
if (ref.getInChannel() != null && Objects.equals(ref.getFloorId(), deviceFloorId)){
|
||||
HikApiService.getInstance().controlGateway(ele.getControlIp(), ref.getInChannel().intValue(), 3);
|
||||
}
|
||||
// Long deviceId = Long.parseLong(ext.getUserProperty("deviceId"));
|
||||
// Long groupId = Long.parseLong(ext.getUserProperty("groupId"));
|
||||
// Long deviceFloorId = Long.parseLong(ext.getUserProperty("deviceFloorId"));
|
||||
//
|
||||
// // 获取当前电梯信息
|
||||
// SisElevatorInfoVo ele = sisElevatorInfoService.queryById(deviceId);
|
||||
//
|
||||
// // 获取权限组下电梯⇄楼层关联信息
|
||||
// List<SisElevatorFloorRefVo> groupRef = sisElevatorFloorRefService.queryByAuthGroupId(groupId);
|
||||
//
|
||||
// // 取出当前电梯的楼层授权信息
|
||||
// List<SisElevatorFloorRefVo> eleRef = groupRef.stream().filter(o -> Objects.equals(o.getElevatorId(), deviceId)).toList();
|
||||
//
|
||||
// for (SisElevatorFloorRefVo ref : eleRef){
|
||||
// if (ref.getUpChannel() != null && Objects.equals(ref.getFloorId(), deviceFloorId)){
|
||||
// HikApiService.getInstance().controlGateway(ele.getControlIp(), ref.getUpChannel().intValue(), 3);
|
||||
// }
|
||||
//
|
||||
// if (ref.getDownChannel() != null && Objects.equals(ref.getFloorId(), deviceFloorId)){
|
||||
// HikApiService.getInstance().controlGateway(ele.getControlIp(), ref.getDownChannel().intValue(), 3);
|
||||
// }
|
||||
//
|
||||
// if (ref.getInChannel() != null && Objects.equals(ref.getFloorId(), deviceFloorId)){
|
||||
// HikApiService.getInstance().controlGateway(ele.getControlIp(), ref.getInChannel().intValue(), 3);
|
||||
// }
|
||||
// }
|
||||
// todo 暂时应急处理,后续调整业务逻辑
|
||||
for (int i = 1; i < 20; i++) {
|
||||
HikApiService.getInstance().controlGateway("192.168.24.150", i, 3);
|
||||
}
|
||||
log.info("梯控清除权限完成");
|
||||
}
|
||||
|
@@ -85,4 +85,9 @@ public class SisDeviceManage extends BaseEntity {
|
||||
*/
|
||||
private Long floorId;
|
||||
|
||||
/**
|
||||
* 是否支持人脸比对
|
||||
*/
|
||||
private Boolean isComparison;
|
||||
|
||||
}
|
||||
|
@@ -83,6 +83,11 @@ public class SisDeviceManageBo extends BaseEntity {
|
||||
*/
|
||||
private Long groupId;
|
||||
|
||||
/**
|
||||
* 是否支持人脸比对
|
||||
*/
|
||||
private Boolean isComparison;
|
||||
|
||||
private String tenantId;
|
||||
|
||||
}
|
||||
|
@@ -95,4 +95,9 @@ public class SisDeviceManageVo implements Serializable {
|
||||
private Long groupId;
|
||||
|
||||
private String groupName;
|
||||
|
||||
/**
|
||||
* 是否支持人脸比对
|
||||
*/
|
||||
private Boolean isComparison;
|
||||
}
|
||||
|
@@ -107,9 +107,12 @@ public class RemoteSisAuthServiceImpl implements RemoteSisAuthService {
|
||||
public Long syncHuaweiBox(RemotePersonAuth person, byte[] imgByte) {
|
||||
Long pId;
|
||||
try {
|
||||
SisPersonLibImgVo vo = sisPersonLibImgService.queryByPersonId(person.getId());
|
||||
AddHWPersonReq req = new AddHWPersonReq();
|
||||
req.setIndex(CodePrefixConstants.PERSON_LIB_IMAGE_CODE_PREFIX + IdUtil.getSnowflakeNextIdStr());
|
||||
req.setName(person.getName());
|
||||
req.setCredentialType("5");
|
||||
req.setCredentialNumber(vo.getId().toString());
|
||||
req.setGender(person.getSex() == 1 ? "0" : person.getSex() == 2 ? "1" : "-1");
|
||||
|
||||
ArrayList<String> pictures = new ArrayList<>();
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package org.dromara.sis.runner;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.sis.sdk.smartDevices.utils.ElevatorControlUtil;
|
||||
import org.dromara.sis.sdk.smartDevices.utils.ElevatorControlTcpUtil;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -19,22 +19,35 @@ public class ElevatorTcpRunner implements ApplicationRunner {
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) {
|
||||
// 获取单例实例并启动服务
|
||||
ElevatorControlUtil instance = ElevatorControlUtil.getInstance();
|
||||
// 获取单例实例
|
||||
ElevatorControlTcpUtil elevatorHelper = ElevatorControlTcpUtil.getInstance();
|
||||
|
||||
// 设置连接监听器
|
||||
elevatorHelper.setConnectionListener(new ElevatorControlTcpUtil.ConnectionListener() {
|
||||
@Override
|
||||
public void onConnected() {
|
||||
log.info("梯控设备已连接");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected() {
|
||||
log.info("梯控设备已断开");
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
// 启动服务
|
||||
instance.start(23);
|
||||
log.info("启动电梯控制服务成功");
|
||||
elevatorHelper.start(23);
|
||||
log.info("电梯控制TCP服务启动成功");
|
||||
|
||||
// 添加关闭钩子
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
// 停止服务
|
||||
log.info("应用关闭中,停止电梯服务...");
|
||||
instance.stop();
|
||||
|
||||
log.info("应用关闭中,停止电梯控制TCP服务...");
|
||||
elevatorHelper.stop();
|
||||
}));
|
||||
|
||||
} catch (IOException e) {
|
||||
log.info("启动电梯控制服务失败");
|
||||
System.err.println("无法启动电梯控制TCP服务: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,14 @@
|
||||
package org.dromara.sis.sdk.hik.calback;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.sun.jna.Pointer;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.sis.domain.SisDeviceManage;
|
||||
import org.dromara.sis.sdk.hik.HCNetSDK;
|
||||
import org.dromara.sis.sdk.hik.HikApiService;
|
||||
import org.dromara.sis.service.ISisDeviceManageService;
|
||||
import org.dromara.sis.service.IZeroSensationPassageService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -11,6 +16,7 @@ import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
@@ -21,6 +27,7 @@ import static org.dromara.sis.sdk.hik.HCNetSDK.*;
|
||||
@RequiredArgsConstructor
|
||||
public class HikAlarmCallBack implements HCNetSDK.FMSGCallBack_V31 {
|
||||
|
||||
private final ISisDeviceManageService sisDeviceManageService;
|
||||
private final IZeroSensationPassageService zeroSensationPassageService;
|
||||
|
||||
@Override
|
||||
@@ -243,12 +250,9 @@ public class HikAlarmCallBack implements HCNetSDK.FMSGCallBack_V31 {
|
||||
Pointer pFaceSnapMatch = strFaceSnapMatch.getPointer();
|
||||
pFaceSnapMatch.write(0, pAlarmInfo.getByteArray(0, strFaceSnapMatch.size()), 0, strFaceSnapMatch.size());
|
||||
strFaceSnapMatch.read();
|
||||
//比对结果,0-保留,1-比对成功,2-比对失败
|
||||
String sFaceSnapMatchInfo = "比对结果:" + strFaceSnapMatch.byContrastStatus + ",相似度:" + strFaceSnapMatch.fSimilarity;
|
||||
|
||||
|
||||
handleFaceComparison(strFaceSnapMatch, pAlarmer);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
|
||||
}
|
||||
@@ -262,9 +266,8 @@ public class HikAlarmCallBack implements HCNetSDK.FMSGCallBack_V31 {
|
||||
*
|
||||
* @param result 人脸数据
|
||||
* @param pAlarmer 设备数据
|
||||
* @return 返回是否处理成功
|
||||
*/
|
||||
private boolean handleFaceSnap(HCNetSDK.NET_VCA_FACESNAP_RESULT result, HCNetSDK.NET_DVR_ALARMER pAlarmer) {
|
||||
private void handleFaceSnap(HCNetSDK.NET_VCA_FACESNAP_RESULT result, HCNetSDK.NET_DVR_ALARMER pAlarmer) {
|
||||
// 读取人脸小图
|
||||
ByteBuffer buffers = result.pBuffer1.getByteBuffer(0, result.dwFacePicLen);
|
||||
byte[] smallImg = new byte[result.dwFacePicLen];
|
||||
@@ -279,8 +282,48 @@ public class HikAlarmCallBack implements HCNetSDK.FMSGCallBack_V31 {
|
||||
//设备ip
|
||||
String sAlarmInfo = new String(pAlarmer.sDeviceIP).trim();
|
||||
log.info("海康设备告警信息上传,设备={}, 人脸图片大小={}, 背景图片大小={}", sAlarmInfo, smallImg.length, bigImg.length);
|
||||
|
||||
SisDeviceManage device = sisDeviceManageService.queryByDeviceIp(sAlarmInfo);
|
||||
|
||||
if (!device.getIsComparison()) {
|
||||
log.info("设备不支持人脸比对");
|
||||
zeroSensationPassageService.pass(sAlarmInfo, smallImg, bigImg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理人脸比对上报
|
||||
*/
|
||||
private void handleFaceComparison(HCNetSDK.NET_VCA_FACESNAP_MATCH_ALARM result, HCNetSDK.NET_DVR_ALARMER pAlarmer) {
|
||||
// 读取比对结果比对结果,0-保留,1-比对成功,2-比对失败
|
||||
int compareResults = result.byContrastStatus;
|
||||
// 比对不成功,不处理
|
||||
if (compareResults != 1) {
|
||||
log.info("前置人脸比对失败,设备:{}", new String(pAlarmer.sDeviceIP).trim());
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取相似度
|
||||
float similarity = result.fSimilarity;
|
||||
// 相似度小于70,不处理
|
||||
if (similarity < 0.7) {
|
||||
log.info("前置人脸比对相似度小于70,设备:{}", new String(pAlarmer.sDeviceIP).trim());
|
||||
return;
|
||||
}
|
||||
|
||||
// 读取名字
|
||||
String name = new String(result.struBlockListInfo.struBlockListInfo.struAttribute.byName, Charset.forName("GBK")).trim();
|
||||
// 人员id为空,不处理
|
||||
if (result.struBlockListInfo.pPID == null) return;
|
||||
// 读取人员id
|
||||
ByteBuffer buffers = result.struBlockListInfo.pPID.getByteBuffer(0, result.struBlockListInfo.dwPIDLen);
|
||||
byte[] pidByte = new byte[result.struBlockListInfo.dwPIDLen];
|
||||
buffers.rewind();
|
||||
buffers.get(pidByte);
|
||||
int pid = Integer.parseInt(new String(pidByte));
|
||||
|
||||
log.info("比对结果:{},相似度:{},人员:{},id:{}", compareResults, similarity, name, pid);
|
||||
zeroSensationPassageService.handleEleOut(new String(pAlarmer.sDeviceIP).trim());
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package org.dromara.sis.sdk.smartDevices.utils;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Service;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -9,53 +9,63 @@ import java.io.OutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author lsm
|
||||
* @apiNote ElevatorControlUtil
|
||||
* @apiNote ElevatorControlTcpUtil
|
||||
* @since 2025/8/8
|
||||
*/
|
||||
@Service
|
||||
public class ElevatorControlUtil {
|
||||
@Slf4j
|
||||
public class ElevatorControlTcpUtil {
|
||||
private static final int FRAME_LENGTH = 10;
|
||||
private static final byte FIXED_ADDRESS = 0x00;
|
||||
private static final byte MANUAL_COMMAND = (byte) 0xD1;
|
||||
private static final byte AUTO_COMMAND = (byte) 0xD2;
|
||||
private static final byte MANUAL_RESPONSE = (byte) 0xC1;
|
||||
private static final byte AUTO_RESPONSE = (byte) 0xC2;
|
||||
private static final byte HEARTBEAT_COMMAND = (byte) 0xD0;
|
||||
|
||||
private static ElevatorControlUtil instance;
|
||||
private static ElevatorControlTcpUtil instance;
|
||||
|
||||
private ServerSocket serverSocket;
|
||||
private Socket clientSocket;
|
||||
private InputStream inputStream;
|
||||
private OutputStream outputStream;
|
||||
private final Object lock = new Object();
|
||||
private ScheduledExecutorService heartbeatScheduler;
|
||||
private volatile boolean isRunning = false;
|
||||
|
||||
/**
|
||||
* -- SETTER --
|
||||
* 设置连接状态监听器
|
||||
*/
|
||||
// 连接状态监听器
|
||||
@Setter
|
||||
private ConnectionListener connectionListener;
|
||||
|
||||
// 线程池处理连接
|
||||
private final ExecutorService executor = Executors.newCachedThreadPool();
|
||||
|
||||
// 私有构造函数
|
||||
private ElevatorControlUtil() {}
|
||||
private ElevatorControlTcpUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单例实例
|
||||
*/
|
||||
public static synchronized ElevatorControlUtil getInstance() {
|
||||
public static synchronized ElevatorControlTcpUtil getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ElevatorControlUtil();
|
||||
instance = new ElevatorControlTcpUtil();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动TCP服务
|
||||
*
|
||||
* @param port 监听端口
|
||||
*/
|
||||
public void start(Integer port) throws IOException {
|
||||
public void start(int port) throws IOException {
|
||||
if (isRunning) {
|
||||
throw new IllegalStateException("服务已在运行中");
|
||||
}
|
||||
@@ -64,8 +74,8 @@ public class ElevatorControlUtil {
|
||||
isRunning = true;
|
||||
|
||||
// 启动连接监听线程
|
||||
new Thread(this::acceptConnections, "TCP-Acceptor").start();
|
||||
System.out.println("电梯控制服务已启动,监听端口: " + port);
|
||||
executor.execute(this::acceptConnections);
|
||||
log.info("电梯控制TCP服务已启动,监听端口: {}", port);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,98 +84,71 @@ public class ElevatorControlUtil {
|
||||
public void stop() {
|
||||
isRunning = false;
|
||||
|
||||
// 停止心跳
|
||||
if (heartbeatScheduler != null) {
|
||||
heartbeatScheduler.shutdown();
|
||||
}
|
||||
|
||||
// 关闭连接
|
||||
// 关闭客户端连接
|
||||
closeClientResources();
|
||||
|
||||
// 关闭服务器
|
||||
if (serverSocket != null && !serverSocket.isClosed()) {
|
||||
try {
|
||||
serverSocket.close();
|
||||
System.out.println("服务已停止");
|
||||
log.info("电梯控制TCP服务已停止");
|
||||
} catch (IOException e) {
|
||||
System.err.println("停止服务时出错: " + e.getMessage());
|
||||
log.error("停止电梯控制TCP服务时出错: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭线程池
|
||||
executor.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* 接受客户端连接
|
||||
*/
|
||||
private void acceptConnections() {
|
||||
while (isRunning) {
|
||||
while (isRunning && !serverSocket.isClosed()) {
|
||||
try {
|
||||
clientSocket = serverSocket.accept();
|
||||
clientSocket.setKeepAlive(true);
|
||||
log.info("等待梯控设备连接...");
|
||||
Socket newClient = serverSocket.accept();
|
||||
|
||||
synchronized (lock) {
|
||||
// 关闭现有连接(如果有)
|
||||
closeClientResources();
|
||||
|
||||
// 接受新连接
|
||||
clientSocket = newClient;
|
||||
inputStream = clientSocket.getInputStream();
|
||||
outputStream = clientSocket.getOutputStream();
|
||||
|
||||
System.out.println("梯控设备已连接: " + clientSocket.getRemoteSocketAddress());
|
||||
log.info("梯控设备已连接: {}", clientSocket.getRemoteSocketAddress());
|
||||
|
||||
// 启动心跳机制
|
||||
startHeartbeat();
|
||||
// 通知连接状态变化
|
||||
if (connectionListener != null) {
|
||||
connectionListener.onConnected();
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
if (isRunning) {
|
||||
System.err.println("接受连接时出错: " + e.getMessage());
|
||||
try {
|
||||
Thread.sleep(5000); // 5秒后重试
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
log.error("接受连接时出错: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动心跳机制
|
||||
*/
|
||||
private void startHeartbeat() {
|
||||
if (heartbeatScheduler != null && !heartbeatScheduler.isShutdown()) {
|
||||
heartbeatScheduler.shutdown();
|
||||
}
|
||||
|
||||
heartbeatScheduler = Executors.newSingleThreadScheduledExecutor();
|
||||
heartbeatScheduler.scheduleAtFixedRate(() -> {
|
||||
if (isClientConnected()) {
|
||||
try {
|
||||
sendHeartbeat();
|
||||
} catch (IOException e) {
|
||||
System.err.println("心跳包发送失败: " + e.getMessage());
|
||||
closeClientResources();
|
||||
}
|
||||
}
|
||||
}, 30, 30, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送心跳包
|
||||
*/
|
||||
private void sendHeartbeat() throws IOException {
|
||||
synchronized (lock) {
|
||||
if (!isClientConnected()) return;
|
||||
|
||||
byte[] heartbeatData = new byte[7];
|
||||
byte[] frame = buildFrame(HEARTBEAT_COMMAND, heartbeatData);
|
||||
outputStream.write(frame);
|
||||
outputStream.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查客户端是否连接
|
||||
*/
|
||||
public boolean isClientConnected() {
|
||||
return clientSocket != null && clientSocket.isConnected() && !clientSocket.isClosed();
|
||||
synchronized (lock) {
|
||||
return clientSocket != null &&
|
||||
clientSocket.isConnected() &&
|
||||
!clientSocket.isClosed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送手动选层命令
|
||||
*
|
||||
* @param floors 要开放的楼层列表
|
||||
* @return 是否成功
|
||||
*/
|
||||
@@ -175,6 +158,7 @@ public class ElevatorControlUtil {
|
||||
|
||||
/**
|
||||
* 发送自动选层命令
|
||||
*
|
||||
* @param floors 要开放的楼层列表
|
||||
* @return 是否成功
|
||||
*/
|
||||
@@ -195,18 +179,24 @@ public class ElevatorControlUtil {
|
||||
|
||||
private boolean sendCommand(byte command, byte expectedResponse, byte[] floorData) {
|
||||
if (!isClientConnected()) {
|
||||
System.err.println("发送命令失败:未连接梯控设备");
|
||||
log.info("发送命令失败:未连接梯控设备");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (floorData == null || floorData.length != 7) {
|
||||
System.err.println("发送命令失败:无效的楼层数据");
|
||||
log.info("发送命令失败:无效的楼层数据");
|
||||
return false;
|
||||
}
|
||||
|
||||
synchronized (lock) {
|
||||
for (int attempt = 0; attempt < 2; attempt++) {
|
||||
try {
|
||||
// 检查连接是否仍然有效
|
||||
if (!isClientConnected()) {
|
||||
log.info("连接在发送前已断开");
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] frame = buildFrame(command, floorData);
|
||||
outputStream.write(frame);
|
||||
outputStream.flush();
|
||||
@@ -219,23 +209,38 @@ public class ElevatorControlUtil {
|
||||
while (bytesRead < FRAME_LENGTH) {
|
||||
int read = inputStream.read(response, bytesRead, FRAME_LENGTH - bytesRead);
|
||||
if (read == -1) {
|
||||
throw new IOException("连接已关闭");
|
||||
// 连接关闭
|
||||
handleConnectionClosed();
|
||||
return false;
|
||||
}
|
||||
bytesRead += read;
|
||||
}
|
||||
|
||||
if (validateResponse(response, expectedResponse)) {
|
||||
return true;
|
||||
} else {
|
||||
log.info("响应验证失败,尝试重试");
|
||||
}
|
||||
} catch (java.net.SocketTimeoutException e) {
|
||||
System.err.println("命令响应超时,尝试重试");
|
||||
log.info("命令响应超时,尝试重试");
|
||||
} catch (IOException e) {
|
||||
System.err.println("发送命令时出错: " + e.getMessage());
|
||||
log.error("发送命令时出错: {}", e.getMessage());
|
||||
handleConnectionClosed();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理连接关闭
|
||||
*/
|
||||
private void handleConnectionClosed() {
|
||||
log.info("检测到连接已关闭");
|
||||
closeClientResources();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (connectionListener != null) {
|
||||
connectionListener.onDisconnected();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,34 +281,61 @@ public class ElevatorControlUtil {
|
||||
}
|
||||
|
||||
private boolean validateResponse(byte[] response, byte expectedHeader) {
|
||||
if (response[0] != expectedHeader) return false;
|
||||
if (response[1] != FIXED_ADDRESS) return false;
|
||||
if (response[0] != expectedHeader) {
|
||||
log.info("响应帧头错误,期望: {},实际:{}", expectedHeader, response[0]);
|
||||
return false;
|
||||
}
|
||||
if (response[1] != FIXED_ADDRESS) {
|
||||
log.info("响应地址错误");
|
||||
return false;
|
||||
}
|
||||
|
||||
byte checksum = 0;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
checksum = (byte) (checksum + response[i]);
|
||||
}
|
||||
|
||||
return response[9] == checksum;
|
||||
if (response[9] != checksum) {
|
||||
log.info("校验和错误,期望: {},实际: {}", checksum, response[9]);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭客户端资源
|
||||
*/
|
||||
private void closeClientResources() {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
if (inputStream != null) inputStream.close();
|
||||
if (outputStream != null) outputStream.close();
|
||||
if (clientSocket != null && !clientSocket.isClosed()) {
|
||||
clientSocket.close();
|
||||
}
|
||||
System.out.println("客户端连接已关闭");
|
||||
log.info("客户端连接已关闭");
|
||||
} catch (IOException e) {
|
||||
System.err.println("关闭连接时出错: " + e.getMessage());
|
||||
log.error("关闭连接时出错: {}", e.getMessage());
|
||||
} finally {
|
||||
clientSocket = null;
|
||||
inputStream = null;
|
||||
outputStream = null;
|
||||
|
||||
// 通知连接断开
|
||||
if (connectionListener != null) {
|
||||
connectionListener.onDisconnected();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接状态监听接口
|
||||
*/
|
||||
public interface ConnectionListener {
|
||||
void onConnected();
|
||||
|
||||
void onDisconnected();
|
||||
}
|
||||
}
|
@@ -70,21 +70,18 @@ public interface ISisDeviceManageService {
|
||||
|
||||
/**
|
||||
* 通过设备ip查询设备信息
|
||||
*
|
||||
* @param deviceIp 设备编码
|
||||
* @param deviceIp 设备ip
|
||||
* @return 设备信息
|
||||
*/
|
||||
SisDeviceManageVo queryVoByDeviceIp(String deviceIp);
|
||||
SisDeviceManage queryByDeviceIp(String deviceIp);
|
||||
|
||||
SisDeviceManage queryByDeviceIp(String deviceId);
|
||||
/**
|
||||
* 查询设备数
|
||||
*
|
||||
* @return
|
||||
* @return tree
|
||||
*/
|
||||
List<TreeNode<Long>> tree();
|
||||
|
||||
|
||||
/**
|
||||
* 通过设备id列表查询设备信息
|
||||
* @param deviceIds 设备id列表
|
||||
|
@@ -11,4 +11,11 @@ public interface IZeroSensationPassageService {
|
||||
*/
|
||||
void pass(String deviceIp, byte[] smallImp, byte[] bigImg);
|
||||
|
||||
/**
|
||||
* 电梯外部按键触发
|
||||
*
|
||||
* @param deviceIp 设备ip
|
||||
*/
|
||||
void handleEleOut(String deviceIp);
|
||||
|
||||
}
|
||||
|
@@ -177,18 +177,15 @@ public class SisDeviceManageServiceImpl implements ISisDeviceManageService {
|
||||
log.info("删除设备通道完成,num={}", num);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过设备ip查询设备信息
|
||||
* @param deviceIp 设备ip
|
||||
* @return 设备信息
|
||||
*/
|
||||
@Override
|
||||
public SisDeviceManageVo queryVoByDeviceIp(String deviceIp) {
|
||||
public SisDeviceManage queryByDeviceIp(String deviceIp) {
|
||||
LambdaQueryWrapper<SisDeviceManage> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(SisDeviceManage::getDeviceIp, deviceIp);
|
||||
return baseMapper.selectVoOne(lqw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SisDeviceManage queryByDeviceIp(String deviceId) {
|
||||
LambdaQueryWrapper<SisDeviceManage> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(SisDeviceManage::getDeviceIp, deviceId);
|
||||
return baseMapper.selectOne(lqw);
|
||||
}
|
||||
|
||||
|
@@ -202,6 +202,9 @@ public class SisElevatorFloorRefServiceImpl implements ISisElevatorFloorRefServi
|
||||
lqw.in(SisElevatorFloorRef::getFloorId, info.stream().map(SisElevatorFloorChannelRef::getFloorId).toList());
|
||||
List<SisElevatorFloorRef> list = baseMapper.selectList(lqw);
|
||||
|
||||
// list为空不需要冗余数据,返回true
|
||||
if(list.isEmpty()) return true;
|
||||
|
||||
// 创建Map提高查找效率,避免在循环中重复流操作
|
||||
Map<Long, SisElevatorFloorChannelRef> floorInfoMap = info.stream()
|
||||
.collect(Collectors.toMap(SisElevatorFloorChannelRef::getFloorId, Function.identity()));
|
||||
|
@@ -252,7 +252,7 @@ public class SisElevatorInfoServiceImpl implements ISisElevatorInfoService {
|
||||
|
||||
// 冗余数据到电梯⇄楼层关联表
|
||||
Boolean update = elevatorFloorRefService.batchUpdateChannel(channelRefs);
|
||||
|
||||
Assert.isTrue(update, "冗余数据到电梯⇄楼层关联表失败!");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -10,6 +10,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.dromara.property.api.RemoteFloorService;
|
||||
import org.dromara.property.api.domain.vo.RemoteFloorVo;
|
||||
import org.dromara.sis.domain.SisElevatorFloorChannelRef;
|
||||
import org.dromara.sis.domain.enums.ControlTypeEnum;
|
||||
import org.dromara.sis.domain.enums.RosterTypeEnum;
|
||||
import org.dromara.sis.domain.vo.*;
|
||||
@@ -19,7 +20,7 @@ import org.dromara.sis.sdk.e8.domain.accessControl.req.RemoteOpenDoorReq;
|
||||
import org.dromara.sis.sdk.hik.HikApiService;
|
||||
import org.dromara.sis.sdk.huawei.HuaWeiBoxApi;
|
||||
import org.dromara.sis.sdk.huawei.domain.HWResult;
|
||||
import org.dromara.sis.sdk.smartDevices.utils.ElevatorControlUtil;
|
||||
import org.dromara.sis.sdk.smartDevices.utils.ElevatorControlTcpUtil;
|
||||
import org.dromara.sis.service.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -46,6 +47,7 @@ public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageSer
|
||||
private final ISisDeviceBindRefService deviceBindRefService;
|
||||
private final ISisAccessControlService accessControlService;
|
||||
private final ISisElevatorFloorRefService elevatorFloorRefService;
|
||||
private final ISisElevatorFloorChannelRefService elevatorFloorChannelRefService;
|
||||
private final E8PlatformApi e8PlatformApi;
|
||||
private final ISisAlarmEventsService alarmEventsService;
|
||||
|
||||
@@ -115,11 +117,11 @@ public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageSer
|
||||
}
|
||||
// 判断绑定设备类型,走不同的处理方法
|
||||
if (Objects.equals(item.getControlType(), ControlTypeEnum.ACCESS_CONTROL.getCode())) { // 门禁
|
||||
handleAc(item.getDeviceId());
|
||||
handleAc(item.getBindId());
|
||||
} else if (item.getControlType().equals(ControlTypeEnum.ELEVATOR_OUT_CONTROL.getCode())) { // 电梯外面面板权限
|
||||
handleEle(item.getDeviceId(), r.getAuthGroupId(), ControlTypeEnum.ELEVATOR_OUT_CONTROL.getCode(), item.getDeviceFloorId());
|
||||
handleEle(item.getBindId(), r.getAuthGroupId(), ControlTypeEnum.ELEVATOR_OUT_CONTROL.getCode(), item.getDeviceFloorId());
|
||||
} else if (item.getControlType().equals(ControlTypeEnum.ELEVATOR_IN_CONTROL.getCode())) { // 电梯里面的面板
|
||||
handleEle(item.getDeviceId(), r.getAuthGroupId(), ControlTypeEnum.ELEVATOR_IN_CONTROL.getCode(), item.getDeviceFloorId());
|
||||
handleEle(item.getBindId(), r.getAuthGroupId(), ControlTypeEnum.ELEVATOR_IN_CONTROL.getCode(), item.getDeviceFloorId());
|
||||
} else {
|
||||
log.info("设备绑定了未知的控制类型[{}],不处理", item.getControlType());
|
||||
}
|
||||
@@ -127,6 +129,39 @@ public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageSer
|
||||
log.info("权限下发执行完成,耗时:{}ms", interval.intervalMs());
|
||||
}
|
||||
|
||||
/**
|
||||
* 电梯外部按键触发
|
||||
*
|
||||
* @param deviceIp 设备ip
|
||||
*/
|
||||
@Override
|
||||
public void handleEleOut(String deviceIp) {
|
||||
// 获取当前设备的绑定设备信息
|
||||
List<SisDeviceBindRefVo> bindRefList = deviceBindRefService.queryByDeviceIp(deviceIp);
|
||||
bindRefList.forEach(item -> {
|
||||
// 只处理外部按键
|
||||
if (Objects.equals(item.getControlType(), ControlTypeEnum.ELEVATOR_OUT_CONTROL.getCode())) {
|
||||
// 获取当前电梯信息
|
||||
SisElevatorInfoVo ele = elevatorInfoService.queryById(item.getBindId());
|
||||
|
||||
List<SisElevatorFloorChannelRefVo> channelRef = elevatorFloorChannelRefService.queryByFloorIds(List.of(item.getDeviceFloorId()));
|
||||
SisElevatorFloorChannelRefVo channelRefVo = channelRef.stream().filter(o -> Objects.equals(o.getElevatorId(), item.getBindId())).findFirst().orElse(null);
|
||||
|
||||
if (channelRefVo != null) {
|
||||
if (channelRefVo.getDownChannel() != null) {
|
||||
HikApiService.getInstance().controlGateway(ele.getControlIp(), channelRefVo.getDownChannel().intValue(), 2);
|
||||
}
|
||||
|
||||
if (channelRefVo.getUpChannel() != null) {
|
||||
HikApiService.getInstance().controlGateway(ele.getControlIp(), channelRefVo.getUpChannel().intValue(), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanLiftAuthRocketProducer.sendMessage(item.getBindId(), 0L, item.getDeviceFloorId(), "清除电梯" + item.getBindId() + "梯控权限", 3);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成告警事件
|
||||
*/
|
||||
@@ -200,11 +235,11 @@ public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageSer
|
||||
}
|
||||
if (CollUtil.isEmpty(num)) return;
|
||||
|
||||
if (!ElevatorControlUtil.getInstance().isClientConnected()){
|
||||
if (!ElevatorControlTcpUtil.getInstance().isClientConnected()) {
|
||||
log.info("梯控模块未连接,请检查梯控模块是否启动");
|
||||
return;
|
||||
}
|
||||
ElevatorControlUtil.getInstance().sendManualCommand(num);
|
||||
ElevatorControlTcpUtil.getInstance().sendManualCommand(num);
|
||||
}
|
||||
log.info("梯控下发权限完成");
|
||||
|
||||
|
Reference in New Issue
Block a user