feat(sis):

- 优化电梯控制逻辑,支持外部按键触发
This commit is contained in:
2025-08-09 23:22:06 +08:00
parent e47a13c214
commit 054a8590ea
14 changed files with 312 additions and 163 deletions

View File

@@ -33,31 +33,35 @@ public class CleanLiftAuthRocketConsumer implements RocketMQListener<MessageExt>
public void onMessage(MessageExt ext) { public void onMessage(MessageExt ext) {
log.info("【消费者】接收消息:消息体 => {}", new String(ext.getBody())); log.info("【消费者】接收消息:消息体 => {}", new String(ext.getBody()));
Long deviceId = Long.parseLong(ext.getUserProperty("deviceId")); // Long deviceId = Long.parseLong(ext.getUserProperty("deviceId"));
Long groupId = Long.parseLong(ext.getUserProperty("groupId")); // Long groupId = Long.parseLong(ext.getUserProperty("groupId"));
Long deviceFloorId = Long.parseLong(ext.getUserProperty("deviceFloorId")); // Long deviceFloorId = Long.parseLong(ext.getUserProperty("deviceFloorId"));
//
// 获取当前电梯信息 // // 获取当前电梯信息
SisElevatorInfoVo ele = sisElevatorInfoService.queryById(deviceId); // SisElevatorInfoVo ele = sisElevatorInfoService.queryById(deviceId);
//
// 获取权限组下电梯⇄楼层关联信息 // // 获取权限组下电梯⇄楼层关联信息
List<SisElevatorFloorRefVo> groupRef = sisElevatorFloorRefService.queryByAuthGroupId(groupId); // List<SisElevatorFloorRefVo> groupRef = sisElevatorFloorRefService.queryByAuthGroupId(groupId);
//
// 取出当前电梯的楼层授权信息 // // 取出当前电梯的楼层授权信息
List<SisElevatorFloorRefVo> eleRef = groupRef.stream().filter(o -> Objects.equals(o.getElevatorId(), deviceId)).toList(); // List<SisElevatorFloorRefVo> eleRef = groupRef.stream().filter(o -> Objects.equals(o.getElevatorId(), deviceId)).toList();
//
for (SisElevatorFloorRefVo ref : eleRef){ // for (SisElevatorFloorRefVo ref : eleRef){
if (ref.getUpChannel() != null && Objects.equals(ref.getFloorId(), deviceFloorId)){ // if (ref.getUpChannel() != null && Objects.equals(ref.getFloorId(), deviceFloorId)){
HikApiService.getInstance().controlGateway(ele.getControlIp(), ref.getUpChannel().intValue(), 3); // HikApiService.getInstance().controlGateway(ele.getControlIp(), ref.getUpChannel().intValue(), 3);
} // }
//
if (ref.getDownChannel() != null && Objects.equals(ref.getFloorId(), deviceFloorId)){ // if (ref.getDownChannel() != null && Objects.equals(ref.getFloorId(), deviceFloorId)){
HikApiService.getInstance().controlGateway(ele.getControlIp(), ref.getDownChannel().intValue(), 3); // HikApiService.getInstance().controlGateway(ele.getControlIp(), ref.getDownChannel().intValue(), 3);
} // }
//
if (ref.getInChannel() != null && Objects.equals(ref.getFloorId(), deviceFloorId)){ // if (ref.getInChannel() != null && Objects.equals(ref.getFloorId(), deviceFloorId)){
HikApiService.getInstance().controlGateway(ele.getControlIp(), ref.getInChannel().intValue(), 3); // 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("梯控清除权限完成"); log.info("梯控清除权限完成");
} }

View File

@@ -85,4 +85,9 @@ public class SisDeviceManage extends BaseEntity {
*/ */
private Long floorId; private Long floorId;
/**
* 是否支持人脸比对
*/
private Boolean isComparison;
} }

View File

@@ -83,6 +83,11 @@ public class SisDeviceManageBo extends BaseEntity {
*/ */
private Long groupId; private Long groupId;
/**
* 是否支持人脸比对
*/
private Boolean isComparison;
private String tenantId; private String tenantId;
} }

