From 9cf672b041976c31ae13b7c4e041429c96cf99ea Mon Sep 17 00:00:00 2001 From: tangzh Date: Thu, 3 Jul 2025 19:28:44 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eladmin/eladmin-system/pom.xml | 6 - .../config/enums/CapabilitieEnum.java | 2 + .../security/config/enums/MsgEnum.java | 4 +- .../system/service/WebSocketService.java | 5 +- .../impl/WebSocketSdcpServiceImpl.java | 269 +++++++----------- .../service/impl/WebSocketVueServiceImpl.java | 122 ++++++-- .../system/service/webstocket/SocketMsg.java | 6 +- .../service/webstocket/WebSocketParam.java | 20 +- .../webstocket/req/WebSocketReqDTO.java | 38 ++- .../webstocket/req/WebSocketReqData.java | 86 ++++-- .../src/main/resources/config/application.yml | 8 - 11 files changed, 331 insertions(+), 235 deletions(-) diff --git a/eladmin/eladmin-system/pom.xml b/eladmin/eladmin-system/pom.xml index eeb1fe3..eb6edc8 100644 --- a/eladmin/eladmin-system/pom.xml +++ b/eladmin/eladmin-system/pom.xml @@ -30,12 +30,6 @@ - - - - - - me.zhengjie eladmin-logging diff --git a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/enums/CapabilitieEnum.java b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/enums/CapabilitieEnum.java index 66b6e7f..5517990 100644 --- a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/enums/CapabilitieEnum.java +++ b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/enums/CapabilitieEnum.java @@ -7,6 +7,8 @@ public enum CapabilitieEnum { PAUSE, // 暂停 PRINT, // 打印 CONTINUE, // 继续 + ALARM_CONTINUE, // 报警继续 + ALARM_EXIT, // 报警退出 EXIT, // 退出 IMAGE, // 图片 OPEN_VIDEO, // 打开-视频 diff --git a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/enums/MsgEnum.java b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/enums/MsgEnum.java index 21be45d..02478e1 100644 --- a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/enums/MsgEnum.java +++ b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/enums/MsgEnum.java @@ -20,7 +20,9 @@ public enum MsgEnum { CONNECT, /** 关闭 */ CLOSE, - /** 信息 */ + /** 状态变化*/ + STATUS, + /** 信息返回 */ INFO, /** 错误 */ ERROR, diff --git a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/WebSocketService.java b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/WebSocketService.java index e8618e6..8fd95f8 100644 --- a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/WebSocketService.java +++ b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/WebSocketService.java @@ -2,7 +2,6 @@ package me.zhengjie.modules.system.service; import me.zhengjie.config.properties.FileProperties; import me.zhengjie.modules.system.domain.dto.ImageDataVo; -import me.zhengjie.modules.system.domain.dto.VideoDataVo; import me.zhengjie.utils.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -34,9 +33,9 @@ public class WebSocketService { // 存储设备号 public static List deviceList = new ArrayList<>(); // 存储观看视频的用户信息 - public static Map videoUser = new LinkedHashMap<>(); + public static Map> videoUser = new HashMap<>(); // 存放查看图片的用户信息 - public static Map imageUser = new LinkedHashMap<>(); + public static Map imageUser = new HashMap<>(); // 存储连接的客户端 public String channel; diff --git a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/WebSocketSdcpServiceImpl.java b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/WebSocketSdcpServiceImpl.java index 59afbf0..9e2cbde 100644 --- a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/WebSocketSdcpServiceImpl.java +++ b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/WebSocketSdcpServiceImpl.java @@ -17,10 +17,12 @@ import org.springframework.stereotype.Component; import javax.websocket.*; import javax.websocket.server.ServerEndpoint; -import java.io.File; import java.io.IOException; +import java.util.Arrays; +import java.util.Base64; import java.util.HashMap; import java.util.Map; +import java.util.stream.Collectors; @ServerEndpoint("/webSocket/sdcp") @Slf4j @@ -60,8 +62,11 @@ public class WebSocketSdcpServiceImpl extends WebSocketService { public void onError(Session session, Throwable error) { WebSocketService collect = getSocket(WebSocketConfig.TOPIC_PREFIX); if (null == collect) { return; } - log.info("SDCP服务端 发现异常:channel={}", collect.channel); + long time = System.currentTimeMillis(); + log.info("【+++++++++++++++++++++++++++++ ↓ " + time + " ↓ +++++++++++++++++++++++++++++】"); + log.info("SDCP服务端 发现异常:channel={},errorMsg={}", collect.channel, error.getMessage()); error.printStackTrace(); + log.info("【+++++++++++++++++++++++++++++ ↑ " + time + " ↑ +++++++++++++++++++++++++++++】"); } /** @@ -73,24 +78,10 @@ public class WebSocketSdcpServiceImpl extends WebSocketService { WebSocketService collect = getSocket(WebSocketConfig.TOPIC_PREFIX); if (null == collect) { return; } long time = System.currentTimeMillis(); - log.info("【+++++++++++++++++++++++++++++ " + time + " +++++++++++++++++++++++++++++】"); + log.info("【+++++++++++++++++++++++++++++ ↓ " + time + " ↓ +++++++++++++++++++++++++++++】"); log.info("SDCP服务端 收到消息:channel={},message={}", collect.channel, message); serviceMessageHandle(session, message); - log.info("【+++++++++++++++++++++++++++++ " + time + " +++++++++++++++++++++++++++++】"); - } - - /** - * 收到客户端消息后调用的方法 - * @param message 客户端发送过来的消息 - */ - @OnMessage - public void onMessage(Session session, byte[] message) { - try { - byteImgDataHandle(message); - // byteImgDataHandle(new String(message, "UTF-8")); - } catch (Exception e) { - e.printStackTrace(); - } + log.info("【+++++++++++++++++++++++++++++ ↑ " + time + " ↑ +++++++++++++++++++++++++++++】"); } // 连接关闭状态刷新 @@ -105,62 +96,51 @@ public class WebSocketSdcpServiceImpl extends WebSocketService { // 初始状态刷新消息(Cmd:0) 指令 private void openDeviceStatus() { + log.info(">>> 初始化设备状态"); + WebSocketService socket = getSocket(WebSocketConfig.TOPIC_PREFIX); for (String deviceSn : deviceList) { long currentTimeLong = System.currentTimeMillis(); - WebSocketReqDTO reqDTO = new WebSocketReqDTO(); - reqDTO.setTopic(WebSocketConfig.TOPIC_PREFIX + "/" + MethodEnum.request.name() + "/" + deviceSn); + Map dataParam = new HashMap<>(); + dataParam.put("UserId", socket.session.getId()); WebSocketReqData data = new WebSocketReqData(); data.setCmd(0); - data.setData(new HashMap()); + data.setData(dataParam); data.setRequestID(currentTimeLong + ""); data.setMainboardID(deviceSn); data.setTimeStamp(currentTimeLong); data.setFrom(0); + WebSocketReqDTO reqDTO = new WebSocketReqDTO(); + reqDTO.setTopic(WebSocketConfig.TOPIC_PREFIX + "/" + MethodEnum.request.name() + "/" + deviceSn); reqDTO.setData(data); - serviceMessageHandle(null, JSON.toJSONString(reqDTO)); + String message = JSON.toJSONString(reqDTO); + try { + log.info("发送【获取初始化】指令:channel={},message={}", channel, message); + socket.session.getBasicRemote().sendText(message); + } catch (IOException e) { throw new RuntimeException(e); } } - } - - private void byteImgDataHandle(byte[] message) { - byte[] byteImg = message; - String deviceSn = "12345678"; - String userId = "1"; - // 获取用户端的session,给当前用户发送消息 - WebSocketService uSocket = clients.get(userId); - if (null == uSocket || null == uSocket.session || !uSocket.session.isOpen()) { - log.info("<<< 用户【{}】已退出连接无需发送,忽略", userId); - return; - } - ImageDataVo imageDataVo = imageUser.get(uSocket.session.getId()); - imageDataVo.imgWrite(byteImg); - imageUser.put(uSocket.session.getId(), imageDataVo); - Map commandResult = new HashMap<>(); - commandResult.put("deviceSn", deviceSn); - commandResult.put("chunkIndex", "0"); // 图片当前分片数 - commandResult.put("totalChunks", "12"); // 图片总的分片数 - sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, "图片传输中", MsgEnum.WRITEIMG)), uSocket.channel, uSocket.session); + log.info("<<< 初始化设备"); } // 处理二进制图片 private void byteImgDataHandle(String message) { - String info = message.substring(message.indexOf("{"), message.indexOf("}") + 1); - byte[] byteImg = message.substring(message.indexOf("}") + 1, message.length()).trim().getBytes(); - JSONObject jsonObject = JSON.parseObject(info); - String deviceSn = jsonObject.get("MainboardID").toString(); - String userId = jsonObject.get("UserId").toString(); - // 获取用户端的session,给当前用户发送消息 + Map dataMap = Arrays.stream(message.split("&")) + .map(s-> s.split("=")) + .collect(Collectors.toMap(data-> data[0], data -> data[1])); + String deviceSn = dataMap.get("MainboardID").toString(); + String userId = dataMap.get("UserId").toString(); + String img64 = dataMap.get("Data").toString(); WebSocketService uSocket = clients.get(userId); if (null == uSocket || null == uSocket.session || !uSocket.session.isOpen()) { log.info("<<< 用户【{}】已退出连接无需发送,忽略", userId); return; } ImageDataVo imageDataVo = imageUser.get(uSocket.session.getId()); - imageDataVo.imgWrite(byteImg); + imageDataVo.imgWrite(Base64.getDecoder().decode(img64)); imageUser.put(uSocket.session.getId(), imageDataVo); Map commandResult = new HashMap<>(); commandResult.put("deviceSn", deviceSn); - commandResult.put("chunkIndex", jsonObject.get("ChunkIndex")); // 图片当前分片数 - commandResult.put("totalChunks", jsonObject.get("TotalChunks")); // 图片总的分片数 + commandResult.put("chunkIndex", dataMap.get("ChunkIndex")); // 图片当前分片数 + commandResult.put("totalChunks", dataMap.get("TotalChunks")); // 图片总的分片数 sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, "图片传输中", MsgEnum.WRITEIMG)), uSocket.channel, uSocket.session); } @@ -181,7 +161,8 @@ public class WebSocketSdcpServiceImpl extends WebSocketService { param = JSON.parseObject(message, WebSocketResDTO.class); method = param.getMethod(); } catch (Exception e) { - e.printStackTrace(); + // json转换失败,说明是传输图片 + byteImgDataHandle(message); return; } if (null == method) { @@ -195,125 +176,100 @@ public class WebSocketSdcpServiceImpl extends WebSocketService { return; } if (method == MethodEnum.request) { - try { - WebSocketService socket = getSocket(WebSocketConfig.TOPIC_PREFIX); - socket.session.getBasicRemote().sendText(message); - } catch (IOException e) { throw new RuntimeException(e); } return; } // 状态与消息前置参数定义 - CurrentStatusEnum status = null; - PrintInfoStatusEnum print = null; - ErrorStatusEnum error = null; - String remark = null; - MsgEnum msgEnum = null; String uChannel = null; Session uSession = null; - + String remark = ""; + MsgEnum msgEnum = null; WebSocketResDTO resDTO = JSON.parseObject(message, WebSocketResDTO.class); Map commandResult = new HashMap<>(); commandResult.put("deviceSn", deviceSn); if (method == MethodEnum.response) { // 指令响应消息 WebSocketResData data = param.getData(); + JSONObject cData = JSON.parseObject(data.getData().toString()); + if (!cData.containsKey("UserId")) { + log.info("<<< 该消息不是用户指令请求反馈,忽略"); + return; + } + WebSocketService uSocket = clients.get(cData.get("UserId").toString()); + if (!(null == uSocket || null == uSocket.session || !uSocket.session.isOpen())) { + uChannel = uSocket.channel; + uSession = uSocket.session; + } Integer cmd = data.getCmd(); // 开始打印 if (cmd.equals(128)) { - String msg = ""; - JSONObject cData = JSON.parseObject(data.getData().toString()); int Ack = Integer.parseInt(cData.get("Ack").toString()); - if (Ack == 0) { - status = CurrentStatusEnum.SDCP_MACHINE_STATUS_PRINTING; - print = PrintInfoStatusEnum.SDCP_PRINT_STATUS_SPADE; - error = ErrorStatusEnum.SDCP_PRINT_ERROR_NONE; - remark = "正在打印中"; - msgEnum = MsgEnum.INFO; - } else { + if (Ack != 0) { if (Ack == 1) { - msg = "设备忙"; + remark = "设备忙"; } else if (Ack == 2) { - msg = "未找到目标文件"; + remark = "未找到目标文件"; } else if (Ack == 3) { - msg = "文件读取失败"; + remark = "文件读取失败"; } else if (Ack == 4) { - msg = "文件分辨率不匹配"; + remark = "文件分辨率不匹配"; } else if (Ack == 5) { - msg = "无法识别的文件格式"; + remark = "无法识别的文件格式"; } - status = CurrentStatusEnum.SDCP_MACHINE_STATUS_PRINTING; - print = PrintInfoStatusEnum.SDCP_PRINT_STATUS_FILE_CHECKING; - error = ErrorStatusEnum.SDCP_PRINT_ERROR_CHECKFILE; - remark = msg; msgEnum = MsgEnum.ERROR; } } // 暂停打印 else if (cmd.equals(129)) { - JSONObject cData = JSON.parseObject(data.getData().toString()); int Ack = Integer.parseInt(cData.get("Ack").toString()); - if (Ack == 0) { - status = CurrentStatusEnum.SDCP_MACHINE_STATUS_IDLE; - print = PrintInfoStatusEnum.SDCP_PRINT_STATUS_PAUSED; - error = ErrorStatusEnum.SDCP_PRINT_ERROR_NONE; - remark = "已暂停打印"; - msgEnum = MsgEnum.INFO; - } else { - status = CurrentStatusEnum.SDCP_MACHINE_STATUS_PRINTING; - print = PrintInfoStatusEnum.SDCP_PRINT_STATUS_PAUSING; - error = ErrorStatusEnum.SDCP_PRINT_ERROR_FAILURE; + if (Ack != 0) { remark = "暂停打印失败"; msgEnum = MsgEnum.ERROR; } } // 退出打印 else if (cmd.equals(130)) { - JSONObject cData = JSON.parseObject(data.getData().toString()); int Ack = Integer.parseInt(cData.get("Ack").toString()); - if (Ack == 0) { - status = CurrentStatusEnum.SDCP_MACHINE_STATUS_IDLE; - print = PrintInfoStatusEnum.SDCP_PRINT_STATUS_IDLE; - error = ErrorStatusEnum.SDCP_PRINT_ERROR_NONE; - remark = "已退出打印"; - msgEnum = MsgEnum.INFO; - } else { - status = CurrentStatusEnum.SDCP_MACHINE_STATUS_PRINTING; - print = PrintInfoStatusEnum.SDCP_PRINT_STATUS_SPADE; - error = ErrorStatusEnum.SDCP_PRINT_ERROR_NONE; + if (Ack != 0) { remark = "退出打印失败"; msgEnum = MsgEnum.ERROR; } } // 继续 else if (cmd.equals(131)) { - JSONObject cData = JSON.parseObject(data.getData().toString()); int Ack = Integer.parseInt(cData.get("Ack").toString()); - if (Ack == 0) { - status = CurrentStatusEnum.SDCP_MACHINE_STATUS_PRINTING; - print = PrintInfoStatusEnum.SDCP_PRINT_STATUS_SPADE; - error = ErrorStatusEnum.SDCP_PRINT_ERROR_NONE; - remark = "继续打印中"; - msgEnum = MsgEnum.INFO; - } else { - status = CurrentStatusEnum.SDCP_MACHINE_STATUS_IDLE; - print = PrintInfoStatusEnum.SDCP_PRINT_STATUS_PAUSED; - error = ErrorStatusEnum.SDCP_PRINT_ERROR_FAILURE; + if (Ack != 0) { remark = "继续打印失败"; msgEnum = MsgEnum.ERROR; } } + // 图片异物报警继续 + else if (cmd.equals(132)) { + int Ack = Integer.parseInt(cData.get("Ack").toString()); + if (Ack != 0) { + remark = "图片异物报警继续失败"; + msgEnum = MsgEnum.ERROR; + } + } + // 图片异物报警退出 + else if (cmd.equals(133)) { + int Ack = Integer.parseInt(cData.get("Ack").toString()); + if (Ack != 0) { + remark = "图片异物报警退出失败"; + msgEnum = MsgEnum.ERROR; + } + } // 获取图片 else if (cmd.equals(385)) { - JSONObject cData = JSON.parseObject(data.getData().toString()); - WebSocketService uSocket = clients.get(cData.get("UserId").toString()); - if (null == uSocket || null == uSocket.session || !uSocket.session.isOpen()) { - log.info("<<< 用户 {} 已退出连接无需发送,忽略", cData.get("UserId")); - return; - } // 处理图片异常/图片接收时 if (cData.containsKey("Ack")) { int Ack = Integer.parseInt(cData.get("Ack").toString()); + // 准备接收图片前期信息 + if (Ack == 0 && cData.containsKey("Type") && cData.get("Type").toString().equals("start")) { + remark = "图片准备传输"; + msgEnum = MsgEnum.WRITEIMG; + } // 图片获取失败 - if (Ack == 1) { + else if (Ack == 1) { remark = "图片获取失败"; msgEnum = MsgEnum.ERROR; } @@ -327,57 +283,50 @@ public class WebSocketSdcpServiceImpl extends WebSocketService { remark = "未知错误"; msgEnum = MsgEnum.ERROR; } - // 准备接收图片前期信息 - else if (Ack == 0 && cData.containsKey("Type") && cData.get("Type").toString().equals("start")) { - remark = "图片准备传输"; - msgEnum = MsgEnum.WRITEIMG; - } - uChannel = uSocket.channel; - uSession = uSocket.session; } else if (cData.containsKey("Type") && cData.get("Type").toString().equals("end")) { + if (null == uSession) { + log.info("<<< 用户【{}】已退出连接无需发送图片,忽略", cData.get("UserId")); + return; + } // 图片接收结束,生成图片,给前端推送图片链接 - ImageDataVo imageDataVo = imageUser.get(uSocket.session.getId()); + ImageDataVo imageDataVo = imageUser.get(uSession.getId()); byte[] imageAllData = imageDataVo.getFullImageData(); - String imgDir = myFileProperties.getPath().getPath() + "image" + File.separator; + String folder = "image/"; + String imgDir = myFileProperties.getPath().getPath() + folder; String imgUrl = imageDataVo.saveImage(imageAllData, imgDir); - commandResult.put("imageUrl", imgUrl); - imageUser.remove(uSocket.session.getId()); - + commandResult.put("imageUrl", "/file/" + folder + imgUrl); remark = "图片完成传输"; msgEnum = MsgEnum.INFO; - uChannel = uSocket.channel; - uSession = uSocket.session; + imageUser.remove(uSession.getId()); } } // 打开/关闭视频 else if (cmd.equals(386)) { - JSONObject cData = JSON.parseObject(data.getData().toString()); - WebSocketService uSocket = clients.get(cData.get("UserID").toString()); int Ack = Integer.parseInt(cData.get("Ack").toString()); if (Ack == 0) { + commandResult.put("videoUrl", cData.get("VideoUrl")); remark = "指令响应成功"; msgEnum = MsgEnum.INFO; - commandResult.put("videoUrl", cData.get("VideoUrl")); - } else if (Ack == 1) { - remark = "超过最大同时拉流限制"; - msgEnum = MsgEnum.ERROR; - } else if (Ack == 2) { - remark = "摄像头不存在"; - msgEnum = MsgEnum.ERROR; - } else if (Ack == 3) { - remark = "未知错误"; + } else { + if (Ack == 1) { + remark = "超过最大同时拉流限制"; + } else if (Ack == 2) { + remark = "摄像头不存在"; + } else if (Ack == 3) { + remark = "未知错误"; + } msgEnum = MsgEnum.ERROR; } - uChannel = uSocket.channel; - uSession = uSocket.session; } } else if (method == MethodEnum.status) { WebSocketResStatus resStatus = resDTO.getStatus(); - status = CurrentStatusEnum.getEnumByNum(resStatus.getCurrentStatus()); - print = PrintInfoStatusEnum.getEnumByNum(resStatus.getPrintInfo().getStatus()); - error = ErrorStatusEnum.SDCP_PRINT_ERROR_NONE; + CurrentStatusEnum status = CurrentStatusEnum.getEnumByNum(resStatus.getCurrentStatus());; + PrintInfoStatusEnum print = PrintInfoStatusEnum.getEnumByNum(resStatus.getPrintInfo().getStatus());; + ErrorStatusEnum error = ErrorStatusEnum.getEnumByNum(resStatus.getPrintInfo().getErrorNumber()); remark = "状态已更新"; - msgEnum = MsgEnum.INFO; + myDeviceService.updateDeviceStatus(deviceSn, status, print, error, remark); + sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, remark, MsgEnum.STATUS)), null, null); + return; } else if (method == MethodEnum.attributes) { WebSocketResAttributes attributes = resDTO.getAttributes(); BusDevice entity = new BusDevice(); @@ -390,18 +339,20 @@ public class WebSocketSdcpServiceImpl extends WebSocketService { return; } else if (method == MethodEnum.error) { WebSocketResStatus resStatus = resDTO.getStatus(); - status = CurrentStatusEnum.getEnumByNum(resStatus.getCurrentStatus()); - print = PrintInfoStatusEnum.getEnumByNum(resStatus.getPrintInfo().getStatus()); - error = ErrorStatusEnum.SDCP_PRINT_ERROR_FAILURE; + CurrentStatusEnum status = CurrentStatusEnum.getEnumByNum(resStatus.getCurrentStatus());; + PrintInfoStatusEnum print = PrintInfoStatusEnum.getEnumByNum(resStatus.getPrintInfo().getStatus());; + ErrorStatusEnum error = ErrorStatusEnum.getEnumByNum(resStatus.getPrintInfo().getErrorNumber()); remark = "设备发生异常"; - msgEnum = MsgEnum.ERROR; + myDeviceService.updateDeviceStatus(deviceSn, status, print, error, remark); + sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, remark, MsgEnum.STATUS)), null, null); + return; } else if (method == MethodEnum.notice) { } - if (null != status && null != print && null != error) { - myDeviceService.updateDeviceStatus(deviceSn, status, print, error, remark); + // 给指定连接发送消息 + if (null != msgEnum) { + sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, remark, msgEnum)), uChannel, uSession); } - sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, remark, msgEnum)), uChannel, uSession); } // 发送消息给指定前端 @@ -421,7 +372,7 @@ public class WebSocketSdcpServiceImpl extends WebSocketService { // 发送消息给前端 private void sendMessage(String message, String channel, Session session) { - if (!session.isOpen()) { return; } + if (null != session && !session.isOpen()) { return; } try { log.info(">>> 推送消息给VUE:channel={},message={}", (StringUtils.isEmpty(channel) ? session.getId() : channel), message); session.getBasicRemote().sendText(message); diff --git a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/WebSocketVueServiceImpl.java b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/WebSocketVueServiceImpl.java index c50990d..2fe3e62 100644 --- a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/WebSocketVueServiceImpl.java +++ b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/WebSocketVueServiceImpl.java @@ -3,14 +3,10 @@ package me.zhengjie.modules.system.service.impl;//package me.zhengjie.modules.sy import com.alibaba.fastjson2.JSON; import lombok.extern.slf4j.Slf4j; import me.zhengjie.modules.security.config.WebSocketConfig; -import me.zhengjie.modules.security.config.enums.CapabilitieEnum; -import me.zhengjie.modules.security.config.enums.CurrentStatusEnum; -import me.zhengjie.modules.security.config.enums.MethodEnum; -import me.zhengjie.modules.security.config.enums.MsgEnum; +import me.zhengjie.modules.security.config.enums.*; import me.zhengjie.modules.system.domain.BusDevice; import me.zhengjie.modules.system.domain.dto.BusDeviceQueryCriteria; import me.zhengjie.modules.system.domain.dto.ImageDataVo; -import me.zhengjie.modules.system.domain.dto.VideoDataVo; import me.zhengjie.modules.system.service.WebSocketService; import me.zhengjie.modules.system.service.webstocket.SocketMsg; import me.zhengjie.modules.system.service.webstocket.req.WebSocketReqDTO; @@ -24,6 +20,7 @@ import javax.websocket.*; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.*; +import java.util.stream.Collectors; @ServerEndpoint("/webSocket/vue") @Slf4j @@ -47,6 +44,31 @@ public class WebSocketVueServiceImpl extends WebSocketService { } } + // 每1分钟检测用户是否断开,断开则需要将视频断开 + @Scheduled(fixedRate = 60000) + public void checkCloseVideo() { + List uClients = clients.keySet().stream().filter(i -> !i.equals(WebSocketConfig.TOPIC_PREFIX)).collect(Collectors.toList()); + if (uClients.isEmpty() && !videoUser.isEmpty()) { + List deviceSns = new ArrayList<>(videoUser.keySet()); + for (String deviceSn : deviceSns) { + long sysTimeLong = System.currentTimeMillis(); + Map dataParam = new HashMap<>(); + dataParam.put("Enable", 0); + dataParam.put("UserId", "-1"); + WebSocketReqData data = new WebSocketReqData(); + data.setCmd(386); + data.setData(dataParam); + data.setRequestID(sysTimeLong + ""); + data.setMainboardID(deviceSn); + data.setTimeStamp(sysTimeLong); + WebSocketReqDTO req = new WebSocketReqDTO(); + req.setTopic(WebSocketConfig.TOPIC_PREFIX + "/" + MethodEnum.request + "/" + deviceSn); + req.setData(data); + sendThirdPartyMessage(JSON.toJSONString(req)); + } + } + } + /** * 连接调用方法 * @param session @@ -68,8 +90,7 @@ public class WebSocketVueServiceImpl extends WebSocketService { WebSocketService collect = getSocket(session.getId()); if (null == collect) { return; } log.info("VUE服务端 连接断开:channel={}", collect.channel); - imageUser.remove(collect.channel); - videoUser.remove(collect.channel); + clients.remove(collect.channel); } /** @@ -81,8 +102,11 @@ public class WebSocketVueServiceImpl extends WebSocketService { public void onError(Session session, Throwable error) { WebSocketService collect = getSocket(session.getId()); if (null == collect) { return; } - log.info("VUE服务端 发现异常:channel={}", collect.channel); + long time = System.currentTimeMillis(); + log.info("【----------------------------- ↓ " + time + " ↓ -----------------------------】"); + log.info("VUE服务端 发现异常:channel={},errorMsg={}", collect.channel, error.getMessage()); error.printStackTrace(); + log.info("【----------------------------- ↑ " + time + " ↑ -----------------------------】"); } /** @@ -94,10 +118,10 @@ public class WebSocketVueServiceImpl extends WebSocketService { WebSocketService collect = getSocket(session.getId()); if (null == collect) { return; } long time = System.currentTimeMillis(); - log.info("【----------------------------- " + time + " -----------------------------】"); + log.info("【----------------------------- ↓ " + time + " ↓ -----------------------------】"); log.info("VUE服务端 收到消息:channel={},message={}", collect.channel, message); serviceMessageHandle(session, message); - log.info("【----------------------------- " + time + " -----------------------------】"); + log.info("【----------------------------- ↑ " + time + " ↑ -----------------------------】"); } private void serviceMessageHandle(Session session, String message) { @@ -131,21 +155,24 @@ public class WebSocketVueServiceImpl extends WebSocketService { // {"Topic":"sdcp/request/12345678","command":"REFRESH"} if (command.equals(CapabilitieEnum.REFRESH.name())) { data.setCmd(0); - data.setData(new HashMap()); + Map dataParam = new HashMap<>(); + dataParam.put("UserId", session.getId()); + data.setData(dataParam); data.setType(0); } // 打印 // {"Topic":"sdcp/request/12345678","command":"PRINT"} else if (command.equals(CapabilitieEnum.PRINT.name())) { BusDevice device = myDeviceService.getByDeviceCode(deviceSn); - if (device.getStatus().equals(CurrentStatusEnum.SDCP_MACHINE_STATUS_PRINTING.getCode())) { + if (!device.getStatus().equals(CurrentStatusEnum.SDCP_MACHINE_STATUS_IDLE.getCode())) { Map commandResult = new HashMap<>(); commandResult.put("deviceSn", deviceSn); - sendVueMessage(session, JSON.toJSONString(new SocketMsg(commandResult, "设备已在任务中,请等空闲在操作", MsgEnum.ERROR))); + sendVueMessage(session, JSON.toJSONString(new SocketMsg(commandResult, "当前状态无法操作打印", MsgEnum.ERROR))); return; } Map dataParam = new HashMap<>(); - dataParam.put("Filename", "D:/duibi/200.3dp"); + dataParam.put("Filename", param.getFilename()); + dataParam.put("UserId", session.getId()); data.setCmd(128); data.setData(dataParam); data.setFrom(0); @@ -157,32 +184,63 @@ public class WebSocketVueServiceImpl extends WebSocketService { if (!device.getStatus().equals(CurrentStatusEnum.SDCP_MACHINE_STATUS_PRINTING.getCode())) { Map commandResult = new HashMap<>(); commandResult.put("deviceSn", deviceSn); - sendVueMessage(session, JSON.toJSONString(new SocketMsg(commandResult, "当前设备状态无法操作暂停", MsgEnum.ERROR))); + sendVueMessage(session, JSON.toJSONString(new SocketMsg(commandResult, "当前状态无法操作暂停", MsgEnum.ERROR))); return; } data.setCmd(129); - data.setData(new HashMap()); + Map dataParam = new HashMap<>(); + dataParam.put("UserId", session.getId()); + data.setData(dataParam); data.setFrom(0); } // 退出 // {"Topic":"sdcp/request/12345678","command":"EXIT"} else if (command.equals(CapabilitieEnum.EXIT.name())) { + BusDevice device = myDeviceService.getByDeviceCode(deviceSn); + if (device.getStatus().equals(CurrentStatusEnum.SDCP_MACHINE_STATUS_IDLE.getCode()) && device.getPrintStatus().equals(PrintInfoStatusEnum.SDCP_PRINT_STATUS_IDLE.getCode())) { + Map commandResult = new HashMap<>(); + commandResult.put("deviceSn", deviceSn); + sendVueMessage(session, JSON.toJSONString(new SocketMsg(commandResult, "当前状态无法操作退出", MsgEnum.ERROR))); + return; + } data.setCmd(130); - data.setData(new HashMap()); + Map dataParam = new HashMap<>(); + dataParam.put("UserId", session.getId()); + data.setData(dataParam); data.setFrom(0); } // 继续 // {"Topic":"sdcp/request/12345678","command":"CONTINUE"} else if (command.equals(CapabilitieEnum.CONTINUE.name())) { BusDevice device = myDeviceService.getByDeviceCode(deviceSn); - if (!device.getStatus().equals(CurrentStatusEnum.SDCP_MACHINE_STATUS_PRINTING.getCode())) { + if (!(device.getStatus().equals(CurrentStatusEnum.SDCP_MACHINE_STATUS_PRINTING.getCode()) && device.getPrintStatus().equals(PrintInfoStatusEnum.SDCP_PRINT_STATUS_PAUSED.getCode()))) { Map commandResult = new HashMap<>(); commandResult.put("deviceSn", deviceSn); - sendVueMessage(session, JSON.toJSONString(new SocketMsg(commandResult, "当前设备状态无法操作继续", MsgEnum.ERROR))); + sendVueMessage(session, JSON.toJSONString(new SocketMsg(commandResult, "当前状态无法操作继续", MsgEnum.ERROR))); return; } data.setCmd(131); - data.setData(new HashMap()); + Map dataParam = new HashMap<>(); + dataParam.put("UserId", session.getId()); + data.setData(dataParam); + data.setFrom(0); + } + // 图片异物报警继续 + // {"Topic":"sdcp/request/12345678","command":"ALARM_CONTINUE"} + else if (command.equals(CapabilitieEnum.ALARM_CONTINUE.name())) { + data.setCmd(132); + Map dataParam = new HashMap<>(); + dataParam.put("UserId", session.getId()); + data.setData(dataParam); + data.setFrom(0); + } + // 图片异物报警暂停 + // {"Topic":"sdcp/request/12345678","command":"ALARM_EXIT"} + else if (command.equals(CapabilitieEnum.ALARM_EXIT.name())) { + data.setCmd(133); + Map dataParam = new HashMap<>(); + dataParam.put("UserId", session.getId()); + data.setData(dataParam); data.setFrom(0); } // 图片 @@ -193,7 +251,7 @@ public class WebSocketVueServiceImpl extends WebSocketService { dataParam.put("Type", 0); dataParam.put("UserId", session.getId()); data.setData(dataParam); - // 记录用户查看图片 + // 记录用户获取图片 imageUser.put(session.getId(), new ImageDataVo()); } // 视频 @@ -203,14 +261,24 @@ public class WebSocketVueServiceImpl extends WebSocketService { data.setCmd(386); Map dataParam = new HashMap<>(); dataParam.put("Enable", command.equals(CapabilitieEnum.OPEN_VIDEO.name()) ? 1 : 0); - dataParam.put("UserID", command.equals(CapabilitieEnum.CLOSE_VIDEO.name()) && videoUser.size() == 1 && videoUser.containsKey(session.getId()) ? "0" : session.getId()); + dataParam.put("UserId", session.getId()); data.setData(dataParam); - // 记录用户打开视频 + LinkedList userIds = videoUser.get(deviceSn); + // 打开视频 if (command.equals(CapabilitieEnum.OPEN_VIDEO.name())) { - videoUser.put(session.getId(), new VideoDataVo()); - // 移除用户记录 - } else { - videoUser.remove(session.getId()); + userIds = (null == userIds ? new LinkedList<>() : userIds); + userIds.add(session.getId()); + videoUser.put(deviceSn, userIds); + } + // 关闭视频 + else { + userIds.remove(session.getId()); + if (!userIds.isEmpty()) { + videoUser.put(deviceSn, userIds); + } else { + dataParam.put("UserId", "-1"); + videoUser.remove(deviceSn); + } } } else { diff --git a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/webstocket/SocketMsg.java b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/webstocket/SocketMsg.java index 70613fa..84b19a1 100644 --- a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/webstocket/SocketMsg.java +++ b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/webstocket/SocketMsg.java @@ -23,16 +23,16 @@ public class SocketMsg { private Object data; private String msg; - private MsgEnum msgType; + private String msgType; public SocketMsg(String msg, MsgEnum msgType) { this.msg = msg; - this.msgType = msgType; + this.msgType = msgType.name(); } public SocketMsg(Object data, String msg, MsgEnum msgType) { this.data = data; this.msg = msg; - this.msgType = msgType; + this.msgType = msgType.name(); } } diff --git a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/webstocket/WebSocketParam.java b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/webstocket/WebSocketParam.java index 8248c37..0b43223 100644 --- a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/webstocket/WebSocketParam.java +++ b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/webstocket/WebSocketParam.java @@ -1,8 +1,7 @@ package me.zhengjie.modules.system.service.webstocket; -import com.alibaba.fastjson.annotation.JSONField; +import com.alibaba.fastjson2.annotation.JSONField; import jodd.util.StringUtil; -import lombok.Data; import me.zhengjie.modules.security.config.enums.MethodEnum; /** @@ -13,20 +12,31 @@ import me.zhengjie.modules.security.config.enums.MethodEnum; * 错误信息(主板->小程序):sdcp/error/${MainboardID} * 通知信息(主板->小程序):sdcp/notice/${MainboardID} */ -@Data public class WebSocketParam { // 消息topic - @JSONField(name = "Topic") private String Topic; // 设备ID - @JSONField(name = "MainboardID") private String MainboardID; // 消息类型 private MethodEnum method; + @JSONField(name = "Topic") + public String getTopic() { + return Topic; + } + + public void setTopic(String topic) { + Topic = topic; + } + + public void setMainboardID(String mainboardID) { + MainboardID = mainboardID; + } + + @JSONField(name = "MainboardID") public String getMainboardID() { if (StringUtil.isBlank(MainboardID)) { return getTopic().substring(getTopic().lastIndexOf("/") + 1); diff --git a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/webstocket/req/WebSocketReqDTO.java b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/webstocket/req/WebSocketReqDTO.java index 2da2d67..d58c5f1 100644 --- a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/webstocket/req/WebSocketReqDTO.java +++ b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/webstocket/req/WebSocketReqDTO.java @@ -1,16 +1,13 @@ package me.zhengjie.modules.system.service.webstocket.req; -import com.alibaba.fastjson.annotation.JSONField; -import lombok.Data; +import com.alibaba.fastjson2.annotation.JSONField; import me.zhengjie.modules.system.service.webstocket.WebSocketParam; import java.io.Serializable; -@Data public class WebSocketReqDTO extends WebSocketParam implements Serializable { // 消息参数 - @JSONField(name = "Data") private WebSocketReqData Data; // 机器品牌标识,32位UUID @@ -19,6 +16,39 @@ public class WebSocketReqDTO extends WebSocketParam implements Serializable { // 指令类型 CapabilitieEnum private String command; + // 打印的文件路径 private String filename; + @JSONField(name = "Data") + public WebSocketReqData getData() { + return Data; + } + + public void setData(WebSocketReqData data) { + Data = data; + } + + public String getId() { + return Id; + } + + public void setId(String id) { + Id = id; + } + + public String getCommand() { + return command; + } + + public void setCommand(String command) { + this.command = command; + } + + public String getFilename() { + return filename; + } + + public void setFilename(String filename) { + this.filename = filename; + } } diff --git a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/webstocket/req/WebSocketReqData.java b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/webstocket/req/WebSocketReqData.java index 4a8786b..952a860 100644 --- a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/webstocket/req/WebSocketReqData.java +++ b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/service/webstocket/req/WebSocketReqData.java @@ -1,38 +1,86 @@ package me.zhengjie.modules.system.service.webstocket.req; -import com.alibaba.fastjson.annotation.JSONField; -import lombok.Data; +import com.alibaba.fastjson2.annotation.JSONField; -import java.io.Serializable; import java.util.Map; -@Data -public class WebSocketReqData implements Serializable { +public class WebSocketReqData { // 请求命令 - @JSONField(name = "Cmd") - private Integer Cmd; - - @JSONField(name = "Data") + public Integer Cmd; + // 数据 private Map Data; - - @JSONField(name = "Type") + // 类型 private Integer Type; - // 请求ID - @JSONField(name = "RequestID") private String RequestID; - // 主板ID - @JSONField(name = "MainboardID") private String MainboardID; - // 时间戳 - @JSONField(name = "TimeStamp") private Long TimeStamp; - // 标识命令来源 - @JSONField(name = "From") private Integer From; + @JSONField(name = "Cmd") + public Integer getCmd() { + return Cmd; + } + + public void setCmd(Integer cmd) { + Cmd = cmd; + } + + @JSONField(name = "Data") + public Map getData() { + return Data; + } + + public void setData(Map data) { + Data = data; + } + + @JSONField(name = "Type") + public Integer getType() { + return Type; + } + + public void setType(Integer type) { + Type = type; + } + + @JSONField(name = "RequestID") + public String getRequestID() { + return RequestID; + } + + public void setRequestID(String requestID) { + RequestID = requestID; + } + + @JSONField(name = "MainboardID") + public String getMainboardID() { + return MainboardID; + } + + public void setMainboardID(String mainboardID) { + MainboardID = mainboardID; + } + + @JSONField(name = "TimeStamp") + public Long getTimeStamp() { + return TimeStamp; + } + + public void setTimeStamp(Long timeStamp) { + TimeStamp = timeStamp; + } + + @JSONField(name = "From") + public Integer getFrom() { + return From; + } + + public void setFrom(Integer from) { + From = from; + } } diff --git a/eladmin/eladmin-system/src/main/resources/config/application.yml b/eladmin/eladmin-system/src/main/resources/config/application.yml index 0925db1..95cdc87 100644 --- a/eladmin/eladmin-system/src/main/resources/config/application.yml +++ b/eladmin/eladmin-system/src/main/resources/config/application.yml @@ -19,14 +19,6 @@ mybatis-plus: local-cache-scope: SESSION spring: - websocket: - message-broker: - # 配置STOMP消息代理的相关属性(如果使用STOMP) - stomp: - # 入站消息的最大字节数 - inbound-message-size-limit: 2048KB # 默认值通常是64KB,根据需要调整 - # 出站消息的最大字节数 - outbound-message-size-limit: 2048KB freemarker: check-template-location: false profiles: