feat(websocket): 增加地图 WebSocket 会话管理

- 新增 getMapSession 方法用于获取地图 WebSocket 会话
- 在 addSession 和 removeSession 中增加对地图会话的处理逻辑
- 优化代码结构,提高可读性和可维护性
This commit is contained in:
aikai 2025-02-13 15:40:07 +08:00
parent ffa26a1fa9
commit 8b0713f653
17 changed files with 279 additions and 90 deletions

View File

@ -16,7 +16,8 @@ public enum NodeTypeEnum {
DEVICE(3, "设备点"), DEVICE(3, "设备点"),
PARKING(4, "停车点"), PARKING(4, "停车点"),
CHANGE(5, "区域变更点"), CHANGE(5, "区域变更点"),
WAIT(6, "等待点"); WAIT(6, "等待点"),
TEXT(7, "文字点");
/** /**
* 类型 * 类型

View File

@ -44,10 +44,10 @@ public abstract class AbstractWebSocketMessageSender implements WebSocketMessage
/** /**
* 发送消息 * 发送消息
* *
* @param sessionId Session 编号 * @param sessionId Session 编号
* @param userType 用户类型 * @param userType 用户类型
* @param userId 用户编号 * @param userId 用户编号
* @param messageType 消息类型 * @param messageType 消息类型
* @param messageContent 消息内容 * @param messageContent 消息内容
*/ */
public void send(String sessionId, Integer userType, Long userId, String messageType, String messageContent) { public void send(String sessionId, Integer userType, Long userId, String messageType, String messageContent) {
@ -57,6 +57,12 @@ public abstract class AbstractWebSocketMessageSender implements WebSocketMessage
WebSocketSession session = sessionManager.getSession(sessionId); WebSocketSession session = sessionManager.getSession(sessionId);
if (session != null) { if (session != null) {
sessions = Collections.singletonList(session); sessions = Collections.singletonList(session);
} else {
// -- 这里用于获取地图的webSocket
session = sessionManager.getMapSession(sessionId);
if (session != null){
sessions = Collections.singletonList(session);
}
} }
} else if (userType != null && userId != null) { } else if (userType != null && userId != null) {
sessions = (List<WebSocketSession>) sessionManager.getSessionList(userType, userId); sessions = (List<WebSocketSession>) sessionManager.getSessionList(userType, userId);
@ -74,8 +80,8 @@ public abstract class AbstractWebSocketMessageSender implements WebSocketMessage
/** /**
* 发送消息的具体实现 * 发送消息的具体实现
* *
* @param sessions Session 列表 * @param sessions Session 列表
* @param messageType 消息类型 * @param messageType 消息类型
* @param messageContent 消息内容 * @param messageContent 消息内容
*/ */
public void doSend(Collection<WebSocketSession> sessions, String messageType, String messageContent) { public void doSend(Collection<WebSocketSession> sessions, String messageType, String messageContent) {

View File

@ -33,6 +33,14 @@ public interface WebSocketSessionManager {
*/ */
WebSocketSession getSession(String id); WebSocketSession getSession(String id);
/**
* 根据 地图 +"_"+ 获取session
*
* @param key
* @return
*/
WebSocketSession getMapSession(String key);
/** /**
* 获得指定用户类型的 Session 列表 * 获得指定用户类型的 Session 列表
* *
@ -45,7 +53,7 @@ public interface WebSocketSessionManager {
* 获得指定用户编号的 Session 列表 * 获得指定用户编号的 Session 列表
* *
* @param userType 用户类型 * @param userType 用户类型
* @param userId 用户编号 * @param userId 用户编号
* @return Session 列表 * @return Session 列表
*/ */
Collection<WebSocketSession> getSessionList(Integer userType, Long userId); Collection<WebSocketSession> getSessionList(Integer userType, Long userId);

View File

@ -1,15 +1,14 @@
package cn.iocoder.yudao.framework.websocket.core.session; package cn.iocoder.yudao.framework.websocket.core.session;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpUtil;
import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils; import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import java.util.ArrayList; import java.nio.charset.StandardCharsets;
import java.util.Collection; import java.util.*;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
@ -23,63 +22,87 @@ public class WebSocketSessionManagerImpl implements WebSocketSessionManager {
/** /**
* id WebSocketSession 映射 * id WebSocketSession 映射
* * <p>
* keySession 编号 * keySession 编号
*/ */
private final ConcurrentMap<String, WebSocketSession> idSessions = new ConcurrentHashMap<>(); private final ConcurrentMap<String, WebSocketSession> idSessions = new ConcurrentHashMap<>();
/** /**
* user WebSocketSession 映射 * user WebSocketSession 映射
* * <p>
* key1用户类型 * key1用户类型
* key2用户编号 * key2用户编号
*/ */
private final ConcurrentMap<Integer, ConcurrentMap<Long, CopyOnWriteArrayList<WebSocketSession>>> userSessions private final ConcurrentMap<Integer, ConcurrentMap<Long, CopyOnWriteArrayList<WebSocketSession>>> userSessions
= new ConcurrentHashMap<>(); = new ConcurrentHashMap<>();
/**
* 地图 WebSocketSession 映射
* <p>
* key地图地址 +'_'+
*/
private final ConcurrentMap<String, WebSocketSession> mapSessions = new ConcurrentHashMap<>();
@Override @Override
public void addSession(WebSocketSession session) { public void addSession(WebSocketSession session) {
// 添加到 idSessions // 解析 session Url 中参数
idSessions.put(session.getId(), session); Map<String, String> paramMap = HttpUtil.decodeParamMap(String.valueOf(session.getUri()), StandardCharsets.UTF_8);
// 添加到 userSessions String type = paramMap.get("type");
LoginUser user = WebSocketFrameworkUtils.getLoginUser(session); // -- 如果是地图里面过来的
if (user == null) { if ("map".equals(type)) {
return; mapSessions.put(paramMap.get("floor") + "_" + paramMap.get("area"), session);
} } else {
ConcurrentMap<Long, CopyOnWriteArrayList<WebSocketSession>> userSessionsMap = userSessions.get(user.getUserType()); // 添加到 idSessions
if (userSessionsMap == null) { idSessions.put(session.getId(), session);
userSessionsMap = new ConcurrentHashMap<>(); // 添加到 userSessions
if (userSessions.putIfAbsent(user.getUserType(), userSessionsMap) != null) { LoginUser user = WebSocketFrameworkUtils.getLoginUser(session);
userSessionsMap = userSessions.get(user.getUserType()); if (user == null) {
return;
} }
} ConcurrentMap<Long, CopyOnWriteArrayList<WebSocketSession>> userSessionsMap = userSessions.get(user.getUserType());
CopyOnWriteArrayList<WebSocketSession> sessions = userSessionsMap.get(user.getId()); if (userSessionsMap == null) {
if (sessions == null) { userSessionsMap = new ConcurrentHashMap<>();
sessions = new CopyOnWriteArrayList<>(); if (userSessions.putIfAbsent(user.getUserType(), userSessionsMap) != null) {
if (userSessionsMap.putIfAbsent(user.getId(), sessions) != null) { userSessionsMap = userSessions.get(user.getUserType());
sessions = userSessionsMap.get(user.getId()); }
} }
CopyOnWriteArrayList<WebSocketSession> sessions = userSessionsMap.get(user.getId());
if (sessions == null) {
sessions = new CopyOnWriteArrayList<>();
if (userSessionsMap.putIfAbsent(user.getId(), sessions) != null) {
sessions = userSessionsMap.get(user.getId());
}
}
sessions.add(session);
} }
sessions.add(session);
} }
@Override @Override
public void removeSession(WebSocketSession session) { public void removeSession(WebSocketSession session) {
// 移除从 idSessions // 解析 session Url 中参数
idSessions.remove(session.getId()); Map<String, String> paramMap = HttpUtil.decodeParamMap(String.valueOf(session.getUri()), StandardCharsets.UTF_8);
// 移除从 idSessions String type = paramMap.get("type");
LoginUser user = WebSocketFrameworkUtils.getLoginUser(session); // -- 如果是地图里面过来的
if (user == null) { if ("map".equals(type)) {
return; mapSessions.remove(paramMap.get("floor") + "_" + paramMap.get("area"), session);
} } else {
ConcurrentMap<Long, CopyOnWriteArrayList<WebSocketSession>> userSessionsMap = userSessions.get(user.getUserType()); // 移除从 idSessions
if (userSessionsMap == null) { idSessions.remove(session.getId());
return; // 移除从 idSessions
} LoginUser user = WebSocketFrameworkUtils.getLoginUser(session);
CopyOnWriteArrayList<WebSocketSession> sessions = userSessionsMap.get(user.getId()); if (user == null) {
sessions.removeIf(session0 -> session0.getId().equals(session.getId())); return;
if (CollUtil.isEmpty(sessions)) { }
userSessionsMap.remove(user.getId(), sessions); ConcurrentMap<Long, CopyOnWriteArrayList<WebSocketSession>> userSessionsMap = userSessions.get(user.getUserType());
if (userSessionsMap == null) {
return;
}
CopyOnWriteArrayList<WebSocketSession> sessions = userSessionsMap.get(user.getId());
sessions.removeIf(session0 -> session0.getId().equals(session.getId()));
if (CollUtil.isEmpty(sessions)) {
userSessionsMap.remove(user.getId(), sessions);
}
} }
} }
@ -88,6 +111,11 @@ public class WebSocketSessionManagerImpl implements WebSocketSessionManager {
return idSessions.get(id); return idSessions.get(id);
} }
@Override
public WebSocketSession getMapSession(String key) {
return mapSessions.get(key);
}
@Override @Override
public Collection<WebSocketSession> getSessionList(Integer userType) { public Collection<WebSocketSession> getSessionList(Integer userType) {
ConcurrentMap<Long, CopyOnWriteArrayList<WebSocketSession>> userSessionsMap = userSessions.get(userType); ConcurrentMap<Long, CopyOnWriteArrayList<WebSocketSession>> userSessionsMap = userSessions.get(userType);

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.api.robot;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDTO; import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDTO;
import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataErrorDTO; import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataErrorDTO;
import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataPoseDTO; import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataPoseDTO;
@ -50,6 +51,7 @@ public class RobotStatusApiImpl implements RobotStatusApi {
/** /**
* 更新机器人点位/异常/能否做任务 * 更新机器人点位/异常/能否做任务
*
* @param robotStatusDataDTO * @param robotStatusDataDTO
* @return * @return
*/ */
@ -61,24 +63,31 @@ public class RobotStatusApiImpl implements RobotStatusApi {
return; return;
} }
String taskStatusKey = RobotTaskChcheConstant.ROBOT_TASK_STATUS +robotStatusDataDTO.getMac(); String taskStatusKey = RobotTaskChcheConstant.ROBOT_TASK_STATUS + robotStatusDataDTO.getMac();
String cargoDetectedKey = RobotTaskChcheConstant.ROBOT_CARGO_DETECTED +robotStatusDataDTO.getMac(); String cargoDetectedKey = RobotTaskChcheConstant.ROBOT_CARGO_DETECTED + robotStatusDataDTO.getMac();
String pose2dKey = RobotTaskChcheConstant.ROBOT_POSE_BAT +robotStatusDataDTO.getMac(); String pose2dKey = RobotTaskChcheConstant.ROBOT_POSE_BAT + robotStatusDataDTO.getMac();
redisUtil.set(taskStatusKey, robotStatusDataDTO.getData().getTask_status(),robotPositionCacheTime); redisUtil.set(taskStatusKey, robotStatusDataDTO.getData().getTask_status(), robotPositionCacheTime);
redisUtil.set(cargoDetectedKey,robotStatusDataDTO.getData().getCargo_detected(),robotPositionCacheTime); redisUtil.set(cargoDetectedKey, robotStatusDataDTO.getData().getCargo_detected(), robotPositionCacheTime);
Object object = redisUtil.get(pose2dKey); Object object = redisUtil.get(pose2dKey);
RobotStatusDataPoseDTO robotStatusDataPoseDTO= JSONUtil.toBean((String)object, RobotStatusDataPoseDTO.class); RobotStatusDataPoseDTO robotStatusDataPoseDTO = JSONUtil.toBean((String) object, RobotStatusDataPoseDTO.class);
robotStatusDataPoseDTO.setX(robotStatusDataDTO.getData().getPose2d().getX()); robotStatusDataPoseDTO.setX(robotStatusDataDTO.getData().getPose2d().getX());
robotStatusDataPoseDTO.setY(robotStatusDataDTO.getData().getPose2d().getY()); robotStatusDataPoseDTO.setY(robotStatusDataDTO.getData().getPose2d().getY());
robotStatusDataPoseDTO.setYaw(robotStatusDataDTO.getData().getPose2d().getYaw()); robotStatusDataPoseDTO.setYaw(robotStatusDataDTO.getData().getPose2d().getYaw());
redisUtil.set(pose2dKey,JSON.toJSONString(robotStatusDataPoseDTO),robotPositionCacheTime); redisUtil.set(pose2dKey, JSON.toJSONString(robotStatusDataPoseDTO), robotPositionCacheTime);
// -- webSocket 推送过来的机器人点位信息 -
// -- 上报的时候没有地图信息 - 那么怎么获取到这个地图的信息呢 -
// - 这里的接口需要接受
if (ObjectUtil.isNotNull(robotStatusDataDTO.getData().getErr_code())) { if (ObjectUtil.isNotNull(robotStatusDataDTO.getData().getErr_code())) {
List<RobotStatusDataErrorDTO> errCode = robotStatusDataDTO.getData().getErr_code(); List<RobotStatusDataErrorDTO> errCode = robotStatusDataDTO.getData().getErr_code();
String robotNo = robotInformationService.getRobotNoByMac(robotStatusDataDTO.getMac()); String robotNo = robotInformationService.getRobotNoByMac(robotStatusDataDTO.getMac());
if (ObjectUtil.isNull(robotNo)) { if (ObjectUtil.isNull(robotNo)) {
log.info("查不到机器人编号 :{}",robotStatusDataDTO.getMac()); log.info("查不到机器人编号 :{}", robotStatusDataDTO.getMac());
return; return;
} }
@ -86,7 +95,7 @@ public class RobotStatusApiImpl implements RobotStatusApi {
errCode.stream().map(RobotStatusDataErrorDTO::getError_code).collect(Collectors.toList()); errCode.stream().map(RobotStatusDataErrorDTO::getError_code).collect(Collectors.toList());
List<RobotWarnCodeMappingDO> robotWarnCodeMappingDOS = List<RobotWarnCodeMappingDO> robotWarnCodeMappingDOS =
warnCodeMappingMapper.selectList(new LambdaQueryWrapper<RobotWarnCodeMappingDO>() warnCodeMappingMapper.selectList(new LambdaQueryWrapper<RobotWarnCodeMappingDO>()
.in(RobotWarnCodeMappingDO::getWarnCode, warnCodes)); .in(RobotWarnCodeMappingDO::getWarnCode, warnCodes));
if (ObjectUtil.isEmpty(robotWarnCodeMappingDOS)) { if (ObjectUtil.isEmpty(robotWarnCodeMappingDOS)) {
log.info("查不对应编号的告警信息 :{}", JSON.toJSONString(warnCodes)); log.info("查不对应编号的告警信息 :{}", JSON.toJSONString(warnCodes));
return; return;
@ -100,7 +109,7 @@ public class RobotStatusApiImpl implements RobotStatusApi {
for (RobotStatusDataErrorDTO robotStatusData : errCode) { for (RobotStatusDataErrorDTO robotStatusData : errCode) {
List<RobotWarnCodeMappingDO> mappingDOS = warnCodeMapping.get(robotStatusData.getError_code()); List<RobotWarnCodeMappingDO> mappingDOS = warnCodeMapping.get(robotStatusData.getError_code());
if (ObjectUtil.isEmpty(mappingDOS)) { if (ObjectUtil.isEmpty(mappingDOS)) {
log.info("当前告警类型查不到对应的告警信息 :{}",robotStatusData.getError_code()); log.info("当前告警类型查不到对应的告警信息 :{}", robotStatusData.getError_code());
continue; continue;
} }
RobotWarnMsgDO warnMsg = RobotWarnMsgDO.builder().warnLevel(Integer.valueOf(robotStatusData.getCode_level())) RobotWarnMsgDO warnMsg = RobotWarnMsgDO.builder().warnLevel(Integer.valueOf(robotStatusData.getCode_level()))
@ -117,5 +126,4 @@ public class RobotStatusApiImpl implements RobotStatusApi {
} }
} }

View File

@ -83,7 +83,7 @@ public class DeviceInformationController {
@PostMapping("/mapBindDeviceInfo") @PostMapping("/mapBindDeviceInfo")
@Operation(summary = "地图绑定设备") @Operation(summary = "地图绑定设备")
public CommonResult<Boolean> mapBindDeviceInfo(@Valid MapBindDeviceInfoDTO dto) { public CommonResult<Boolean> mapBindDeviceInfo(@Valid @RequestBody MapBindDeviceInfoDTO dto) {
informationService.mapBindDeviceInfo(dto); informationService.mapBindDeviceInfo(dto);
return success(true); return success(true);
} }

View File

@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMa
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapItemDO; import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapItemDO;
import cn.iocoder.yudao.module.system.handler.mapnode.NodeProcessingContext; import cn.iocoder.yudao.module.system.handler.mapnode.NodeProcessingContext;
import cn.iocoder.yudao.module.system.service.positionmap.PositionMapItemService; import cn.iocoder.yudao.module.system.service.positionmap.PositionMapItemService;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@ -43,6 +44,12 @@ public class PositionMapItemController {
@Resource @Resource
private NodeProcessingContext nodeProcessingContext; private NodeProcessingContext nodeProcessingContext;
@GetMapping("/getMapItemId")
@Operation(summary = "获取节点id")
public CommonResult<String> getMapItemId() {
return success(String.valueOf(IdWorker.getId()));
}
// -- 前端给所有的节点信息 - // -- 前端给所有的节点信息 -
@PostMapping("/batchSaveOrEditOrDel") @PostMapping("/batchSaveOrEditOrDel")
@Operation(summary = "批量新增编辑删除节点") @Operation(summary = "批量新增编辑删除节点")

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.system.controller.admin.positionmap;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapLineRespVO; import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapLineRespVO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapLineSaveReqVO; import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapLineSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapLineDO; import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapLineDO;

View File

@ -1,11 +1,12 @@
package cn.iocoder.yudao.module.system.controller.admin.positionmap.vo; package cn.iocoder.yudao.module.system.controller.admin.positionmap.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.system.controller.admin.positionmap.vo; package cn.iocoder.yudao.module.system.controller.admin.positionmap.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -27,6 +28,30 @@ public class PositionMapLinePageReqVO extends PageParam {
@Schema(description = "结束点id(点位子表id)", example = "15890") @Schema(description = "结束点id(点位子表id)", example = "15890")
private Long endPointId; private Long endPointId;
@Schema(description = "开始控制点x轴", example = "15890")
private String beginControlX;
@Schema(description = "开始控制点y轴", example = "15890")
private String beginControlY;
@Schema(description = "结束控制点x轴", example = "15890")
private String endControlX;
@Schema(description = "结束控制点y轴", example = "15890")
private String endControlY;
@Schema(description = "膨胀区域前", example = "15890")
private BigDecimal expansionZoneFront;
@Schema(description = "膨胀区域后", example = "15890")
private BigDecimal expansionZoneAfter;
@Schema(description = "膨胀区域左", example = "15890")
private BigDecimal expansionZoneLeft;
@Schema(description = "膨胀区域右", example = "15890")
private BigDecimal expansionZoneRight;
@Schema(description = "行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线") @Schema(description = "行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线")
private Integer method; private Integer method;

View File

@ -29,6 +29,38 @@ public class PositionMapLineRespVO {
@ExcelProperty("结束点id(点位子表id)") @ExcelProperty("结束点id(点位子表id)")
private Long endPointId; private Long endPointId;
@Schema(description = "开始控制点x轴", example = "15890")
@ExcelProperty("开始控制点x轴")
private String beginControlX;
@Schema(description = "开始控制点y轴", example = "15890")
@ExcelProperty("开始控制点y轴")
private String beginControlY;
@Schema(description = "结束控制点x轴", example = "15890")
@ExcelProperty("结束控制点x轴")
private String endControlX;
@Schema(description = "结束控制点y轴", example = "15890")
@ExcelProperty("结束控制点y轴")
private String endControlY;
@Schema(description = "膨胀区域前", example = "15890")
@ExcelProperty("膨胀区域前")
private BigDecimal expansionZoneFront;
@Schema(description = "膨胀区域后", example = "15890")
@ExcelProperty("膨胀区域后")
private BigDecimal expansionZoneAfter;
@Schema(description = "膨胀区域左", example = "15890")
@ExcelProperty("膨胀区域左")
private BigDecimal expansionZoneLeft;
@Schema(description = "膨胀区域右", example = "15890")
@ExcelProperty("膨胀区域右")
private BigDecimal expansionZoneRight;
@Schema(description = "行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线") @Schema(description = "行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线")
@ExcelProperty("行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线") @ExcelProperty("行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线")
private Integer method; private Integer method;

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.system.controller.admin.positionmap.vo; package cn.iocoder.yudao.module.system.controller.admin.positionmap.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
@ -24,6 +25,30 @@ public class PositionMapLineSaveReqVO {
@Schema(description = "结束点id(点位子表id)", example = "15890") @Schema(description = "结束点id(点位子表id)", example = "15890")
private Long endPointId; private Long endPointId;
@Schema(description = "开始控制点x轴", example = "15890")
private String beginControlX;
@Schema(description = "开始控制点y轴", example = "15890")
private String beginControlY;
@Schema(description = "结束控制点x轴", example = "15890")
private String endControlX;
@Schema(description = "结束控制点y轴", example = "15890")
private String endControlY;
@Schema(description = "膨胀区域前", example = "15890")
private BigDecimal expansionZoneFront;
@Schema(description = "膨胀区域后", example = "15890")
private BigDecimal expansionZoneAfter;
@Schema(description = "膨胀区域左", example = "15890")
private BigDecimal expansionZoneLeft;
@Schema(description = "膨胀区域右", example = "15890")
private BigDecimal expansionZoneRight;
@Schema(description = "行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线") @Schema(description = "行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线")
private Integer method; private Integer method;

View File

@ -1,32 +1,32 @@
package cn.iocoder.yudao.module.system.controller.admin.robot; package cn.iocoder.yudao.module.system.controller.admin.robot;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.*; import cn.iocoder.yudao.module.system.controller.admin.robot.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO; import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO;
import cn.iocoder.yudao.module.system.service.robot.RobotInformationService; import cn.iocoder.yudao.module.system.service.robot.RobotInformationService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.*; import javax.annotation.Resource;
import javax.servlet.http.*; import javax.annotation.security.PermitAll;
import java.util.*; import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
@Tag(name = "管理后台 - 车辆信息") @Tag(name = "管理后台 - 车辆信息")
@RestController @RestController
@ -36,6 +36,8 @@ public class RobotInformationController {
@Resource @Resource
private RobotInformationService informationService; private RobotInformationService informationService;
@Resource
private WebSocketSenderApi webSocketSenderApi;
@PostMapping("/create") @PostMapping("/create")
@Operation(summary = "创建车辆信息") @Operation(summary = "创建车辆信息")
@ -44,6 +46,14 @@ public class RobotInformationController {
return success(informationService.createInformation(createReqVO)); return success(informationService.createInformation(createReqVO));
} }
@PostMapping("/test")
@PermitAll
@Operation(summary = "测试")
public CommonResult<Boolean> test(@RequestParam String id, @RequestParam String msg) {
webSocketSenderApi.sendObject(id,"map_push", msg);
return success(true);
}
@PutMapping("/update") @PutMapping("/update")
@Operation(summary = "更新车辆信息") @Operation(summary = "更新车辆信息")
@PreAuthorize("@ss.hasPermission('robot:information:update')") @PreAuthorize("@ss.hasPermission('robot:information:update')")
@ -83,12 +93,12 @@ public class RobotInformationController {
@PreAuthorize("@ss.hasPermission('robot:information:export')") @PreAuthorize("@ss.hasPermission('robot:information:export')")
@ApiAccessLog(operateType = EXPORT) @ApiAccessLog(operateType = EXPORT)
public void exportInformationExcel(@Valid RobotInformationPageReqVO pageReqVO, public void exportInformationExcel(@Valid RobotInformationPageReqVO pageReqVO,
HttpServletResponse response) throws IOException { HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<RobotInformationPageRespVO> list = informationService.getInformationPage(pageReqVO).getList(); List<RobotInformationPageRespVO> list = informationService.getInformationPage(pageReqVO).getList();
// 导出 Excel // 导出 Excel
ExcelUtils.write(response, "车辆信息.xls", "数据", RobotInformationPageRespVO.class, ExcelUtils.write(response, "车辆信息.xls", "数据", RobotInformationPageRespVO.class,
BeanUtils.toBean(list, RobotInformationPageRespVO.class)); BeanUtils.toBean(list, RobotInformationPageRespVO.class));
} }
@PostMapping("/statistics") @PostMapping("/statistics")

View File

@ -6,7 +6,10 @@ import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsChannelEnum;
import cn.iocoder.yudao.module.system.service.sms.SmsSendService; import cn.iocoder.yudao.module.system.service.sms.SmsSendService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.annotation.security.PermitAll; import javax.annotation.security.PermitAll;
@ -30,7 +33,6 @@ public class SmsCallbackController {
smsSendService.receiveSmsStatus(SmsChannelEnum.ALIYUN.getCode(), text); smsSendService.receiveSmsStatus(SmsChannelEnum.ALIYUN.getCode(), text);
return success(true); return success(true);
} }
@PostMapping("/tencent") @PostMapping("/tencent")
@PermitAll @PermitAll
@Operation(summary = "腾讯云短信的回调", description = "参见 https://cloud.tencent.com/document/product/382/52077 文档") @Operation(summary = "腾讯云短信的回调", description = "参见 https://cloud.tencent.com/document/product/382/52077 文档")

View File

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -41,6 +42,38 @@ public class PositionMapLineDO extends BaseDO {
* 结束点id(点位子表id) * 结束点id(点位子表id)
*/ */
private Long endPointId; private Long endPointId;
/**
* 开始控制点x轴
*/
private String beginControlX;
/**
* 开始控制点y轴
*/
private String beginControlY;
/**
* 结束控制点x轴
*/
private String endControlX;
/**
* 结束控制点y轴
*/
private String endControlY;
/**
* 膨胀区域前
*/
private BigDecimal expansionZoneFront;
/**
* 膨胀区域后
*/
private BigDecimal expansionZoneAfter;
/**
* 膨胀区域左
*/
private BigDecimal expansionZoneLeft;
/**
* 膨胀区域右
*/
private BigDecimal expansionZoneRight;
/** /**
* 行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线 * 行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线
*/ */

View File

@ -50,6 +50,8 @@ public class NodeProcessingContext {
strategyMap.put(NodeTypeEnum.CHANGE.getType(), mapNodeStrategyImpl); strategyMap.put(NodeTypeEnum.CHANGE.getType(), mapNodeStrategyImpl);
// 等待点 // 等待点
strategyMap.put(NodeTypeEnum.WAIT.getType(), mapNodeStrategyImpl); strategyMap.put(NodeTypeEnum.WAIT.getType(), mapNodeStrategyImpl);
// 文字点
strategyMap.put(NodeTypeEnum.TEXT.getType(), mapNodeStrategyImpl);
// todo 可以继续添加更多的策略 - 新增实现即可 // todo 可以继续添加更多的策略 - 新增实现即可
} }

View File

@ -72,9 +72,11 @@ public class PositionMapItemServiceImpl extends ServiceImpl<PositionMapItemMappe
public void batchSaveOrEditOrDel(Long positionMapId, List<List<PositionMapItemDO>> list) { public void batchSaveOrEditOrDel(Long positionMapId, List<List<PositionMapItemDO>> list) {
//批量添加修改删除 //批量添加修改删除
if (isNotEmpty(list.get(0))) { if (isNotEmpty(list.get(0))) {
list.get(0).forEach(a -> a.setPositionMapId(positionMapId));
positionMapItemMapper.insertBatch(list.get(0)); positionMapItemMapper.insertBatch(list.get(0));
} }
if (isNotEmpty(list.get(1))) { if (isNotEmpty(list.get(1))) {
list.get(1).forEach(a -> a.setPositionMapId(positionMapId));
positionMapItemMapper.updateBatch(list.get(1)); positionMapItemMapper.updateBatch(list.get(1));
} }
if (isNotEmpty(list.get(2))) { if (isNotEmpty(list.get(2))) {