View File

@@ -95,4 +95,9 @@ public class SisDeviceManageVo implements Serializable {
private Long groupId; private Long groupId;
private String groupName; private String groupName;
/**
* 是否支持人脸比对
*/
private Boolean isComparison;
} }

View File

@@ -107,9 +107,12 @@ public class RemoteSisAuthServiceImpl implements RemoteSisAuthService {
public Long syncHuaweiBox(RemotePersonAuth person, byte[] imgByte) { public Long syncHuaweiBox(RemotePersonAuth person, byte[] imgByte) {
Long pId; Long pId;
try { try {
SisPersonLibImgVo vo = sisPersonLibImgService.queryByPersonId(person.getId());
AddHWPersonReq req = new AddHWPersonReq(); AddHWPersonReq req = new AddHWPersonReq();
req.setIndex(CodePrefixConstants.PERSON_LIB_IMAGE_CODE_PREFIX + IdUtil.getSnowflakeNextIdStr()); req.setIndex(CodePrefixConstants.PERSON_LIB_IMAGE_CODE_PREFIX + IdUtil.getSnowflakeNextIdStr());
req.setName(person.getName()); req.setName(person.getName());
req.setCredentialType("5");
req.setCredentialNumber(vo.getId().toString());
req.setGender(person.getSex() == 1 ? "0" : person.getSex() == 2 ? "1" : "-1"); req.setGender(person.getSex() == 1 ? "0" : person.getSex() == 2 ? "1" : "-1");
ArrayList<String> pictures = new ArrayList<>(); ArrayList<String> pictures = new ArrayList<>();

View File

@@ -1,7 +1,7 @@
package org.dromara.sis.runner; package org.dromara.sis.runner;
import lombok.extern.slf4j.Slf4j; 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.ApplicationArguments;
import org.springframework.boot.ApplicationRunner; import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -19,22 +19,35 @@ public class ElevatorTcpRunner implements ApplicationRunner {
@Override @Override
public void run(ApplicationArguments args) { public void run(ApplicationArguments args) {
// 获取单例实例并启动服务 // 获取单例实例
ElevatorControlUtil instance = ElevatorControlUtil.getInstance(); ElevatorControlTcpUtil elevatorHelper = ElevatorControlTcpUtil.getInstance();
try{ // 设置连接监听器
elevatorHelper.setConnectionListener(new ElevatorControlTcpUtil.ConnectionListener() {
@Override
public void onConnected() {
log.info("梯控设备已连接");
}
@Override
public void onDisconnected() {
log.info("梯控设备已断开");
}
});
try {
// 启动服务 // 启动服务
instance.start(23); elevatorHelper.start(23);
log.info("启动电梯控制服务成功"); log.info("电梯控制TCP服务启动成功");
// 添加关闭钩子
Runtime.getRuntime().addShutdownHook(new Thread(() -> { Runtime.getRuntime().addShutdownHook(new Thread(() -> {
// 停止服务 log.info("应用关闭中停止电梯控制TCP服务...");
log.info("应用关闭中,停止电梯服务..."); elevatorHelper.stop();
instance.stop();
})); }));
} catch (IOException e) { } catch (IOException e) {
log.info("启动电梯控制服务失败"); System.err.println("无法启动电梯控制TCP服务: " + e.getMessage());
} }
} }
} }

View File

@@ -1,9 +1,14 @@
package org.dromara.sis.sdk.hik.calback; package org.dromara.sis.sdk.hik.calback;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.sis.domain.SisDeviceManage;
import org.dromara.sis.sdk.hik.HCNetSDK; 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.dromara.sis.service.IZeroSensationPassageService;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -11,6 +16,7 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
@@ -21,6 +27,7 @@ import static org.dromara.sis.sdk.hik.HCNetSDK.*;
@RequiredArgsConstructor @RequiredArgsConstructor
public class HikAlarmCallBack implements HCNetSDK.FMSGCallBack_V31 { public class HikAlarmCallBack implements HCNetSDK.FMSGCallBack_V31 {
private final ISisDeviceManageService sisDeviceManageService;
private final IZeroSensationPassageService zeroSensationPassageService; private final IZeroSensationPassageService zeroSensationPassageService;
@Override @Override
@@ -243,12 +250,9 @@ public class HikAlarmCallBack implements HCNetSDK.FMSGCallBack_V31 {
Pointer pFaceSnapMatch = strFaceSnapMatch.getPointer(); Pointer pFaceSnapMatch = strFaceSnapMatch.getPointer();
pFaceSnapMatch.write(0, pAlarmInfo.getByteArray(0, strFaceSnapMatch.size()), 0, strFaceSnapMatch.size()); pFaceSnapMatch.write(0, pAlarmInfo.getByteArray(0, strFaceSnapMatch.size()), 0, strFaceSnapMatch.size());
strFaceSnapMatch.read(); strFaceSnapMatch.read();
//比对结果0-保留1-比对成功2-比对失败 handleFaceComparison(strFaceSnapMatch, pAlarmer);
String sFaceSnapMatchInfo = "比对结果:" + strFaceSnapMatch.byContrastStatus + ",相似度:" + strFaceSnapMatch.fSimilarity; break;
} }
default: { default: {
} }
@@ -262,9 +266,8 @@ public class HikAlarmCallBack implements HCNetSDK.FMSGCallBack_V31 {
* *
* @param result 人脸数据 * @param result 人脸数据
* @param pAlarmer 设备数据 * @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); ByteBuffer buffers = result.pBuffer1.getByteBuffer(0, result.dwFacePicLen);
byte[] smallImg = new byte[result.dwFacePicLen]; byte[] smallImg = new byte[result.dwFacePicLen];
@@ -279,8 +282,48 @@ public class HikAlarmCallBack implements HCNetSDK.FMSGCallBack_V31 {
//设备ip //设备ip
String sAlarmInfo = new String(pAlarmer.sDeviceIP).trim(); String sAlarmInfo = new String(pAlarmer.sDeviceIP).trim();
log.info("海康设备告警信息上传,设备={}, 人脸图片大小={} 背景图片大小={}", sAlarmInfo, smallImg.length, bigImg.length); log.info("海康设备告警信息上传,设备={}, 人脸图片大小={} 背景图片大小={}", sAlarmInfo, smallImg.length, bigImg.length);
zeroSensationPassageService.pass(sAlarmInfo, smallImg, bigImg);
return false; SisDeviceManage device = sisDeviceManageService.queryByDeviceIp(sAlarmInfo);
if (!device.getIsComparison()) {
log.info("设备不支持人脸比对");
zeroSensationPassageService.pass(sAlarmInfo, smallImg, bigImg);
}
}
/**
* 处理人脸比对上报
*/
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());
} }

View File

@@ -1,7 +1,7 @@
package org.dromara.sis.sdk.smartDevices.utils; package org.dromara.sis.sdk.smartDevices.utils;
import org.springframework.stereotype.Component; import lombok.Setter;
import org.springframework.stereotype.Service; import lombok.extern.slf4j.Slf4j;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -9,53 +9,63 @@ import java.io.OutputStream;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/** /**
* @author lsm * @author lsm
* @apiNote ElevatorControlUtil * @apiNote ElevatorControlTcpUtil
* @since 2025/8/8 * @since 2025/8/8
*/ */
@Service @Slf4j
public class ElevatorControlUtil { public class ElevatorControlTcpUtil {
private static final int FRAME_LENGTH = 10; private static final int FRAME_LENGTH = 10;
private static final byte FIXED_ADDRESS = 0x00; private static final byte FIXED_ADDRESS = 0x00;
private static final byte MANUAL_COMMAND = (byte) 0xD1; private static final byte MANUAL_COMMAND = (byte) 0xD1;
private static final byte AUTO_COMMAND = (byte) 0xD2; private static final byte AUTO_COMMAND = (byte) 0xD2;
private static final byte MANUAL_RESPONSE = (byte) 0xC1; private static final byte MANUAL_RESPONSE = (byte) 0xC1;
private static final byte AUTO_RESPONSE = (byte) 0xC2; 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 ServerSocket serverSocket;
private Socket clientSocket; private Socket clientSocket;
private InputStream inputStream; private InputStream inputStream;
private OutputStream outputStream; private OutputStream outputStream;
private final Object lock = new Object(); private final Object lock = new Object();
private ScheduledExecutorService heartbeatScheduler;
private volatile boolean isRunning = false; 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) { if (instance == null) {
instance = new ElevatorControlUtil(); instance = new ElevatorControlTcpUtil();
} }
return instance; return instance;
} }
/** /**
* 启动TCP服务 * 启动TCP服务
*
* @param port 监听端口 * @param port 监听端口
*/ */
public void start(Integer port) throws IOException { public void start(int port) throws IOException {
if (isRunning) { if (isRunning) {
throw new IllegalStateException("服务已在运行中"); throw new IllegalStateException("服务已在运行中");
} }
@@ -64,8 +74,8 @@ public class ElevatorControlUtil {
isRunning = true; isRunning = true;
// 启动连接监听线程 // 启动连接监听线程
new Thread(this::acceptConnections, "TCP-Acceptor").start(); executor.execute(this::acceptConnections);
System.out.println("电梯控制服务已启动,监听端口: " + port); log.info("电梯控制TCP服务已启动,监听端口: {}", port);
} }
/** /**
@@ -74,98 +84,71 @@ public class ElevatorControlUtil {
public void stop() { public void stop() {
isRunning = false; isRunning = false;
// 停止心跳 // 关闭客户端连接
if (heartbeatScheduler != null) {
heartbeatScheduler.shutdown();
}
// 关闭连接
closeClientResources(); closeClientResources();
// 关闭服务器 // 关闭服务器
if (serverSocket != null && !serverSocket.isClosed()) { if (serverSocket != null && !serverSocket.isClosed()) {
try { try {
serverSocket.close(); serverSocket.close();
System.out.println("服务已停止"); log.info("电梯控制TCP服务已停止");
} catch (IOException e) { } catch (IOException e) {
System.err.println("停止服务时出错: " + e.getMessage()); log.error("停止电梯控制TCP服务时出错: {}", e.getMessage());
} }
} }
// 关闭线程池
executor.shutdown();
} }
/** /**
* 接受客户端连接 * 接受客户端连接
*/ */
private void acceptConnections() { private void acceptConnections() {
while (isRunning) { while (isRunning && !serverSocket.isClosed()) {
try { try {
clientSocket = serverSocket.accept(); log.info("等待梯控设备连接...");
clientSocket.setKeepAlive(true); Socket newClient = serverSocket.accept();
inputStream = clientSocket.getInputStream();
outputStream = clientSocket.getOutputStream();
System.out.println("梯控设备已连接: " + clientSocket.getRemoteSocketAddress()); synchronized (lock) {
// 关闭现有连接如果有
closeClientResources();
// 启动心跳机制 // 接受新连接
startHeartbeat(); clientSocket = newClient;
inputStream = clientSocket.getInputStream();
outputStream = clientSocket.getOutputStream();
log.info("梯控设备已连接: {}", clientSocket.getRemoteSocketAddress());
// 通知连接状态变化
if (connectionListener != null) {
connectionListener.onConnected();
}
}
} catch (IOException e) { } catch (IOException e) {
if (isRunning) { if (isRunning) {
System.err.println("接受连接时出错: " + e.getMessage()); log.error("接受连接时出错: {}", e.getMessage());
try {
Thread.sleep(5000); // 5秒后重试
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
} }
} }
} }
} }
/**
* 启动心跳机制
*/
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() { public boolean isClientConnected() {
return clientSocket != null && clientSocket.isConnected() && !clientSocket.isClosed(); synchronized (lock) {
return clientSocket != null &&
clientSocket.isConnected() &&
!clientSocket.isClosed();
}
} }
/** /**
* 发送手动选层命令 * 发送手动选层命令
*
* @param floors 要开放的楼层列表 * @param floors 要开放的楼层列表
* @return 是否成功 * @return 是否成功
*/ */
@@ -175,6 +158,7 @@ public class ElevatorControlUtil {
/** /**
* 发送自动选层命令 * 发送自动选层命令
*
* @param floors 要开放的楼层列表 * @param floors 要开放的楼层列表
* @return 是否成功 * @return 是否成功
*/ */
@@ -195,18 +179,24 @@ public class ElevatorControlUtil {
private boolean sendCommand(byte command, byte expectedResponse, byte[] floorData) { private boolean sendCommand(byte command, byte expectedResponse, byte[] floorData) {
if (!isClientConnected()) { if (!isClientConnected()) {
System.err.println("发送命令失败:未连接梯控设备"); log.info("发送命令失败:未连接梯控设备");
return false; return false;
} }
if (floorData == null || floorData.length != 7) { if (floorData == null || floorData.length != 7) {
System.err.println("发送命令失败:无效的楼层数据"); log.info("发送命令失败:无效的楼层数据");
return false; return false;
} }
synchronized (lock) { synchronized (lock) {
for (int attempt = 0; attempt < 2; attempt++) { for (int attempt = 0; attempt < 2; attempt++) {
try { try {
// 检查连接是否仍然有效
if (!isClientConnected()) {
log.info("连接在发送前已断开");
return false;
}
byte[] frame = buildFrame(command, floorData); byte[] frame = buildFrame(command, floorData);
outputStream.write(frame); outputStream.write(frame);
outputStream.flush(); outputStream.flush();
@@ -219,19 +209,23 @@ public class ElevatorControlUtil {
while (bytesRead < FRAME_LENGTH) { while (bytesRead < FRAME_LENGTH) {
int read = inputStream.read(response, bytesRead, FRAME_LENGTH - bytesRead); int read = inputStream.read(response, bytesRead, FRAME_LENGTH - bytesRead);
if (read == -1) { if (read == -1) {
throw new IOException("连接关闭"); // 连接关闭
handleConnectionClosed();
return false;
} }
bytesRead += read; bytesRead += read;
} }
if (validateResponse(response, expectedResponse)) { if (validateResponse(response, expectedResponse)) {
return true; return true;
} else {
log.info("响应验证失败,尝试重试");
} }
} catch (java.net.SocketTimeoutException e) { } catch (java.net.SocketTimeoutException e) {
System.err.println("命令响应超时,尝试重试"); log.info("命令响应超时,尝试重试");
} catch (IOException e) { } catch (IOException e) {
System.err.println("发送命令时出错: " + e.getMessage()); log.error("发送命令时出错: {}", e.getMessage());
closeClientResources(); handleConnectionClosed();
return false; return false;
} }
} }
@@ -239,6 +233,17 @@ public class ElevatorControlUtil {
} }
} }
/**
* 处理连接关闭
*/
private void handleConnectionClosed() {
log.info("检测到连接已关闭");
closeClientResources();
if (connectionListener != null) {
connectionListener.onDisconnected();
}
}
/** /**
* 生成楼层数据 * 生成楼层数据
*/ */
@@ -276,34 +281,61 @@ public class ElevatorControlUtil {
} }
private boolean validateResponse(byte[] response, byte expectedHeader) { private boolean validateResponse(byte[] response, byte expectedHeader) {
if (response[0] != expectedHeader) return false; if (response[0] != expectedHeader) {
if (response[1] != FIXED_ADDRESS) return false; log.info("响应帧头错误,期望: {},实际:{}", expectedHeader, response[0]);
return false;
}
if (response[1] != FIXED_ADDRESS) {
log.info("响应地址错误");
return false;
}
byte checksum = 0; byte checksum = 0;
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++) {
checksum = (byte) (checksum + response[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() { private void closeClientResources() {
try { synchronized (lock) {
if (inputStream != null) inputStream.close(); try {
if (outputStream != null) outputStream.close(); if (inputStream != null) inputStream.close();
if (clientSocket != null && !clientSocket.isClosed()) { if (outputStream != null) outputStream.close();
clientSocket.close(); if (clientSocket != null && !clientSocket.isClosed()) {
clientSocket.close();
}
log.info("客户端连接已关闭");
} catch (IOException e) {
log.error("关闭连接时出错: {}", e.getMessage());
} finally {
clientSocket = null;
inputStream = null;
outputStream = null;
// 通知连接断开
if (connectionListener != null) {
connectionListener.onDisconnected();
}
} }
System.out.println("客户端连接已关闭");
} catch (IOException e) {
System.err.println("关闭连接时出错: " + e.getMessage());
} finally {
clientSocket = null;
inputStream = null;
outputStream = null;
} }
} }
/**
* 连接状态监听接口
*/
public interface ConnectionListener {
void onConnected();
void onDisconnected();
}
} }

View File

@@ -70,21 +70,18 @@ public interface ISisDeviceManageService {
/** /**
* 通过设备ip查询设备信息 * 通过设备ip查询设备信息
* * @param deviceIp 设备ip
* @param deviceIp 设备编码
* @return 设备信息 * @return 设备信息
*/ */
SisDeviceManageVo queryVoByDeviceIp(String deviceIp); SisDeviceManage queryByDeviceIp(String deviceIp);
SisDeviceManage queryByDeviceIp(String deviceId);
/** /**
* 查询设备数 * 查询设备数
* *
* @return * @return tree
*/ */
List<TreeNode<Long>> tree(); List<TreeNode<Long>> tree();
/** /**
* 通过设备id列表查询设备信息 * 通过设备id列表查询设备信息
* @param deviceIds 设备id列表 * @param deviceIds 设备id列表

View File

@@ -11,4 +11,11 @@ public interface IZeroSensationPassageService {
*/ */
void pass(String deviceIp, byte[] smallImp, byte[] bigImg); void pass(String deviceIp, byte[] smallImp, byte[] bigImg);
/**
* 电梯外部按键触发
*
* @param deviceIp 设备ip
*/
void handleEleOut(String deviceIp);
} }

View File

@@ -177,18 +177,15 @@ public class SisDeviceManageServiceImpl implements ISisDeviceManageService {
log.info("删除设备通道完成,num={}", num); log.info("删除设备通道完成,num={}", num);
} }
/**
* 通过设备ip查询设备信息
* @param deviceIp 设备ip
* @return 设备信息
*/
@Override @Override
public SisDeviceManageVo queryVoByDeviceIp(String deviceIp) { public SisDeviceManage queryByDeviceIp(String deviceIp) {
LambdaQueryWrapper<SisDeviceManage> lqw = Wrappers.lambdaQuery(); LambdaQueryWrapper<SisDeviceManage> lqw = Wrappers.lambdaQuery();
lqw.eq(SisDeviceManage::getDeviceIp, deviceIp); 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); return baseMapper.selectOne(lqw);
} }

View File

@@ -202,6 +202,9 @@ public class SisElevatorFloorRefServiceImpl implements ISisElevatorFloorRefServi
lqw.in(SisElevatorFloorRef::getFloorId, info.stream().map(SisElevatorFloorChannelRef::getFloorId).toList()); lqw.in(SisElevatorFloorRef::getFloorId, info.stream().map(SisElevatorFloorChannelRef::getFloorId).toList());
List<SisElevatorFloorRef> list = baseMapper.selectList(lqw); List<SisElevatorFloorRef> list = baseMapper.selectList(lqw);
// list为空不需要冗余数据返回true
if(list.isEmpty()) return true;
// 创建Map提高查找效率避免在循环中重复流操作 // 创建Map提高查找效率避免在循环中重复流操作
Map<Long, SisElevatorFloorChannelRef> floorInfoMap = info.stream() Map<Long, SisElevatorFloorChannelRef> floorInfoMap = info.stream()
.collect(Collectors.toMap(SisElevatorFloorChannelRef::getFloorId, Function.identity())); .collect(Collectors.toMap(SisElevatorFloorChannelRef::getFloorId, Function.identity()));

View File

@@ -252,7 +252,7 @@ public class SisElevatorInfoServiceImpl implements ISisElevatorInfoService {
// 冗余数据到电梯⇄楼层关联表 // 冗余数据到电梯⇄楼层关联表
Boolean update = elevatorFloorRefService.batchUpdateChannel(channelRefs); Boolean update = elevatorFloorRefService.batchUpdateChannel(channelRefs);
Assert.isTrue(update, "冗余数据到电梯⇄楼层关联表失败!");
} }
/** /**

View File

@@ -10,6 +10,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference; import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.property.api.RemoteFloorService; import org.dromara.property.api.RemoteFloorService;
import org.dromara.property.api.domain.vo.RemoteFloorVo; 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.ControlTypeEnum;
import org.dromara.sis.domain.enums.RosterTypeEnum; import org.dromara.sis.domain.enums.RosterTypeEnum;
import org.dromara.sis.domain.vo.*; 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.hik.HikApiService;
import org.dromara.sis.sdk.huawei.HuaWeiBoxApi; import org.dromara.sis.sdk.huawei.HuaWeiBoxApi;
import org.dromara.sis.sdk.huawei.domain.HWResult; 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.dromara.sis.service.*;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -46,6 +47,7 @@ public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageSer
private final ISisDeviceBindRefService deviceBindRefService; private final ISisDeviceBindRefService deviceBindRefService;
private final ISisAccessControlService accessControlService; private final ISisAccessControlService accessControlService;
private final ISisElevatorFloorRefService elevatorFloorRefService; private final ISisElevatorFloorRefService elevatorFloorRefService;
private final ISisElevatorFloorChannelRefService elevatorFloorChannelRefService;
private final E8PlatformApi e8PlatformApi; private final E8PlatformApi e8PlatformApi;
private final ISisAlarmEventsService alarmEventsService; private final ISisAlarmEventsService alarmEventsService;
@@ -115,11 +117,11 @@ public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageSer
} }
// 判断绑定设备类型,走不同的处理方法 // 判断绑定设备类型,走不同的处理方法
if (Objects.equals(item.getControlType(), ControlTypeEnum.ACCESS_CONTROL.getCode())) { // 门禁 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())) { // 电梯外面面板权限 } 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())) { // 电梯里面的面板 } 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 { } else {
log.info("设备绑定了未知的控制类型[{}],不处理", item.getControlType()); log.info("设备绑定了未知的控制类型[{}],不处理", item.getControlType());
} }
@@ -127,6 +129,39 @@ public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageSer
log.info("权限下发执行完成,耗时:{}ms", interval.intervalMs()); 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);
});
}
/** /**
* 生成告警事件 * 生成告警事件
*/ */
@@ -192,7 +227,7 @@ public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageSer
for (int i = 1; i < floorList.size(); i++) { for (int i = 1; i < floorList.size(); i++) {
int finalI = i; int finalI = i;
// 取出权限楼层id与实际楼层id相等的数据 // 取出权限楼层id与实际楼层id相等的数据
vo = eleRef.stream().filter(o -> Objects.equals(o.getFloorId(), floorList.get(finalI-1).getId())).findFirst().orElse(null); vo = eleRef.stream().filter(o -> Objects.equals(o.getFloorId(), floorList.get(finalI - 1).getId())).findFirst().orElse(null);
// 存在权限楼层添加到num中梯控模块从1开始 // 存在权限楼层添加到num中梯控模块从1开始
if (vo != null) { if (vo != null) {
num.add(i); num.add(i);
@@ -200,11 +235,11 @@ public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageSer
} }
if (CollUtil.isEmpty(num)) return; if (CollUtil.isEmpty(num)) return;
if (!ElevatorControlUtil.getInstance().isClientConnected()){ if (!ElevatorControlTcpUtil.getInstance().isClientConnected()) {
log.info("梯控模块未连接,请检查梯控模块是否启动"); log.info("梯控模块未连接,请检查梯控模块是否启动");
return; return;
} }
ElevatorControlUtil.getInstance().sendManualCommand(num); ElevatorControlTcpUtil.getInstance().sendManualCommand(num);
} }
log.info("梯控下发权限完成"); log.info("梯控下发权限完成");