From 25ea561dc8da08f3a6fe6946927a4fbdb9256472 Mon Sep 17 00:00:00 2001 From: Echo <4759156@qq.com> Date: Wed, 29 May 2024 17:46:59 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E8=80=83=E5=8B=A4=E4=BB=AA=E8=AE=BE?= =?UTF-8?q?=E5=A4=87websocket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handler/JsonWebSocketMessageHandler.java | 80 ++++++++++++++++--- .../AbstractWebSocketMessageSender.java | 37 ++++++++- .../core/sender/WebSocketMessageSender.java | 13 +++ .../core/session/WebSocketSessionManager.java | 29 +++++++ .../session/WebSocketSessionManagerImpl.java | 40 +++++++++- .../api/websocket/WebSocketSenderApi.java | 12 +++ .../websocket/dto/WebSocketSendReqDTO.java | 3 + .../api/websocket/WebSocketSenderApiImpl.java | 5 +- .../AttendanceWebSocketMessageListener.java | 40 ++++++++++ .../message/AttendanceReceiveMessage.java | 23 ++++++ .../message/AttendanceSendMessage.java | 22 +++++ .../attendance/AttendanceBaseMessage.java | 45 +++++++++++ .../attendance/AttendanceConstants.java | 37 +++++++++ 13 files changed, 370 insertions(+), 16 deletions(-) create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/AttendanceWebSocketMessageListener.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/message/AttendanceReceiveMessage.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/message/AttendanceSendMessage.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/attendance/AttendanceBaseMessage.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/attendance/AttendanceConstants.java diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/handler/JsonWebSocketMessageHandler.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/handler/JsonWebSocketMessageHandler.java index 9b63528b..2f96e6c3 100644 --- a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/handler/JsonWebSocketMessageHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/handler/JsonWebSocketMessageHandler.java @@ -2,11 +2,16 @@ package cn.iocoder.yudao.framework.websocket.core.handler; import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.TypeUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; +import cn.iocoder.yudao.framework.websocket.core.attendance.AttendanceConstants; import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListener; import cn.iocoder.yudao.framework.websocket.core.message.JsonWebSocketMessage; +import cn.iocoder.yudao.framework.websocket.core.session.WebSocketSessionManager; import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils; +import com.github.yulichang.toolkit.SpringContentUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketHandler; @@ -43,28 +48,79 @@ public class JsonWebSocketMessageHandler extends TextWebSocketHandler { @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { + // 1.1 空消息,跳过 if (message.getPayloadLength() == 0) { return; } - // 1.2 ping 心跳消息,直接返回 pong 消息。 - if (message.getPayloadLength() == 4 && Objects.equals(message.getPayload(), "ping")) { - session.sendMessage(new TextMessage("pong")); - return; + + String payload = message.getPayload() ; + boolean isTypeJSON = JSONUtil.isTypeJSON(payload) ; + if( isTypeJSON ) { + JSONObject object = new JSONObject(payload); + String cmd = object.getStr("cmd") ; //设备请求方法 + String sn = object.getStr("sn") ; //设备编号 + // 此指令服务端不需要回复 客户端声明 + if ( cmd !=null && cmd.equals("declare") ) { + log.info("[客户端声明]"+ "||"+ session.getId()+ "||"+ message.getPayload(), session.getId(), message.getPayload()); + //此处需要将sessionId 与sn 绑定 + WebSocketSessionManager webSocketSessionManager = SpringContentUtils.getBean(WebSocketSessionManager.class); + webSocketSessionManager.addSession(session,sn); + return; + } + + // 1.2 ping 心跳消息,直接返回 pong 消息。 + if ( cmd != null && cmd.equals("ping") ) { + log.info("[设备心跳]"+ "||"+ session.getId()+ "||"+ message.getPayload(), session.getId(), message.getPayload()); + session.sendMessage(new TextMessage("{\"cmd\": \"pong\"}")); + //TODO 更新设备心跳请求时间 + // 传入设备sn编码, 调用相关方法,更新对应sn的本次请求时间。 + // 并且将设备的状态,更新成在线状态 + + + return; + } + } else { + // 1.2 ping 心跳消息,直接返回 pong 消息。 + if (message.getPayloadLength() == 4 && Objects.equals(message.getPayload(), "ping")) { +// log.info("[WEB心跳]"+ "||"+ session.getId()+ "||"+ message.getPayload(), session.getId(), message.getPayload()); + session.sendMessage(new TextMessage("pong")); + return; + } } - // 2.1 解析消息 try { + // 2.1 解析消息 JsonWebSocketMessage jsonMessage = JsonUtils.parseObject(message.getPayload(), JsonWebSocketMessage.class); - if (jsonMessage == null) { + if (message.getPayload() == null) { log.error("[handleTextMessage][session({}) message({}) 解析为空]", session.getId(), message.getPayload()); return; } - if (StrUtil.isEmpty(jsonMessage.getType())) { - log.error("[handleTextMessage][session({}) message({}) 类型为空]", session.getId(), message.getPayload()); + + JSONObject object = new JSONObject(message.getPayload()); + String cmd = object.getStr("cmd") ; + if (StrUtil.isEmpty( cmd )) { + log.error("[handleTextMessage][session({}) message({}) 数据格错误]", session.getId(), message.getPayload()); return; } - // 2.2 获得对应的 WebSocketMessageListener + + if( cmd.equals(AttendanceConstants.CMD_TO_DEVICE) ) { + jsonMessage.setType("attendance-message-send") ; + //服务器下发数据到设备 + //TODO 记录服务器下数据 + + + }else if( cmd.equals(AttendanceConstants.CMD_TO_CLIENT) ) { + jsonMessage.setType("attendance-message-send") ; + //设备的响应数据返回服务器 + //{"cmd":"to_client","form":"QT74824","from":"QT74824","to":"system","data":{"cmd":"addUserRet","code":0,"msg":"下发成功","user_id":"999999"},"extra":"null"} + String data = object.getStr("data") ; + JSONObject dataObject = new JSONObject(data); + String msg= dataObject.getStr("msg") ; + // TODO 记录响应 + } + + // 2.2 获得对应的 WebSocketMessageListener 根据Type找到对应的处理监听器 WebSocketMessageListener messageListener = listeners.get(jsonMessage.getType()); if (messageListener == null) { log.error("[handleTextMessage][session({}) message({}) 监听器为空]", session.getId(), message.getPayload()); @@ -72,7 +128,11 @@ public class JsonWebSocketMessageHandler extends TextWebSocketHandler { } // 2.3 处理消息 Type type = TypeUtil.getTypeArgument(messageListener.getClass(), 0); - Object messageObj = JsonUtils.parseObject(jsonMessage.getContent(), type); + JSONObject object1 = new JSONObject(message.getPayload()); + Object data = object1.get("data"); + object1.set("data",data.toString()) ; + String string = object1.toString(); + Object messageObj = JsonUtils.parseObject(string, type); Long tenantId = WebSocketFrameworkUtils.getTenantId(session); TenantUtils.execute(tenantId, () -> messageListener.onMessage(session, messageObj)); } catch (Throwable ex) { diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/AbstractWebSocketMessageSender.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/AbstractWebSocketMessageSender.java index 3adfbbb2..256f44ba 100644 --- a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/AbstractWebSocketMessageSender.java +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/AbstractWebSocketMessageSender.java @@ -2,6 +2,8 @@ package cn.iocoder.yudao.framework.websocket.core.sender; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.websocket.core.message.JsonWebSocketMessage; import cn.iocoder.yudao.framework.websocket.core.session.WebSocketSessionManager; @@ -41,6 +43,36 @@ public abstract class AbstractWebSocketMessageSender implements WebSocketMessage send(sessionId, null, null, messageType, messageContent); } + @Override + public void snSend(String sn, String messageType, String messageContent) { + SNSend(sn, messageType, messageContent); + } + + /** + * 发送消息 + * + * @param sn 设备编码 编号 + * @param messageType 消息类型 + * @param messageContent 消息内容 + */ + public void SNSend(String sn, String messageType, String messageContent) { + // 1. 获得 Session 列表 + List sessions = Collections.emptyList(); + System.out.println("===="+ sn) ; + if (StrUtil.isNotEmpty(sn)) { + WebSocketSession session = sessionManager.getSessionByDeviceNum(sn); + if (session != null) { + sessions = Collections.singletonList(session); + } + } + if (CollUtil.isEmpty(sessions)) { + log.info("[send][sn({}) messageType({}) messageContent({}) 未匹配到sn设备]", + sn, messageType, messageContent); + } + // 2. 执行发送 + doSend(sessions, messageType, messageContent); + } + /** * 发送消息 * @@ -80,7 +112,10 @@ public abstract class AbstractWebSocketMessageSender implements WebSocketMessage */ public void doSend(Collection sessions, String messageType, String messageContent) { JsonWebSocketMessage message = new JsonWebSocketMessage().setType(messageType).setContent(messageContent); - String payload = JsonUtils.toJsonString(message); // 关键,使用 JSON 序列化 + +// JSONObject object = JSONUtil.parseObj(message.getContent()) ; + //消息内容中获取text 属性下的内容,用户发送给指定的设备 + String payload = messageContent; sessions.forEach(session -> { // 1. 各种校验,保证 Session 可以被发送 if (session == null) { diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/WebSocketMessageSender.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/WebSocketMessageSender.java index acddfb05..36d4a6ac 100644 --- a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/WebSocketMessageSender.java +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/WebSocketMessageSender.java @@ -37,6 +37,15 @@ public interface WebSocketMessageSender { */ void send(String sessionId, String messageType, String messageContent); + /** + * 发送消息给指定 Session + * + * @param sn 设备标号 编号 + * @param messageType 消息类型 + * @param messageContent 消息内容,JSON 格式 + */ + void snSend(String sn, String messageType, String messageContent); + default void sendObject(Integer userType, Long userId, String messageType, Object messageContent) { send(userType, userId, messageType, JsonUtils.toJsonString(messageContent)); } @@ -49,4 +58,8 @@ public interface WebSocketMessageSender { send(sessionId, messageType, JsonUtils.toJsonString(messageContent)); } + default void sendSNObject(String sn, String messageType, Object messageContent) { + snSend(sn, messageType, JsonUtils.toJsonString(messageContent)); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManager.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManager.java index a20643db..34862337 100644 --- a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManager.java +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManager.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.websocket.core.session; import org.springframework.web.socket.WebSocketSession; import java.util.Collection; +import java.util.Set; /** * {@link WebSocketSession} 管理器的接口 @@ -50,4 +51,32 @@ public interface WebSocketSessionManager { */ Collection getSessionList(Integer userType, Long userId); + + /** + * 添加 Session + * + * @param session Session + * @param sn 设备号 + */ + void addSession(WebSocketSession session, String sn); + + /** + * 获得指定设备编号的 Session + * + * @param sn 设备号 + * @return Session session + */ + WebSocketSession getSessionByDeviceNum(String sn); + + /** + * 获取设备SN的集合 + * @return + */ + Collection getSNSession(); + + /** + * 获取所有在线设备的SN + * @return + */ + Set getOnlineSN() ; } \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManagerImpl.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManagerImpl.java index e05e1a5f..fc7c9dfa 100644 --- a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManagerImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManagerImpl.java @@ -6,10 +6,7 @@ import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils; import org.springframework.web.socket.WebSocketSession; -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArrayList; @@ -21,6 +18,13 @@ import java.util.concurrent.CopyOnWriteArrayList; */ public class WebSocketSessionManagerImpl implements WebSocketSessionManager { + /** + * sn 与 WebSocketSession 映射 + * + * key:设备编号 + */ + private final ConcurrentMap snSessions = new ConcurrentHashMap<>(); + /** * id 与 WebSocketSession 映射 * @@ -39,6 +43,7 @@ public class WebSocketSessionManagerImpl implements WebSocketSessionManager { @Override public void addSession(WebSocketSession session) { + System.out.println("add###############"+ session.getId()); // 添加到 idSessions 中 idSessions.put(session.getId(), session); // 添加到 userSessions 中 @@ -65,8 +70,10 @@ public class WebSocketSessionManagerImpl implements WebSocketSessionManager { @Override public void removeSession(WebSocketSession session) { + System.out.println("remove###############"+ session.getId()); // 移除从 idSessions 中 idSessions.remove(session.getId()); + snSessions.remove(session.getId()); // 移除从 idSessions 中 LoginUser user = WebSocketFrameworkUtils.getLoginUser(session); if (user == null) { @@ -122,4 +129,29 @@ public class WebSocketSessionManagerImpl implements WebSocketSessionManager { return CollUtil.isNotEmpty(sessions) ? new ArrayList<>(sessions) : new ArrayList<>(); } + + @Override + public void addSession(WebSocketSession session, String sn){ + System.out.println("sn===="+ sn); + //添加之前先删除历史sn对应的snsession + snSessions.remove(sn) ; + // 添加到 idSessions 中 + snSessions.put(sn, session); + } + + @Override + public WebSocketSession getSessionByDeviceNum(String sn) { + return snSessions.get(sn); + } + + @Override + public Collection getSNSession(){ + return this.snSessions.values(); + } + + @Override + public Set getOnlineSN() { + Set snSet = this.snSessions.keySet(); + return snSet ; + } } diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApi.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApi.java index 5ed3c9f4..2f3901c4 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApi.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApi.java @@ -71,4 +71,16 @@ public interface WebSocketSenderApi { send(sessionId, messageType, JsonUtils.toJsonString(messageContent)); } + + /** + * 发送消息给指定 SN + * + * @param sn 设备 编号 + * @param messageType 消息类型 + * @param messageContent 消息内容,JSON 格式 + */ + default void sendSN(String sn, String messageType, String messageContent) { + send(new WebSocketSendReqDTO().setSn(sn) + .setMessageType(messageType).setMessageContent(messageContent)).checkError(); + } } diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/dto/WebSocketSendReqDTO.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/dto/WebSocketSendReqDTO.java index 0f321a8c..31d0c5c8 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/dto/WebSocketSendReqDTO.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/dto/WebSocketSendReqDTO.java @@ -9,6 +9,9 @@ import javax.validation.constraints.NotEmpty; @Data public class WebSocketSendReqDTO { + @Schema(description = "sn 编号", example = "QT74824") + private String sn; + @Schema(description = "Session 编号", example = "abc") private String sessionId; @Schema(description = "用户编号", example = "1024") diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApiImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApiImpl.java index 53c98dd0..97b9032d 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApiImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApiImpl.java @@ -20,7 +20,10 @@ public class WebSocketSenderApiImpl implements WebSocketSenderApi { @Override public CommonResult send(WebSocketSendReqDTO message) { - if (StrUtil.isNotEmpty(message.getSessionId())) { + if (StrUtil.isNotEmpty(message.getSn())) { + webSocketMessageSender.snSend(message.getSn(), + message.getMessageType(), message.getMessageContent()); + }else if (StrUtil.isNotEmpty(message.getSessionId())) { webSocketMessageSender.send(message.getSessionId(), message.getMessageType(), message.getMessageContent()); } else if (message.getUserType() != null && message.getUserId() != null) { diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/AttendanceWebSocketMessageListener.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/AttendanceWebSocketMessageListener.java new file mode 100644 index 00000000..38f03184 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/AttendanceWebSocketMessageListener.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.infra.websocket; + +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListener; +import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils; +import cn.iocoder.yudao.module.infra.websocket.message.AttendanceReceiveMessage; +import cn.iocoder.yudao.module.infra.websocket.message.AttendanceSendMessage; +import cn.iocoder.yudao.module.infra.websocket.message.DemoReceiveMessage; +import cn.iocoder.yudao.module.infra.websocket.message.DemoSendMessage; +import org.springframework.stereotype.Component; +import org.springframework.web.socket.WebSocketSession; + +import javax.annotation.Resource; + +/** + * 考勤仪设备 WebSocket 数据通信 + * + + */ +@Component +public class AttendanceWebSocketMessageListener implements WebSocketMessageListener { + + @Resource + private WebSocketMessageSender webSocketMessageSender; + + @Override + public void onMessage(WebSocketSession session, AttendanceSendMessage message) { + String sn = session.getId() ; + AttendanceReceiveMessage toMessage = new AttendanceReceiveMessage().setFrom("system") + .setData(message.getData()); + webSocketMessageSender.sendSNObject(sn, "attendance-message-send", toMessage); + } + + @Override + public String getType() { + return "attendance-message-send"; + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/message/AttendanceReceiveMessage.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/message/AttendanceReceiveMessage.java new file mode 100644 index 00000000..b6f0daf0 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/message/AttendanceReceiveMessage.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.infra.websocket.message; + +import lombok.Data; + +/** + * 示例:server -> client 同步消息 + * + + */ +@Data +public class AttendanceReceiveMessage { + + /** + * 接收人的编号 + */ + private String from; + /** + * 内容 + */ + private String data; + + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/message/AttendanceSendMessage.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/message/AttendanceSendMessage.java new file mode 100644 index 00000000..1d073100 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/message/AttendanceSendMessage.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.infra.websocket.message; + +import lombok.Data; + +/** + * 示例:client -> server 发送消息 + * + + */ +@Data +public class AttendanceSendMessage { + + /** + * 发送给哪个设备 + */ + private String to; + /** + * 内容 + */ + private String data; + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/attendance/AttendanceBaseMessage.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/attendance/AttendanceBaseMessage.java new file mode 100644 index 00000000..6de29468 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/attendance/AttendanceBaseMessage.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.system.attendance; + +import cn.hutool.json.JSONObject; +import lombok.Data; + +/** + * 功能描述 + * + * @author: yj + * @date: 2024年05月27日 10:48 + */ +@Data +public class AttendanceBaseMessage { + + /** + * 固定为 to_device + */ + public final String cmd = AttendanceConstants.CMD_BASE; + + /** + * 这个字段对设备来说没有任何作用,只是在响应指令时在 to 字段中附带回服务端。 + * 可以认为是 message id 的概念,一般是让服务端区分设备响应的是具体的哪一条消息,服务端没有用到的话可以为空字符 + */ + public String from ; + + /** + * 字段非必填,这个字段和 from 一样对设备来说没有任何作用, + * 只是在响应指令时原封不动的把 extra 的内容响应回去,服务端没有用到可以不传 + */ + public String extra ; + + /** + * 目标的设备编号 + */ + public String to ; + + /** + * 具体指令中的数据格式,每个指令都不一样 + */ + public JSONObject data; + +// public void setData(Object o) { +// this.data = JsonUtils.toJsonString(o); +// } +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/attendance/AttendanceConstants.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/attendance/AttendanceConstants.java new file mode 100644 index 00000000..f014a7ad --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/attendance/AttendanceConstants.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.system.attendance; + +/** + * 功能描述 + * + * @author: yj + * @date: 2024年05月27日 11:40 + */ +public class AttendanceConstants { + + public static final String CMD_BASE = "to_device" ; + + public static class OperateUserCMD { + + /** + * 下发人员信息到设备 + */ + public static final String ADD_USER_CMD = "addUser" ; + + /** + * 修改人员信息 + */ + public static final String EDIT_USER_CMD = "editUser" ; + + /** + * 批量删除人员 + */ + public static final String DEL_MULTI_USER_CMD = "delMultiUser" ; + + + /** + * 检测图片质量 + */ + public static final String CHECK_USER_PHOTO_CMD = "verifyPhoto" ; + + } +} From f7b7c3fa2d3a687b6ed2b04bd203d710175857c5 Mon Sep 17 00:00:00 2001 From: Echo <4759156@qq.com> Date: Wed, 29 May 2024 17:48:55 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E8=80=83=E5=8B=A4=E4=BB=AA=E8=AE=BE?= =?UTF-8?q?=E5=A4=87websocket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../attendance/SendUserToDeviceMessage.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/attendance/SendUserToDeviceMessage.java diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/attendance/SendUserToDeviceMessage.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/attendance/SendUserToDeviceMessage.java new file mode 100644 index 00000000..8a9ed2cf --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/attendance/SendUserToDeviceMessage.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.system.attendance; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 功能描述 + * + * @author: yj + * @date: 2024年05月27日 11:02 + */ + +@Schema(description="下发人员信息到设备") +@Data +public class SendUserToDeviceMessage { + + @Schema(description = "指令名称", requiredMode = Schema.RequiredMode.REQUIRED ,example = "addUser") + @NotNull(message = "指定名称不能为空") + public String cmd = AttendanceConstants.OperateUserCMD.ADD_USER_CMD; + + @Schema(description = "用户id,注意 user_id 请不要使用 DL 开头", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "user_id不能为空") + public String user_id ; + + @Schema(description = "用户姓名", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + @NotNull(message = "用户姓名不能为空") + public String name; + +// @Schema(description = "身份证号码,在刷身份证时会匹配这个号码是否存在", example = "362301111111111111") +// public String user_id_card ; + + @Schema(description = "彩色照片,可以为两种格式。\n" + + "1.http 链接,例如 https://up.enterdesk.com/edpic/70/0e/33/700e3312f74e378fbcc2fb3819421e73.jpg\n" + + "2.直接传图片 点击查看【2.服务规范】中的照片编码规则 。设备【验证模式】为【人脸或卡】时可以不传照片,非【人脸或卡】模式这个字段为必传", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://xxx.xx.jpg") + @NotNull(message = "照片不能为空") + public String face_template ; + + @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18888888888") + @NotNull(message = "手机号不能为空") + public String phone; + + @Schema(description = "人员有效期(人员在这个时间点后,无法通行)格式:yyyy-MM-dd 或者 yyyy-MM-dd HH:mm,为 “” 则为永久", requiredMode = Schema.RequiredMode.REQUIRED, example = "") + public final String id_valid= ""; +}