From f922b4f7f1eccf9f8b3c93db04492bd2b4e7f562 Mon Sep 17 00:00:00 2001 From: tangzh Date: Fri, 27 Jun 2025 17:58:52 +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 | 8 +- .../security/config/SpringSecurityConfig.java | 4 +- .../config/enums/CapabilitieEnum.java | 1 + .../config/enums/ErrorStatusEnum.java | 1 + .../security/config/enums/MsgEnum.java | 4 +- .../system/domain/dto/ImageDataVo.java | 49 +++ .../system/service/WebSocketService.java | 14 +- .../impl/WebSocketSdcpServiceImpl.java | 347 +++++++++++++----- .../service/impl/WebSocketVueServiceImpl.java | 147 +++++--- .../webstocket/req/WebSocketReqDTO.java | 2 + .../src/main/resources/config/application.yml | 8 + eladmin/pom.xml | 1 - 12 files changed, 445 insertions(+), 141 deletions(-) create mode 100644 eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/dto/ImageDataVo.java diff --git a/eladmin/eladmin-system/pom.xml b/eladmin/eladmin-system/pom.xml index 1ed15ac..eeb1fe3 100644 --- a/eladmin/eladmin-system/pom.xml +++ b/eladmin/eladmin-system/pom.xml @@ -30,9 +30,15 @@ + + + + + + me.zhengjie - eladmin-flv + eladmin-logging 1.1 diff --git a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SpringSecurityConfig.java b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SpringSecurityConfig.java index 78216f6..af24c3a 100644 --- a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SpringSecurityConfig.java +++ b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SpringSecurityConfig.java @@ -95,7 +95,9 @@ public class SpringSecurityConfig { "/webSocket/**" ).permitAll() // 视频播放 - .antMatchers("/api/front/flv/**").permitAll() +// .antMatchers( +// "/api/front/flv/**", +// "/api/front/m3u8/**").permitAll() // swagger 文档 .antMatchers("/swagger-ui.html").permitAll() .antMatchers("/swagger-resources/**").permitAll() 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 15bcb0c..66b6e7f 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 @@ -5,6 +5,7 @@ public enum CapabilitieEnum { REFRESH, // 刷新 PAUSE, // 暂停 + PRINT, // 打印 CONTINUE, // 继续 EXIT, // 退出 IMAGE, // 图片 diff --git a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/enums/ErrorStatusEnum.java b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/enums/ErrorStatusEnum.java index 2907fac..140e392 100644 --- a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/enums/ErrorStatusEnum.java +++ b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/enums/ErrorStatusEnum.java @@ -22,6 +22,7 @@ public enum ErrorStatusEnum { SDCP_PRINT_ERROR_DEFAULT(-1, "默认/断开"), SDCP_PRINT_ERROR_NONE(0 ,"正常"), + SDCP_PRINT_ERROR_FAILURE(8 ,"异常"), SDCP_PRINT_ERROR_CHECKFILE(1 ,"文件校验失败"), SDCP_PRINT_ERROR_DEVICE(2 ,"设备或加密出错"), SDCP_PRINT_ERROR_PREPARE(3 ,"打印准备过程出错"), 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 3ed1676..21be45d 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,11 +20,11 @@ public enum MsgEnum { CONNECT, /** 关闭 */ CLOSE, - /** 断开连接 */ - DISCONNECT, /** 信息 */ INFO, /** 错误 */ ERROR, + /** 写入中 */ + WRITEIMG, ; } diff --git a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/dto/ImageDataVo.java b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/dto/ImageDataVo.java new file mode 100644 index 0000000..b5453e5 --- /dev/null +++ b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/dto/ImageDataVo.java @@ -0,0 +1,49 @@ +package me.zhengjie.modules.system.domain.dto; + +import me.zhengjie.utils.FileUtil; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.web.multipart.MultipartFile; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class ImageDataVo { + + private List imgByteArray; + + public ImageDataVo() { + this.imgByteArray = new ArrayList<>(); + } + + public String saveImage(byte[] imageData, String imgDir) { + MultipartFile multipartFile = new MockMultipartFile("file", "img.jpg", "application/octet-stream", imageData); + File file = FileUtil.upload(multipartFile, imgDir); + return file.getName(); + } + + public void imgWrite(byte[] data) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + baos.write(data); + imgByteArray.add(baos); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public byte[] getFullImageData() { + ByteArrayOutputStream fullData = new ByteArrayOutputStream(); + try { + for (ByteArrayOutputStream chunk : imgByteArray) { + fullData.write(chunk.toByteArray()); + } + return fullData.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } +} 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 10889ec..e8618e6 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 @@ -1,5 +1,8 @@ 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; @@ -13,7 +16,9 @@ import java.util.concurrent.ConcurrentHashMap; public class WebSocketService { public static BusDeviceService myDeviceService; + public static FileProperties myFileProperties; @Autowired private BusDeviceService deviceService; + @Autowired private FileProperties fileProperties; // 初始化 @PostConstruct @@ -21,12 +26,17 @@ public class WebSocketService { if (null == myDeviceService) { myDeviceService = deviceService; } + if (null == myFileProperties) { + myFileProperties = fileProperties; + } } // 存储设备号 public static List deviceList = new ArrayList<>(); - // 观看视频的用户 - public static Set videoUser = new LinkedHashSet<>(); + // 存储观看视频的用户信息 + public static Map videoUser = new LinkedHashMap<>(); + // 存放查看图片的用户信息 + public static Map imageUser = new LinkedHashMap<>(); // 存储连接的客户端 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 de83639..59afbf0 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 @@ -6,6 +6,7 @@ import lombok.extern.slf4j.Slf4j; import me.zhengjie.modules.security.config.WebSocketConfig; import me.zhengjie.modules.security.config.enums.*; import me.zhengjie.modules.system.domain.BusDevice; +import me.zhengjie.modules.system.domain.dto.ImageDataVo; import me.zhengjie.modules.system.service.WebSocketService; import me.zhengjie.modules.system.service.webstocket.SocketMsg; import me.zhengjie.modules.system.service.webstocket.req.WebSocketReqDTO; @@ -16,6 +17,7 @@ import org.springframework.stereotype.Component; import javax.websocket.*; import javax.websocket.server.ServerEndpoint; +import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -33,7 +35,7 @@ public class WebSocketSdcpServiceImpl extends WebSocketService { public void onOpen(Session session) { this.session = session; this.channel = WebSocketConfig.TOPIC_PREFIX; - log.info("【SDCP服务端】连接成功:channel={}", channel); + log.info("SDCP服务端 连接成功:channel={}", channel); clients.put(channel, this); openDeviceStatus(); } @@ -45,7 +47,7 @@ public class WebSocketSdcpServiceImpl extends WebSocketService { public void onClose(Session session) { WebSocketService collect = getSocket(WebSocketConfig.TOPIC_PREFIX); if (null == collect) { return; } - log.info("【SDCP服务端】连接断开:channel={}", collect.channel); + log.info("SDCP服务端 连接断开:channel={}", collect.channel); closeDeviceStatus(); } @@ -58,7 +60,7 @@ 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); + log.info("SDCP服务端 发现异常:channel={}", collect.channel); error.printStackTrace(); } @@ -71,19 +73,34 @@ public class WebSocketSdcpServiceImpl extends WebSocketService { WebSocketService collect = getSocket(WebSocketConfig.TOPIC_PREFIX); if (null == collect) { return; } long time = System.currentTimeMillis(); - log.info("【SDCP服务端】收到消息:channel={},message={}", collect.channel, message); - log.info("【" + time + ":+++++++++++++++++++++++++++++】"); + log.info("【+++++++++++++++++++++++++++++ " + time + " +++++++++++++++++++++++++++++】"); + log.info("SDCP服务端 收到消息:channel={},message={}", collect.channel, message); serviceMessageHandle(session, message); - log.info("【" + time + ":+++++++++++++++++++++++++++++】"); + 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(); + } } // 连接关闭状态刷新 private void closeDeviceStatus() { - for (String deviceSn : deviceList) { - WebSocketReqDTO reqDTO = new WebSocketReqDTO(); - reqDTO.setTopic(WebSocketConfig.TOPIC_PREFIX + "/" + MethodEnum.close.name() + "/" + deviceSn); - serviceMessageHandle(null, JSON.toJSONString(reqDTO)); - } + CurrentStatusEnum status = CurrentStatusEnum.SDCP_MACHINE_STATUS_DEFAULT; + PrintInfoStatusEnum print = PrintInfoStatusEnum.SDCP_PRINT_STATUS_DEFAULT; + ErrorStatusEnum error = ErrorStatusEnum.SDCP_PRINT_ERROR_DEFAULT; + String remark = "已关闭连接"; + myDeviceService.updateDeviceStatus(null, status, print, error, remark); + sendVueMessage(JSON.toJSONString(new SocketMsg(new HashMap<>() , remark, MsgEnum.CLOSE)), null, null); } // 初始状态刷新消息(Cmd:0) 指令 @@ -104,6 +121,49 @@ public class WebSocketSdcpServiceImpl extends WebSocketService { } } + 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); + } + + // 处理二进制图片 + 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,给当前用户发送消息 + 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", jsonObject.get("ChunkIndex")); // 图片当前分片数 + commandResult.put("totalChunks", jsonObject.get("TotalChunks")); // 图片总的分片数 + sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, "图片传输中", MsgEnum.WRITEIMG)), uSocket.channel, uSocket.session); + } + // 处理服务端接收到的消息 private void serviceMessageHandle(Session session, String message) { if (StringUtils.isEmpty(message)) { return; } @@ -120,7 +180,10 @@ public class WebSocketSdcpServiceImpl extends WebSocketService { try { param = JSON.parseObject(message, WebSocketResDTO.class); method = param.getMethod(); - } catch (Exception e) { e.printStackTrace(); } + } catch (Exception e) { + e.printStackTrace(); + return; + } if (null == method) { log.info("<<< 请求类型有误,忽略"); return; @@ -128,7 +191,7 @@ public class WebSocketSdcpServiceImpl extends WebSocketService { String deviceSn = param.getMainboardID(); // 只关心已有的设备 if (!deviceList.contains(deviceSn)) { - log.info("<<< 设备【{}】在系统未找到,忽略", deviceSn); + log.info("<<< 设备 {} 在系统未找到,忽略", deviceSn); return; } if (method == MethodEnum.request) { @@ -138,6 +201,15 @@ public class WebSocketSdcpServiceImpl extends WebSocketService { } 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; + WebSocketResDTO resDTO = JSON.parseObject(message, WebSocketResDTO.class); Map commandResult = new HashMap<>(); commandResult.put("deviceSn", deviceSn); @@ -145,106 +217,217 @@ public class WebSocketSdcpServiceImpl extends WebSocketService { // 指令响应消息 WebSocketResData data = param.getData(); Integer cmd = data.getCmd(); - // 指令-获取图片 - if (cmd.equals(385)) { + // 开始打印 + if (cmd.equals(128)) { + String msg = ""; JSONObject cData = JSON.parseObject(data.getData().toString()); int Ack = Integer.parseInt(cData.get("Ack").toString()); if (Ack == 0) { - commandResult.put("imageType", cData.get("ImageType")); - commandResult.put("imageData", cData.get("ImageData")); - sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, "指令响应成功", MsgEnum.INFO))); - } else if (Ack == 1) { - sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, "图片获取失败", MsgEnum.ERROR))); - } else if (Ack == 2) { - sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, "不支持该类型图片", MsgEnum.ERROR))); - } else if (Ack == 3) { - sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, "未知错误", MsgEnum.ERROR))); + 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 == 1) { + msg = "设备忙"; + } else if (Ack == 2) { + msg = "未找到目标文件"; + } else if (Ack == 3) { + msg = "文件读取失败"; + } else if (Ack == 4) { + msg = "文件分辨率不匹配"; + } else if (Ack == 5) { + msg = "无法识别的文件格式"; + } + 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; + 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; + 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; + 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 == 1) { + remark = "图片获取失败"; + msgEnum = MsgEnum.ERROR; + } + // 不支持该类型图片 + else if (Ack == 2) { + remark = "不支持该类型图片"; + msgEnum = MsgEnum.ERROR; + } + // 未知错误 + else if (Ack == 3) { + 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")) { + // 图片接收结束,生成图片,给前端推送图片链接 + ImageDataVo imageDataVo = imageUser.get(uSocket.session.getId()); + byte[] imageAllData = imageDataVo.getFullImageData(); + String imgDir = myFileProperties.getPath().getPath() + "image" + File.separator; + String imgUrl = imageDataVo.saveImage(imageAllData, imgDir); + commandResult.put("imageUrl", imgUrl); + imageUser.remove(uSocket.session.getId()); + + remark = "图片完成传输"; + msgEnum = MsgEnum.INFO; + uChannel = uSocket.channel; + uSession = uSocket.session; + } + } + // 打开/关闭视频 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) { + remark = "指令响应成功"; + msgEnum = MsgEnum.INFO; commandResult.put("videoUrl", cData.get("VideoUrl")); - sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, "指令响应成功", MsgEnum.INFO))); } else if (Ack == 1) { - sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, "超过最大同时拉流限制", MsgEnum.ERROR))); + remark = "超过最大同时拉流限制"; + msgEnum = MsgEnum.ERROR; } else if (Ack == 2) { - sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, "摄像头不存在", MsgEnum.ERROR))); + remark = "摄像头不存在"; + msgEnum = MsgEnum.ERROR; } else if (Ack == 3) { - sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, "未知错误", MsgEnum.ERROR))); + remark = "未知错误"; + msgEnum = MsgEnum.ERROR; } + uChannel = uSocket.channel; + uSession = uSocket.session; } } else if (method == MethodEnum.status) { - WebSocketResStatus status = resDTO.getStatus(); - WebSocketResPrintInfo printInfo = status.getPrintInfo(); - myDeviceService.updateDeviceStatus( - deviceSn, - CurrentStatusEnum.getEnumByNum(status.getCurrentStatus()), - PrintInfoStatusEnum.getEnumByNum(printInfo.getStatus()), - ErrorStatusEnum.SDCP_PRINT_ERROR_NONE, - null - ); - sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, "状态更新", MsgEnum.INFO))); + WebSocketResStatus resStatus = resDTO.getStatus(); + status = CurrentStatusEnum.getEnumByNum(resStatus.getCurrentStatus()); + print = PrintInfoStatusEnum.getEnumByNum(resStatus.getPrintInfo().getStatus()); + error = ErrorStatusEnum.SDCP_PRINT_ERROR_NONE; + remark = "状态已更新"; + msgEnum = MsgEnum.INFO; } else if (method == MethodEnum.attributes) { WebSocketResAttributes attributes = resDTO.getAttributes(); - // String[] capabilities = attributes.getCapabilities(); BusDevice entity = new BusDevice(); entity.setDeviceSn(deviceSn); entity.setName(attributes.getName()); entity.setModel(attributes.getMachineName()); entity.setFirmwareVersion(attributes.getFirmwareVersion()); entity.setProtocolVersion(attributes.getProtocolVersion()); - // List commandList = new ArrayList<>(); - // for (String capability : capabilities) { - // BusDeviceCommand command = new BusDeviceCommand(); - // command.setCommandType(capability); - // commandList.add(command); - // } - // entity.setCommandList(commandList); myDeviceService.updateOrAdd(entity); + return; } else if (method == MethodEnum.error) { - WebSocketResStatus status = resDTO.getStatus(); - WebSocketResPrintInfo printInfo = status.getPrintInfo(); - myDeviceService.updateDeviceStatus( - deviceSn, - CurrentStatusEnum.getEnumByNum(status.getCurrentStatus()), - PrintInfoStatusEnum.getEnumByNum(printInfo.getStatus()), - ErrorStatusEnum.SDCP_PRINT_ERROR_NONE, - null - ); - sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, "设备发生异常", MsgEnum.ERROR))); + WebSocketResStatus resStatus = resDTO.getStatus(); + status = CurrentStatusEnum.getEnumByNum(resStatus.getCurrentStatus()); + print = PrintInfoStatusEnum.getEnumByNum(resStatus.getPrintInfo().getStatus()); + error = ErrorStatusEnum.SDCP_PRINT_ERROR_FAILURE; + remark = "设备发生异常"; + msgEnum = MsgEnum.ERROR; } else if (method == MethodEnum.notice) { - } else if (method == MethodEnum.close || method == MethodEnum.disconnect) { - String msg = (method == MethodEnum.close ? "已关闭连接" : "已断开连接"); - MsgEnum en = (method == MethodEnum.close ? MsgEnum.CLOSE : MsgEnum.DISCONNECT); - myDeviceService.updateDeviceStatus( - null, - CurrentStatusEnum.SDCP_MACHINE_STATUS_DEFAULT, - PrintInfoStatusEnum.SDCP_PRINT_STATUS_DEFAULT, - ErrorStatusEnum.SDCP_PRINT_ERROR_DEFAULT, - msg - ); - sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, msg, en))); + } + if (null != status && null != print && null != error) { + myDeviceService.updateDeviceStatus(deviceSn, status, print, error, remark); + } + sendVueMessage(JSON.toJSONString(new SocketMsg(commandResult, remark, msgEnum)), uChannel, uSession); + } + + // 发送消息给指定前端 + private void sendVueMessage(String message, String uChannel, Session uSession) { + if (null != uSession) { + sendMessage(message, uChannel, uSession); + return; + } + for (Map.Entry entry : clients.entrySet()) { + WebSocketService server = entry.getValue(); + String channel = server.channel; + Session session = server.session; + if (channel.equals(WebSocketConfig.TOPIC_PREFIX) || null == session || !session.isOpen()) { continue; } + sendMessage(message, channel, session); } } - // 发送消息给第三方 - private void sendVueMessage(String message) { - for (Map.Entry entry : clients.entrySet()) { - try { - WebSocketService server = entry.getValue(); - String channel = server.channel; - Session session = server.session; - if (channel.equals(WebSocketConfig.TOPIC_PREFIX) || null == session || !session.isOpen()) { continue; } - log.info(">>> 推送消息给VUE:channel={},message={}", channel, message); - session.getBasicRemote().sendText(message); - } catch (IOException e) { - e.printStackTrace(); - log.info("<<< 推送消息给VUE-异常 原因:", e); - } + // 发送消息给前端 + private void sendMessage(String message, String channel, Session session) { + if (!session.isOpen()) { return; } + try { + log.info(">>> 推送消息给VUE:channel={},message={}", (StringUtils.isEmpty(channel) ? session.getId() : channel), message); + session.getBasicRemote().sendText(message); + } catch (IOException e) { + e.printStackTrace(); + log.info("<<< 推送消息给VUE-异常 原因:", e); } } } \ No newline at end of file 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 086eef3..c50990d 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 @@ -4,15 +4,17 @@ 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.service.dto.JwtUserDto; +import me.zhengjie.modules.security.config.enums.MsgEnum; import me.zhengjie.modules.system.domain.BusDevice; -import me.zhengjie.modules.system.domain.User; 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; import me.zhengjie.modules.system.service.webstocket.req.WebSocketReqData; -import me.zhengjie.utils.SecurityUtils; import me.zhengjie.utils.StringUtils; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -53,7 +55,7 @@ public class WebSocketVueServiceImpl extends WebSocketService { public void onOpen(Session session) { this.session = session; this.channel = session.getId(); - log.info("【VUE服务端】连接成功:channel={}", channel); + log.info("VUE服务端 连接成功:channel={}", channel); clients.put(channel, this); } @@ -65,7 +67,9 @@ public class WebSocketVueServiceImpl extends WebSocketService { public void onClose(Session session) { WebSocketService collect = getSocket(session.getId()); if (null == collect) { return; } - log.info("【VUE服务端】连接断开:channel={}", collect.channel); + log.info("VUE服务端 连接断开:channel={}", collect.channel); + imageUser.remove(collect.channel); + videoUser.remove(collect.channel); } /** @@ -77,7 +81,7 @@ 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); + log.info("VUE服务端 发现异常:channel={}", collect.channel); error.printStackTrace(); } @@ -90,13 +94,13 @@ public class WebSocketVueServiceImpl extends WebSocketService { WebSocketService collect = getSocket(session.getId()); if (null == collect) { return; } long time = System.currentTimeMillis(); - log.info("【VUE服务端】收到消息:channel={},message={}", collect.channel, message); - log.info("【" + time + "-----------------------------】"); - serviceMessageHandle(message); - log.info("【" + time + "-----------------------------】"); + log.info("【----------------------------- " + time + " -----------------------------】"); + log.info("VUE服务端 收到消息:channel={},message={}", collect.channel, message); + serviceMessageHandle(session, message); + log.info("【----------------------------- " + time + " -----------------------------】"); } - private void serviceMessageHandle(String message) { + private void serviceMessageHandle(Session session, String message) { if (StringUtils.isEmpty(message)) { return; } // 发送的指令 message = message.replace("\\", ""); @@ -113,7 +117,7 @@ public class WebSocketVueServiceImpl extends WebSocketService { String deviceSn = param.getMainboardID(); // 只关心已有的设备 if (!deviceList.contains(deviceSn)) { - log.info("<<< 设备【{}】在系统未找到,忽略", deviceSn); + log.info("<<< 设备 {} 在系统未找到,忽略", deviceSn); return; } String command = param.getCommand(); @@ -121,77 +125,116 @@ public class WebSocketVueServiceImpl extends WebSocketService { log.info("<<< 命令为空,忽略"); return; } - String commandStr = null; long sysTimeLong = System.currentTimeMillis(); + WebSocketReqData data = new WebSocketReqData(); // 刷新 + // {"Topic":"sdcp/request/12345678","command":"REFRESH"} if (command.equals(CapabilitieEnum.REFRESH.name())) { - WebSocketReqData data = new WebSocketReqData(); data.setCmd(0); data.setData(new HashMap()); data.setType(0); - data.setRequestID(sysTimeLong + ""); - data.setMainboardID(deviceSn); - data.setTimeStamp(sysTimeLong); - WebSocketReqDTO req = new WebSocketReqDTO(); - req.setTopic(WebSocketConfig.TOPIC_PREFIX + "/" + MethodEnum.request + "/" + deviceSn); - req.setData(data); - commandStr = JSON.toJSONString(req); + } + // 打印 + // {"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())) { + Map commandResult = new HashMap<>(); + commandResult.put("deviceSn", deviceSn); + sendVueMessage(session, JSON.toJSONString(new SocketMsg(commandResult, "设备已在任务中,请等空闲在操作", MsgEnum.ERROR))); + return; + } + Map dataParam = new HashMap<>(); + dataParam.put("Filename", "D:/duibi/200.3dp"); + data.setCmd(128); + data.setData(dataParam); + data.setFrom(0); } // 暂停 + // {"Topic":"sdcp/request/12345678","command":"PAUSE"} else if (command.equals(CapabilitieEnum.PAUSE.name())) { - - } - // 继续 - else if (command.equals(CapabilitieEnum.CONTINUE.name())) { - + BusDevice device = myDeviceService.getByDeviceCode(deviceSn); + 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))); + return; + } + data.setCmd(129); + data.setData(new HashMap()); + data.setFrom(0); } // 退出 + // {"Topic":"sdcp/request/12345678","command":"EXIT"} else if (command.equals(CapabilitieEnum.EXIT.name())) { - + data.setCmd(130); + data.setData(new HashMap()); + 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())) { + Map commandResult = new HashMap<>(); + commandResult.put("deviceSn", deviceSn); + sendVueMessage(session, JSON.toJSONString(new SocketMsg(commandResult, "当前设备状态无法操作继续", MsgEnum.ERROR))); + return; + } + data.setCmd(131); + data.setData(new HashMap()); + data.setFrom(0); } // 图片 + // {"Topic":"sdcp/request/12345678","command":"IMAGE"} else if (command.equals(CapabilitieEnum.IMAGE.name())) { - Map dataParam = new HashMap<>(); - dataParam.put("Type", 0); - WebSocketReqData data = new WebSocketReqData(); data.setCmd(385); + Map dataParam = new HashMap<>(); + dataParam.put("Type", 0); + dataParam.put("UserId", session.getId()); 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); - commandStr = JSON.toJSONString(req); + // 记录用户查看图片 + imageUser.put(session.getId(), new ImageDataVo()); } // 视频 + // {"Topic":"sdcp/request/12345678","command":"OPEN_VIDEO"} + // {"Topic":"sdcp/request/12345678","command":"CLOSE_VIDEO"} else if (command.equals(CapabilitieEnum.OPEN_VIDEO.name()) || command.equals(CapabilitieEnum.CLOSE_VIDEO.name())) { - int uIndex = (videoUser.contains(session.getId())) ? new ArrayList<>(videoUser).indexOf(session.getId()) : videoUser.size(); + data.setCmd(386); Map dataParam = new HashMap<>(); dataParam.put("Enable", command.equals(CapabilitieEnum.OPEN_VIDEO.name()) ? 1 : 0); - dataParam.put("UserId", uIndex); - WebSocketReqData data = new WebSocketReqData(); - data.setCmd(386); + dataParam.put("UserID", command.equals(CapabilitieEnum.CLOSE_VIDEO.name()) && videoUser.size() == 1 && videoUser.containsKey(session.getId()) ? "0" : session.getId()); 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); - commandStr = JSON.toJSONString(req); // 记录用户打开视频 - if (command.equals(CapabilitieEnum.OPEN_VIDEO.name())) - videoUser.add(session.getId()); + if (command.equals(CapabilitieEnum.OPEN_VIDEO.name())) { + videoUser.put(session.getId(), new VideoDataVo()); // 移除用户记录 - else + } else { videoUser.remove(session.getId()); + } } else { log.info("<<< 命令类型未找到,忽略"); return; } - sendThirdPartyMessage(commandStr); + // 发送指令 + 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)); + } + + private void sendVueMessage(Session session, String message) { + try { + log.info("<<< 返回消息给VUE:message={}", message); + session.getBasicRemote().sendText(message); + } catch (IOException e) { + e.printStackTrace(); + log.info("<<< 返回消息给VUE-异常 原因:", e); + } } // 发送消息给第三方 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 0f07a9f..2da2d67 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 @@ -19,4 +19,6 @@ public class WebSocketReqDTO extends WebSocketParam implements Serializable { // 指令类型 CapabilitieEnum private String command; + private String filename; + } diff --git a/eladmin/eladmin-system/src/main/resources/config/application.yml b/eladmin/eladmin-system/src/main/resources/config/application.yml index 95cdc87..0925db1 100644 --- a/eladmin/eladmin-system/src/main/resources/config/application.yml +++ b/eladmin/eladmin-system/src/main/resources/config/application.yml @@ -19,6 +19,14 @@ 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: diff --git a/eladmin/pom.xml b/eladmin/pom.xml index 459b17b..c3f2133 100644 --- a/eladmin/pom.xml +++ b/eladmin/pom.xml @@ -12,7 +12,6 @@ eladmin-logging eladmin-system eladmin-generator - eladmin-flv 后台管理