opt:添加国际化等

This commit is contained in:
2025-08-28 16:00:27 +08:00
parent 1061b07f1e
commit 30dad1a294
56 changed files with 1481 additions and 117 deletions

22
pom.xml
View File

@@ -104,6 +104,13 @@
<version>1.1.22</version>
</dependency>
<!-- EasyExcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
@@ -196,6 +203,21 @@
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>${basedir}/src/main/java</directory>
<includes>
<include>**/*.*</include>
</includes>
</resource>
<resource>
<directory>${basedir}/src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
</resource>
</resources>
</build>
</project>

View File

@@ -1,8 +1,10 @@
package org.nl.apt15e;
import org.mybatis.spring.annotation.MapperScan;
import org.nl.apt15e.config.SpringContextHolder;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@@ -22,6 +24,11 @@ public class Apt15EApplication {
SpringApplication.run(Apt15EApplication.class, args);
}
@Bean
public SpringContextHolder springContextHolder() {
return new SpringContextHolder();
}
/**
* 访问首页提示
*

View File

@@ -0,0 +1,83 @@
package org.nl.apt15e.apt.anomalyInfo.controller;
import com.alibaba.excel.EasyExcel;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorHandling;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorInfo;
import org.nl.apt15e.apt.anomalyInfo.service.AnomalyInfoService;
import org.nl.apt15e.apt.anomalyInfo.service.ErrorHandlingService;
import org.nl.apt15e.apt.anomalyInfo.service.ErrorInfoService;
import org.nl.apt15e.common.BadRequestException;
import org.nl.apt15e.common.excel.ErrorHandlingListener;
import org.nl.apt15e.common.excel.ErrorInfoListener;
import org.nl.apt15e.config.language.LangProcess;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
/**
* @author dsh
* 2025/8/26
*/
@RestController
@RequestMapping("/anomalyInfo")
public class AnomalyInfoController {
@Resource
private AnomalyInfoService anomalyInfoService;
@Resource
private ErrorInfoService errorInfoService;
@Resource
private ErrorHandlingService errorHandlingService;
@PostMapping("/queryErrorDataByCode")
public ResponseEntity<Object> queryErrorDataByCode(@RequestParam("code") String code) {
return new ResponseEntity<>(anomalyInfoService.queryErrorDataByCode(code), HttpStatus.OK);
}
@PostMapping("/importErrorInfoExcel")
public ResponseEntity<Object> importErrorInfoExcel(@RequestParam("file") MultipartFile file) throws IOException {
if (file.isEmpty()) {
throw new BadRequestException("请选择文件上传");
}
// 创建监听器实例传入所需的Service
ErrorInfoListener listener = new ErrorInfoListener(errorInfoService);
// 读取Excel文件
// withFile(file.getInputStream())... 也可以
EasyExcel.read(file.getInputStream(), ErrorInfo.class, listener)
.sheet() // 默认读取第一个sheet
.doRead();
return new ResponseEntity<>(LangProcess.msg("successful"),HttpStatus.OK);
}
@PostMapping("/importErrorHandlingExcel")
public ResponseEntity<Object> importErrorHandlingExcel(@RequestParam("file") MultipartFile file) throws IOException {
if (file.isEmpty()) {
throw new BadRequestException("请选择文件上传");
}
// 创建监听器实例传入所需的Service
ErrorHandlingListener listener = new ErrorHandlingListener(errorHandlingService);
// 读取Excel文件
// withFile(file.getInputStream())... 也可以
EasyExcel.read(file.getInputStream(), ErrorHandling.class, listener)
.sheet() // 默认读取第一个sheet
.doRead();
return new ResponseEntity<>(LangProcess.msg("successful"),HttpStatus.OK);
}
}

View File

@@ -0,0 +1,64 @@
package org.nl.apt15e.apt.anomalyInfo.dao;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* @author dsh
* 2025/8/20
*/
@Data
@TableName("error_handling")
public class ErrorHandling {
/**
* 异常处理标识
*/
@TableId
@ExcelProperty(index = 0,value = "标识")
private String error_handling_id;
/**
* 异常信息编码
*/
@ExcelProperty(index = 1,value = "异常编码")
private String error_code;
/**
* 异常处理类型(1 图文说明 2视频说明)
*/
@ExcelProperty(index = 2,value = "异常处理类型(1图文说明2视频说明)")
private Integer error_handling_type;
/**
* 异常处理说明
*/
@ExcelProperty(index = 3,value = "异常处理说明")
private String error_handling_title;
/**
* 中文异常处理说明
*/
@ExcelProperty(index = 4,value = "异常处理说明(中文)")
private String zh_error_handling_title;
/**
* 英文异常处理说明
*/
@ExcelProperty(index = 5,value = "异常处理说明(英文)")
private String en_error_handling_title;
/**
* 异常处理排序
*/
@ExcelProperty(index = 6,value = "异常处理排序")
private Integer error_handling_seq;
/**
* 异常处理地址(图片 或 视频地址)
*/
@ExcelProperty(index = 7,value = "异常处理地址(图片或视频地址)")
private String error_handling_addre;
}

View File

@@ -0,0 +1,77 @@
package org.nl.apt15e.apt.anomalyInfo.dao;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* @author dsh
* 2025/8/20
*/
@Data
@TableName("error_info")
public class ErrorInfo {
/**
* 异常信息标识
*/
@TableId
@ExcelProperty(index = 0,value = "唯一标识")
private String error_id;
/**
* 异常信息名称
*/
@ExcelProperty(index = 1,value = "异常名称")
private String error_name;
/**
* 中文异常信息名称
*/
@ExcelProperty(index = 2,value = "异常名称(中文)")
private String zh_error_name;
/**
* 英文异常信息名称
*/
@ExcelProperty(index = 3,value = "异常名称(英文)")
private String en_error_name;
/**
* 异常信息编码
*/
@ExcelProperty(index = 4,value = "异常编号")
private String error_code;
/**
* 异常信息类别(1普通故障 2严重故障)
*/
@ExcelProperty(index = 5,value = "异常类别(1普通故障,2严重故障)")
private Integer error_category;
/**
* 异常说明
*/
@ExcelProperty(index = 6,value = "异常说明")
private String error_description;
/**
* 中文异常说明
*/
@ExcelProperty(index = 7,value = "异常说明(中文)")
private String zh_error_description;
/**
* 英文异常说明
*/
@ExcelProperty(index = 8,value = "异常说明(英文)")
private String en_error_description;
/**
* 异常信息类型(1电气 2导航)
*/
@ExcelProperty(index = 9,value = "异常类型(1电气,2导航)")
private Integer error_type;
}

View File

@@ -0,0 +1,26 @@
package org.nl.apt15e.apt.anomalyInfo.dto;
import lombok.Data;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorHandling;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorInfo;
import java.util.List;
/**
* @author dsh
* 2025/8/26
*/
@Data
public class ErrorDataDto extends ErrorInfo {
/**
* 图文异常处理
*/
private List<ErrorHandling> graphicDescription;
/**
* 视频异常处理
*/
private List<ErrorHandling> videoDescription;
}

View File

@@ -0,0 +1,17 @@
package org.nl.apt15e.apt.anomalyInfo.service;
import org.nl.apt15e.apt.anomalyInfo.dto.ErrorDataDto;
/**
* @author dsh
* 2025/8/26
*/
public interface AnomalyInfoService {
/**
* 根据异常编码查询处理方法
* @param code
* @return
*/
ErrorDataDto queryErrorDataByCode(String code);
}

View File

@@ -0,0 +1,12 @@
package org.nl.apt15e.apt.anomalyInfo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorHandling;
/**
* @author dsh
* 2025/8/27
*/
public interface ErrorHandlingService extends IService<ErrorHandling> {
}

View File

@@ -0,0 +1,11 @@
package org.nl.apt15e.apt.anomalyInfo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorInfo;
/**
* @author dsh
* 2025/8/26
*/
public interface ErrorInfoService extends IService<ErrorInfo> {
}

View File

@@ -0,0 +1,47 @@
package org.nl.apt15e.apt.anomalyInfo.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorHandling;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorInfo;
import org.nl.apt15e.apt.anomalyInfo.dto.ErrorDataDto;
import org.nl.apt15e.apt.anomalyInfo.service.AnomalyInfoService;
import org.nl.apt15e.apt.anomalyInfo.service.mapper.ErrorHandlingMapper;
import org.nl.apt15e.apt.anomalyInfo.service.mapper.ErrorInfoMapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author dsh
* 2025/8/26
*/
@Service
public class AnomalyInfoServiceImpl implements AnomalyInfoService {
@Resource
private ErrorHandlingMapper errorHandlingMapper;
@Resource
private ErrorInfoMapper errorInfoMapper;
@Override
public ErrorDataDto queryErrorDataByCode(String code) {
ErrorDataDto errorDataDto = new ErrorDataDto();
// 异常信息
ErrorInfo errorInfo = errorInfoMapper.selectOne(new LambdaQueryWrapper<>(ErrorInfo.class).eq(ErrorInfo::getError_code,code));
BeanUtil.copyProperties(errorInfo,errorDataDto);
// 异常处理
List<ErrorHandling> errorHandlingList = errorHandlingMapper.selectList(new LambdaQueryWrapper<>(ErrorHandling.class).eq(ErrorHandling::getError_code,code));
// 图文说明
List<ErrorHandling> graphicDescription = errorHandlingList.stream().filter(errorHandling -> errorHandling.getError_handling_type() == 1).collect(Collectors.toList());
// 视频说明
List<ErrorHandling> videoDescription = errorHandlingList.stream().filter(errorHandling -> errorHandling.getError_handling_type() == 2).collect(Collectors.toList());
errorDataDto.setGraphicDescription(graphicDescription);
errorDataDto.setVideoDescription(videoDescription);
return errorDataDto;
}
}

View File

@@ -0,0 +1,15 @@
package org.nl.apt15e.apt.anomalyInfo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorHandling;
import org.nl.apt15e.apt.anomalyInfo.service.ErrorHandlingService;
import org.nl.apt15e.apt.anomalyInfo.service.mapper.ErrorHandlingMapper;
import org.springframework.stereotype.Service;
/**
* @author dsh
* 2025/8/27
*/
@Service
public class ErrorHandlingServiceImpl extends ServiceImpl<ErrorHandlingMapper, ErrorHandling> implements ErrorHandlingService {
}

View File

@@ -0,0 +1,17 @@
package org.nl.apt15e.apt.anomalyInfo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.ibatis.annotations.Mapper;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorInfo;
import org.nl.apt15e.apt.anomalyInfo.service.ErrorInfoService;
import org.nl.apt15e.apt.anomalyInfo.service.mapper.ErrorInfoMapper;
import org.springframework.stereotype.Service;
/**
* @author dsh
* 2025/8/26
*/
@Service
public class ErrorInfoServiceImpl extends ServiceImpl<ErrorInfoMapper, ErrorInfo> implements ErrorInfoService {
}

View File

@@ -0,0 +1,15 @@
package org.nl.apt15e.apt.anomalyInfo.service.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorHandling;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorInfo;
/**
* @author dsh
* 2025/8/26
*/
@Mapper
public interface ErrorHandlingMapper extends BaseMapper<ErrorHandling> {
}

View File

@@ -0,0 +1,16 @@
package org.nl.apt15e.apt.anomalyInfo.service.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorInfo;
import org.nl.apt15e.apt.anomalyInfo.dto.ErrorDataDto;
/**
* @author dsh
* 2025/8/26
*/
@Mapper
public interface ErrorInfoMapper extends BaseMapper<ErrorInfo> {
}

View File

@@ -2,6 +2,7 @@ package org.nl.apt15e.apt.dto;
import lombok.Builder;
import lombok.Data;
import org.nl.apt15e.config.language.LangProcess;
/**
* <p>
@@ -31,7 +32,7 @@ public class WebResponse<T> {
*/
public static WebResponse requestOk() {
return WebResponse.builder()
.message("操作成功!")
.message(LangProcess.msg("successful"))
.build();
}
@@ -41,7 +42,7 @@ public class WebResponse<T> {
*/
public static <T> WebResponse requestParamOk(T data) {
return WebResponse.builder()
.message("操作成功!")
.message(LangProcess.msg("successful"))
.data(data)
.build();
}

View File

@@ -16,6 +16,7 @@ import org.nl.apt15e.apt.station.service.StationService;
import org.nl.apt15e.apt.task.enums.TaskStatus;
import org.nl.apt15e.apt.task.service.ITaskService;
import org.nl.apt15e.apt.task.service.dao.Task;
import org.nl.apt15e.config.language.LangProcess;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -56,7 +57,7 @@ public class RcsToAptServiceImpl implements RcsToAptService {
);
if (ObjectUtil.isEmpty(task)) {
result.put("receive", "1");
result.put("message", "任务不存在!【"+rcsToAptTaskChainPoDto.getId()+"");
result.put("message", LangProcess.msg("task_Id_isNull",rcsToAptTaskChainPoDto.getId().toString()));
log.info("RCS上报任务信息输出参数{}", result.toString());
return result;
}

View File

@@ -4,10 +4,7 @@ import org.nl.apt15e.apt.map.dao.MapInfo;
import org.nl.apt15e.apt.map.service.MapInfoService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@@ -26,4 +23,9 @@ public class MapInfoController {
public ResponseEntity<Object> getMapInfoByCode() {
return new ResponseEntity<>(mapInfoService.getMapInfoByCode(), HttpStatus.OK);
}
@PostMapping("/synchronizedMap")
public ResponseEntity<Object> synchronizedMap() {
return new ResponseEntity<>(mapInfoService.synchronizedMap(), HttpStatus.OK);
}
}

View File

@@ -17,4 +17,10 @@ public interface MapInfoService extends IService<MapInfo> {
*/
MapInfo getMapInfoByCode();
/**
* 获取当前车辆地图同步到本地
* @return
*/
boolean synchronizedMap();
}

View File

@@ -2,6 +2,8 @@ package org.nl.apt15e.apt.map.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -9,10 +11,15 @@ import lombok.extern.slf4j.Slf4j;
import org.nl.apt15e.apt.map.dao.MapInfo;
import org.nl.apt15e.apt.map.service.MapInfoService;
import org.nl.apt15e.apt.map.service.mapper.MapInfoMapper;
import org.nl.apt15e.apt.teaching.service.TeachingService;
import org.nl.apt15e.common.BadRequestException;
import org.nl.apt15e.config.language.LangProcess;
import org.nl.apt15e.util.HTTPUtil;
import org.nl.apt15e.util.URLConstant;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
@@ -23,8 +30,45 @@ import java.util.List;
@Service
public class MapInfoServiceImpl extends ServiceImpl<MapInfoMapper, MapInfo> implements MapInfoService {
@Resource
private MapInfoMapper mapInfoMapper;
@Resource
private TeachingService teachingService;
@Override
public MapInfo getMapInfoByCode() {
return this.getOne(new LambdaQueryWrapper<>(MapInfo.class));
}
@Override
public boolean synchronizedMap() {
HttpResponse response = null;
try {
response = HTTPUtil.post(URLConstant.VEHICLE_IP_PORT,"/tool/rob/getVehicle", new JSONObject());
if (response!=null && response.isOk()) {
// 获取响应体内容
JSONObject body = JSON.parseObject(response.body());
// 如:"../map/apt_map_20250814141523"
String mapId = body.getJSONObject("data").getString("mapId");
if (StrUtil.isEmpty(mapId)) {
throw new BadRequestException(LangProcess.msg("param_is_null"));
}
String mapName = mapId.substring(mapId.lastIndexOf('/') + 1);
MapInfo mapInfo = mapInfoMapper.selectOne(new LambdaQueryWrapper<>(MapInfo.class));
// 如果数据库地图数据为空 或者 地图数据和车辆后台数据不一致 执行同步数据操作
if (ObjectUtil.isEmpty(mapInfo) || !mapName.equals(mapInfo.getMapName())) {
teachingService.getRunMapZip(mapName);
return true;
}else {
throw new BadRequestException(LangProcess.msg("latest"));
}
}else {
throw new BadRequestException(LangProcess.msg("error_request_vehicle"));
}
} catch (Exception e) {
log.info("同步地图失败:{}",e.getMessage());
throw new BadRequestException(LangProcess.msg("failed"));
}
}
}

View File

@@ -17,6 +17,7 @@ import org.nl.apt15e.apt.taskOperate.service.TaskManageService;
import org.nl.apt15e.apt.taskchain.service.ITaskchainService;
import org.nl.apt15e.apt.taskchain.service.dao.Taskchain;
import org.nl.apt15e.common.BadRequestException;
import org.nl.apt15e.config.language.LangProcess;
import org.nl.apt15e.util.HTTPUtil;
import org.nl.apt15e.util.IdUtil;
import org.nl.apt15e.util.URLConstant;
@@ -68,7 +69,7 @@ public class TaskManageServiceImpl implements TaskManageService {
.lt(Task::getTask_status, TaskStatus.FINISHED.getCode())
);
if (ObjectUtil.isNotEmpty(list)) {
throw new BadRequestException("当前有正在执行中的任务!");
throw new BadRequestException(LangProcess.msg("task_Is_exist"));
}
List<Station> staList = whereJson.getJSONArray("data").toJavaList(Station.class);
@@ -84,7 +85,7 @@ public class TaskManageServiceImpl implements TaskManageService {
.eq(Station::getStation_type, "Breaks")
);
if (ObjectUtil.isEmpty(breakPoint)) {
throw new BadRequestException("请先设置返回点!");
throw new BadRequestException(LangProcess.msg("not_return_point"));
}
staList.add(breakPoint);
}
@@ -100,11 +101,11 @@ public class TaskManageServiceImpl implements TaskManageService {
JSONObject result = JSONObject.parseObject(response.body());
log.info("下发RCS任务输出参数{}", result.toString());
if (result.getBoolean("state").equals(false)) {
throw new BadRequestException("访问调度报错:" + result.getString("errMsg"));
throw new BadRequestException(LangProcess.msg("error_request_rcs") + result.getString("errMsg"));
}
task_id = result.getString("data");
} catch (Exception e) {
throw new BadRequestException("访问调度报错:" + e.getMessage());
throw new BadRequestException(LangProcess.msg("error_request_rcs") + e.getMessage());
}
// 创建任务
@@ -114,7 +115,7 @@ public class TaskManageServiceImpl implements TaskManageService {
task.setTask_seq(
staList.stream()
.map(Station::getStation_name)
.collect(Collectors.joining("-"))
.collect(Collectors.joining(","))
);
task.setTask_status(TaskStatus.CREATE.getCode());
task.setCreate_time(DateUtil.now());
@@ -153,26 +154,26 @@ public class TaskManageServiceImpl implements TaskManageService {
.lt(Task::getTask_status, TaskStatus.FINISHED.getCode())
);
if (ObjectUtil.isEmpty(task)) {
throw new BadRequestException("当前没有任务在执行中!");
throw new BadRequestException(LangProcess.msg("task_Is_not_exist"));
}
try {
HttpResponse response = HTTPUtil.post(URLConstant.RCS_IP_PORT, URLConstant.CANCEL_TASK_URL + task.getTask_id(), null);
JSONObject result = JSONObject.parseObject(response.body());
if (result.getBoolean("state").equals(false)) {
throw new BadRequestException("访问调度报错:" + result.getString("errMsg"));
throw new BadRequestException(LangProcess.msg("error_request_rcs") + result.getString("errMsg"));
}
// 取消任务
task.setTask_status(TaskStatus.CANCELED.getCode());
iTaskService.updateById(task);
} catch (Exception e) {
throw new BadRequestException("访问调度报错:" + e.getMessage());
throw new BadRequestException(LangProcess.msg("error_request_rcs") + e.getMessage());
}
return WebResponse.requestOk();
}
@Override
public WebResponse queryTaskChain() {
List<Taskchain> taskList = iTaskchainService.list();
List<Taskchain> taskList = iTaskchainService.queryAllTaskchain();
// 根据任务链id分组
Map<String, List<Taskchain>> mapTask = taskList.stream()
.collect(Collectors.groupingBy(Taskchain::getChain_id));
@@ -220,10 +221,6 @@ public class TaskManageServiceImpl implements TaskManageService {
@Override
public WebResponse TaskChainDtl(JSONObject whereJson) {
return WebResponse.requestParamOk(iTaskchainService.list(
new QueryWrapper<Taskchain>().lambda()
.eq(Taskchain::getChain_id, whereJson.getString("chain_id"))
.orderByAsc(Taskchain::getOrder_num)
));
return WebResponse.requestParamOk(iTaskchainService.queryTaskchainById(whereJson.getString("chain_id")));
}
}

View File

@@ -3,6 +3,8 @@ package org.nl.apt15e.apt.taskchain.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.nl.apt15e.apt.taskchain.service.dao.Taskchain;
import java.util.List;
/**
* <p>
* 服务类
@@ -13,4 +15,7 @@ import org.nl.apt15e.apt.taskchain.service.dao.Taskchain;
*/
public interface ITaskchainService extends IService<Taskchain> {
List<Taskchain> queryAllTaskchain();
List<Taskchain> queryTaskchainById(String chain_id);
}

View File

@@ -1,8 +1,12 @@
package org.nl.apt15e.apt.taskchain.service.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.nl.apt15e.apt.taskchain.service.dao.Taskchain;
import java.util.List;
/**
* <p>
* Mapper 接口
@@ -11,6 +15,14 @@ import org.nl.apt15e.apt.taskchain.service.dao.Taskchain;
* @author Liuxy
* @since 2025-07-09
*/
@Mapper
public interface TaskchainMapper extends BaseMapper<Taskchain> {
/**
* 查询所有任务链
* @return
*/
List<Taskchain> queryAllTaskchain();
List<Taskchain> queryTaskchainById(@Param("chain_id") String chain_id);
}

View File

@@ -1,5 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.nl.apt15e.apt.taskchain.service.dao.mapper.TaskchainMapper">
<select id="queryAllTaskchain" resultType="org.nl.apt15e.apt.taskchain.service.dao.Taskchain">
select tc.id,tc.chain_id,tc.chain_name,tc.order_num,tc.station_code,s.station_name,tc.action_type
from taskchain tc left join station s on tc.station_code = s.station_code
</select>
<select id="queryTaskchainById" parameterType="string" resultType="org.nl.apt15e.apt.taskchain.service.dao.Taskchain">
select tc.id,tc.chain_id,tc.chain_name,tc.order_num,tc.station_code,s.station_name,tc.action_type
from taskchain tc left join station s on tc.station_code = s.station_code
where tc.chain_id = #{chain_id}
order by tc.order_num asc
</select>
</mapper>

View File

@@ -6,6 +6,10 @@ import org.nl.apt15e.apt.taskchain.service.dao.Taskchain;
import org.nl.apt15e.apt.taskchain.service.dao.mapper.TaskchainMapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
/**
* <p>
* 服务实现类
@@ -17,4 +21,16 @@ import org.springframework.stereotype.Service;
@Service
public class TaskchainServiceImpl extends ServiceImpl<TaskchainMapper, Taskchain> implements ITaskchainService {
@Resource
private TaskchainMapper taskchainMapper;
@Override
public List<Taskchain> queryAllTaskchain() {
return taskchainMapper.queryAllTaskchain();
}
@Override
public List<Taskchain> queryTaskchainById(String chain_id) {
return taskchainMapper.queryTaskchainById(chain_id);
}
}

View File

@@ -16,6 +16,7 @@ import org.nl.apt15e.apt.teaching.service.TeachingService;
import org.nl.apt15e.apt.vehicle.ProcessZip;
import org.nl.apt15e.apt.vehicle.service.impl.VehicleInfoServiceImpl;
import org.nl.apt15e.common.BadRequestException;
import org.nl.apt15e.config.language.LangProcess;
import org.nl.apt15e.config.thread.ProtobufWebSocketHandler;
import org.nl.apt15e.util.HTTPUtil;
import org.nl.apt15e.util.URLConstant;
@@ -57,7 +58,7 @@ public class TeachingServiceImpl implements TeachingService {
@Override
public Map<String, Object> startMapping(String mapName) {
if (StrUtil.isBlank(mapName)){
throw new BadRequestException("mapName is empty");
throw new BadRequestException(LangProcess.msg("param_is_null"));
}
// 开始建图时清除一下 打点记录
teachingStationMap.clear();
@@ -68,7 +69,7 @@ public class TeachingServiceImpl implements TeachingService {
response = HTTPUtil.post(URLConstant.VEHICLE_IP_PORT,"/tool/rob/startMapping", params);
} catch (Exception e) {
log.info("访问车体开始建图接口报错:{}",e.getMessage());
throw new BadRequestException("开始建图失败");
throw new BadRequestException(LangProcess.msg("error_starting_mapping"));
}
// 检查响应状态码
if (response.isOk()) {
@@ -77,13 +78,13 @@ public class TeachingServiceImpl implements TeachingService {
log.info("开始建图:{}",body);
if ("200".equals(body.getString("code"))){
// body =(JSONObject) this.startManual();
body.put("message","开始建图成功");
body.put("message",LangProcess.msg("successful"));
return body;
}
}
log.info("开始建图失败");
throw new BadRequestException("开始建图失败");
throw new BadRequestException(LangProcess.msg("error_starting_mapping"));
}
@Override
@@ -93,7 +94,7 @@ public class TeachingServiceImpl implements TeachingService {
response = HTTPUtil.post(URLConstant.VEHICLE_IP_PORT,"/tool/rob/startManual", new JSONObject());
} catch (Exception e) {
log.info("访问车体切手动接口报错:{}",e.getMessage());
throw new BadRequestException("切手动失败");
throw new BadRequestException(LangProcess.msg("error_cut_manually"));
}
// 检查响应状态码
if (response.isOk() && response.body() != null) {
@@ -101,12 +102,12 @@ public class TeachingServiceImpl implements TeachingService {
JSONObject body = JSON.parseObject(response.body());
log.info("切手动:{}",body);
if ("200".equals(body.getString("code"))){
body.put("message","切自动成功");
body.put("message",LangProcess.msg("successful"));
return body;
}
}
log.info("切手动失败");
throw new BadRequestException("切手动失败");
throw new BadRequestException(LangProcess.msg("error_cut_manually"));
}
@Override
@@ -116,7 +117,7 @@ public class TeachingServiceImpl implements TeachingService {
response = HTTPUtil.post(URLConstant.VEHICLE_IP_PORT,"/tool/rob/stopManual", new JSONObject());
} catch (Exception e) {
log.info("访问车体切自动接口报错:{}",e.getMessage());
throw new BadRequestException("切自动失败");
throw new BadRequestException(LangProcess.msg("error_cut_automatically"));
}
// 检查响应状态码
if (response.isOk() && response.body() != null) {
@@ -124,12 +125,12 @@ public class TeachingServiceImpl implements TeachingService {
JSONObject body = JSON.parseObject(response.body());
log.info("切自动:{}",body);
if ("200".equals(body.getString("code"))){
body.put("message","切自动成功");
body.put("message",LangProcess.msg("successful"));
}
return body;
}
log.info("切自动失败");
throw new BadRequestException("切自动失败");
throw new BadRequestException(LangProcess.msg("error_cut_automatically"));
}
@Override
@@ -139,7 +140,7 @@ public class TeachingServiceImpl implements TeachingService {
response = HTTPUtil.post(URLConstant.VEHICLE_IP_PORT,"/tool/rob/stopMapping", new JSONObject());
} catch (Exception e) {
log.info("访问车体结束建图接口报错:{}",e.getMessage());
throw new BadRequestException("结束建图失败");
throw new BadRequestException(LangProcess.msg("error_end_mapping"));
}
// 检查响应状态码
if (response.isOk() && response.body() != null) {
@@ -148,18 +149,18 @@ public class TeachingServiceImpl implements TeachingService {
log.info("结束建图:{}",body);
if ("200".equals(body.getString("code"))){
// body =(JSONObject) this.stopManual();
body.put("message","结束建图成功");
body.put("message",LangProcess.msg("successful"));
return body;
}
}
log.info("结束建图失败");
throw new BadRequestException("结束建图失败");
throw new BadRequestException(LangProcess.msg("error_end_mapping"));
}
@Override
public Map<String, Object> setStation(String stationName,String stationCode) {
if (StrUtil.isBlank(stationCode) || StrUtil.isBlank(stationName)){
throw new BadRequestException("spotCode is empty");
throw new BadRequestException(LangProcess.msg("param_is_null"));
}
// 记录打点时站点数据
teachingStationMap.put(stationCode,stationName);
@@ -170,7 +171,7 @@ public class TeachingServiceImpl implements TeachingService {
response = HTTPUtil.post(URLConstant.VEHICLE_IP_PORT,"/tool/rob/setStates", params);
} catch (Exception e) {
log.info("访问车体设置站点接口报错:{}",e.getMessage());
throw new BadRequestException("设置站点失败");
throw new BadRequestException(LangProcess.msg("error_set_station"));
}
// 检查响应状态码
if (response.isOk() && response.body() != null) {
@@ -178,22 +179,22 @@ public class TeachingServiceImpl implements TeachingService {
JSONObject body = JSON.parseObject(response.body());
log.info("设置站点:{}",body);
if ("200".equals(body.getString("code"))){
body.put("message","设置站点成功");
body.put("message",LangProcess.msg("successful"));
return body;
}
}
log.info("设置站点失败");
throw new BadRequestException("设置站点失败");
throw new BadRequestException(LangProcess.msg("error_set_station"));
}
@Override
public JSONObject getLocalMaps() {
HttpResponse response = null;
try {
response = HTTPUtil.get(URLConstant.VEHICLE_IP_PORT,"/tool/editor/getLocalMaps", new JSONObject());
response = HTTPUtil.get(URLConstant.VEHICLE_IP_PORT,"/tool/editor/getLocalMaps", new JSONObject(),"");
} catch (Exception e) {
log.info("访问车体地图列表接口报错:{}",e.getMessage());
throw new BadRequestException("获取地图列表失败");
throw new BadRequestException(LangProcess.msg("error_get_Maps"));
}
// 检查响应状态码
if (response.isOk() && response.body() != null) {
@@ -201,18 +202,18 @@ public class TeachingServiceImpl implements TeachingService {
JSONObject body = JSON.parseObject(response.body());
log.info("获取地图列表:{}",body);
if ("200".equals(body.getString("code"))){
body.put("message","获取地图列表成功");
body.put("message",LangProcess.msg("successful"));
return body;
}
}
log.info("获取地图列表失败");
throw new BadRequestException("获取地图列表失败");
throw new BadRequestException(LangProcess.msg("error_get_Maps"));
}
@Override
public Map<String, Object> deployRunMap(String mapName) {
if (StrUtil.isBlank(mapName)){
throw new BadRequestException("mapName is empty");
throw new BadRequestException(LangProcess.msg("param_is_null"));
}
JSONObject params = new JSONObject();
params.put("id", mapName);
@@ -221,7 +222,7 @@ public class TeachingServiceImpl implements TeachingService {
response = HTTPUtil.post(URLConstant.VEHICLE_IP_PORT,"/tool/rob/deployRunMap", params);
} catch (Exception e) {
log.info("访问车体部署地图接口报错:{}",e.getMessage());
throw new BadRequestException("部署地图失败");
throw new BadRequestException(LangProcess.msg("error_deploy_maps"));
}
// 检查响应状态码
if (response.isOk() && response.body() != null) {
@@ -229,18 +230,18 @@ public class TeachingServiceImpl implements TeachingService {
JSONObject body = JSON.parseObject(response.body());
log.info("部署地图:{}",body);
if ("200".equals(body.getString("code"))){
body.put("message","部署地图成功");
body.put("message",LangProcess.msg("successful"));
return body;
}
}
log.info("部署地图失败");
throw new BadRequestException("部署地图失败");
throw new BadRequestException(LangProcess.msg("error_deploy_maps"));
}
@Override
public Map<String, Object> changeCurrentRunMap(String mapName) {
if (StrUtil.isBlank(mapName)){
throw new BadRequestException("mapName is empty");
throw new BadRequestException(LangProcess.msg("param_is_null"));
}
JSONObject params = new JSONObject();
params.put("name", mapName);
@@ -249,7 +250,7 @@ public class TeachingServiceImpl implements TeachingService {
response = HTTPUtil.post(URLConstant.VEHICLE_IP_PORT,"/tool/rob/changeCurrentRunMap", params);
} catch (Exception e) {
log.info("访问车体应用地图接口报错:{}",e.getMessage());
throw new BadRequestException("应用地图失败");
throw new BadRequestException(LangProcess.msg("error_app_maps"));
}
// 检查响应状态码
if (response.isOk() && response.body() != null) {
@@ -257,18 +258,18 @@ public class TeachingServiceImpl implements TeachingService {
JSONObject body = JSON.parseObject(response.body());
log.info("应用地图:{}",body);
if ("200".equals(body.getString("code"))){
body.put("message","应用地图成功");
body.put("message",LangProcess.msg("successful"));
return body;
}
}
log.info("应用地图失败");
throw new BadRequestException("应用地图失败");
throw new BadRequestException(LangProcess.msg("error_app_maps"));
}
@Override
public byte[] getRunMapZip(String mapName) {
if (StrUtil.isBlank(mapName)){
throw new BadRequestException("mapName is empty");
throw new BadRequestException(LangProcess.msg("param_is_null"));
}
JSONObject params = new JSONObject();
params.put("name", mapName);
@@ -277,7 +278,7 @@ public class TeachingServiceImpl implements TeachingService {
response = HTTPUtil.post(URLConstant.VEHICLE_IP_PORT,"/tool/rob/getRunMapZip", params);
} catch (Exception e) {
log.info("访问车体地图包接口报错:{}",e.getMessage());
throw new BadRequestException("获取地图包失败");
throw new BadRequestException(LangProcess.msg("error_get_map_pack"));
}
// 检查响应状态码
if (response.isOk() && response.body() != null) {
@@ -290,7 +291,7 @@ public class TeachingServiceImpl implements TeachingService {
return zipBytes;
}
log.info("获取地图包失败");
throw new BadRequestException("获取地图包失败");
throw new BadRequestException(LangProcess.msg("error_get_map_pack"));
}
@Override
@@ -309,7 +310,7 @@ public class TeachingServiceImpl implements TeachingService {
.execute();
} catch (Exception e) {
log.info("同步地图到调度接口报错:{}",e.getMessage());
throw new BadRequestException("同步地图失败");
throw new BadRequestException(LangProcess.msg("error_synchronized_map"));
}
// 检查响应状态码
if (response.isOk() && response.body() != null) {
@@ -317,18 +318,18 @@ public class TeachingServiceImpl implements TeachingService {
JSONObject body = JSON.parseObject(response.body());
log.info("同步地图:{}",body);
if (body.getBoolean("state")){
body.put("message","同步地图成功");
body.put("message",LangProcess.msg("successful"));
return body;
}
}
log.info("同步地图失败");
throw new BadRequestException("同步地图失败");
throw new BadRequestException(LangProcess.msg("error_synchronized_map"));
}
@Override
public Map<String, Object> relocate(Double x, Double y, Double angle) {
if (ObjectUtil.isEmpty(x) || ObjectUtil.isEmpty(y) || ObjectUtil.isEmpty(angle)){
throw new BadRequestException("params is empty");
throw new BadRequestException(LangProcess.msg("param_is_null"));
}
log.info(angle.toString());
angle = (angle * 180) / Math.PI;
@@ -346,7 +347,7 @@ public class TeachingServiceImpl implements TeachingService {
response = HTTPUtil.post(URLConstant.VEHICLE_IP_PORT,"/tool/rob/relocate", params);
} catch (Exception e) {
log.info("访问车体重定位接口报错:{}",e.getMessage());
throw new BadRequestException("重定位指令下发失败");
throw new BadRequestException(LangProcess.msg("error_relocate"));
}
// 检查响应状态码
if (response.isOk() && response.body() != null) {
@@ -354,12 +355,12 @@ public class TeachingServiceImpl implements TeachingService {
JSONObject body = JSON.parseObject(response.body());
log.info("重定位:{}",body);
if ("200".equals(body.getString("code"))){
body.put("message","重定位指令下发成功,正在重新定位中。");
body.put("message",LangProcess.msg("successful"));
return body;
}
}
log.info("重定位指令下发失败");
throw new BadRequestException("重定位指令下发失败");
throw new BadRequestException(LangProcess.msg("error_relocate"));
}
@Override
@@ -369,7 +370,7 @@ public class TeachingServiceImpl implements TeachingService {
response = HTTPUtil.post(URLConstant.VEHICLE_IP_PORT,"/tool/rob/restart", new JSONObject());
} catch (Exception e) {
log.info("访问车体程序重启接口报错:{}",e.getMessage());
throw new BadRequestException("车体程序重启失败");
throw new BadRequestException(LangProcess.msg("error_restart"));
}
// 检查响应状态码
if (response.isOk() && response.body() != null) {
@@ -377,18 +378,18 @@ public class TeachingServiceImpl implements TeachingService {
JSONObject body = JSON.parseObject(response.body());
log.info("车体程序重启:{}",body);
if ("200".equals(body.getString("code"))){
body.put("message","车体程序重启成功");
body.put("message",LangProcess.msg("successful"));
return body;
}
}
log.info("车体程序重启失败");
throw new BadRequestException("车体程序重启失败");
throw new BadRequestException(LangProcess.msg("error_restart"));
}
@Override
public Map<String, Object> oneClickDeployment(String mapName) {
if (StrUtil.isBlank(mapName)){
throw new BadRequestException("mapName is empty");
throw new BadRequestException(LangProcess.msg("param_is_null"));
}
JSONObject response = new JSONObject();
// 获取地图列表
@@ -419,7 +420,7 @@ public class TeachingServiceImpl implements TeachingService {
);
this.relocate(station.getX(),station.getY(),station.getAngle());
response.put("code", 200);
response.put("message", "部署成功");
response.put("message", LangProcess.msg("successful"));
return response;
}
@@ -437,7 +438,7 @@ public class TeachingServiceImpl implements TeachingService {
response = HTTPUtil.post(URLConstant.VEHICLE_IP_PORT,"/tool/rob/sendCMD", params);
} catch (Exception e) {
log.info("访问车体放弃示教建图接口报错:{}",e.getMessage());
throw new BadRequestException("车体放弃示教建图失败");
throw new BadRequestException(LangProcess.msg("error_abandon_mapping"));
}
// 检查响应状态码
if (response.isOk() && response.body() != null) {
@@ -445,12 +446,12 @@ public class TeachingServiceImpl implements TeachingService {
JSONObject body = JSON.parseObject(response.body());
log.info("放弃示教建图:{}",body);
if ("200".equals(body.getString("code"))){
body.put("message","放弃示教建图成功");
body.put("message",LangProcess.msg("successful"));
return body;
}
}
log.info("放弃示教建图失败");
throw new BadRequestException("放弃示教建图失败");
throw new BadRequestException(LangProcess.msg("error_abandon_mapping"));
}
@Override

View File

@@ -7,15 +7,18 @@ import lombok.extern.slf4j.Slf4j;
import org.nl.apt15e.apt.map.dao.MapInfo;
import org.nl.apt15e.apt.map.dto.ProcessMapYamlDto;
import org.nl.apt15e.apt.map.service.MapInfoService;
import org.nl.apt15e.apt.map.service.mapper.MapInfoMapper;
import org.nl.apt15e.apt.route.dao.RouteInfo;
import org.nl.apt15e.apt.route.service.RouteInfoService;
import org.nl.apt15e.apt.station.StationTypeEnum;
import org.nl.apt15e.apt.station.dao.Station;
import org.nl.apt15e.apt.station.service.StationService;
import org.nl.apt15e.apt.station.service.impl.StationServiceImpl;
import org.nl.apt15e.apt.taskchain.service.ITaskchainService;
import org.nl.apt15e.apt.teaching.service.impl.TeachingServiceImpl;
import org.nl.apt15e.common.BadRequestException;
import org.nl.apt15e.config.file.FileProperties;
import org.nl.apt15e.config.language.LangProcess;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -48,11 +51,14 @@ public class ProcessZip {
private StationService stationService;
@Resource
private MapInfoService mapInfoService;
private MapInfoMapper mapInfoMapper;
@Resource
private RouteInfoService routeInfoService;
@Resource
private ITaskchainService taskchainService;
@Resource
private FileProperties properties;
@@ -69,7 +75,8 @@ public class ProcessZip {
//存储之前先清除站点表、路径表、地图信息表的数据
stationService.remove(new LambdaQueryWrapper<>());
routeInfoService.remove(new LambdaQueryWrapper<>());
mapInfoService.remove(new LambdaQueryWrapper<>());
mapInfoMapper.delete(new LambdaQueryWrapper<>());
taskchainService.remove(new LambdaQueryWrapper<>());
ZipEntry entry;
// 遍历ZIP文件中的每个条目
@@ -92,7 +99,7 @@ public class ProcessZip {
processLine(line, lineNumber);
}
if (lineNumber == 0) {
throw new BadRequestException("地图包数据为空,扫描失败。请重新建图");
throw new BadRequestException(LangProcess.msg("error_map_pack_isNull"));
}
}
// 点云图 .pgm 文件转换 .png
@@ -115,17 +122,18 @@ public class ProcessZip {
mapInfo.setHeight((double) pngImage.getHeight());
if (ObjectUtil.isEmpty(pngImage)) {
log.info("PGM转换失败: {}", entryName);
throw new BadRequestException("地图PGM转换失败: ");
throw new BadRequestException(LangProcess.msg("error_map_pgm"));
}
// 将灰度图转换为透明背景图
pngImage = convertToTransparentBackground(pngImage);
String mapName = entryName.substring(0, entryName.lastIndexOf('.'));
// 保存PNG文件
String pngFileName = entryName.substring(0, entryName.lastIndexOf('.')) + ".png";
String pngFileName = mapName + ".png";
// 记录地图编码、名称
mapInfo.setMapCode(pngFileName);
mapInfo.setMapName(pngFileName);
mapInfo.setMapCode(mapName);
mapInfo.setMapName(mapName);
mapInfo.setMapImageAddress("/file/"+pngFileName);
savePngImage(pngImage, pngFileName);
}
@@ -155,14 +163,14 @@ public class ProcessZip {
line = reader.readLine();
}
if (!flag){
throw new BadRequestException(".YAML文件内容为空");
throw new BadRequestException(LangProcess.msg("error_yaml_isNull"));
}
// 解析YAML内容
String yamlContent = contentBuilder.toString();
ProcessMapYamlDto processMapYamlDto = new Yaml().loadAs(yamlContent, ProcessMapYamlDto.class);
log.info(".yaml数据: {}", processMapYamlDto);
if (ObjectUtil.isEmpty(processMapYamlDto) || processMapYamlDto.getOrigin().length<3){
throw new BadRequestException(".yaml数据信息格式错误");
throw new BadRequestException(LangProcess.msg("error_formatting_error"));
}
// 记录像素比例和图片左下角像素坐标
mapInfo.setResolution(processMapYamlDto.getResolution());
@@ -170,18 +178,18 @@ public class ProcessZip {
mapInfo.setY(processMapYamlDto.getOrigin()[1]);
mapInfo.setAngle(processMapYamlDto.getOrigin()[2]);
} catch (IOException e) {
throw new BadRequestException("YAML解析失败:"+ e.getMessage());
throw new BadRequestException(LangProcess.msg("error_parsing")+ e.getMessage());
}
}
}
// 保存地图信息
if (ObjectUtil.isNotEmpty(mapInfo)) {
log.info("地图信息:{}",mapInfo);
mapInfoService.save(mapInfo);
mapInfoMapper.insert(mapInfo);
}
}
catch (Exception e) {
throw new BadRequestException("处理地图包数据失败:"+e.getMessage());
throw new BadRequestException(LangProcess.msg("error_process_map_pack")+e.getMessage());
}
}
@@ -246,7 +254,7 @@ public class ProcessZip {
return transparentImage;
}catch (Exception e) {
log.info(".png点云图将灰度图像转换为透明背景图像失败:{}",e.getMessage());
throw new BadRequestException(".png点云图将灰度图像转换为透明背景图像失败:"+e.getMessage());
throw new BadRequestException(LangProcess.msg("error_png_convert_transparency")+e.getMessage());
}
}
@@ -273,9 +281,9 @@ public class ProcessZip {
station.setStation_id(Integer.valueOf(processData[1]));
String stationName = "";
if ("A".equals(processData[2])){
stationName = "起点";
stationName = LangProcess.msg("starting_point");
}else if ("C".equals(processData[2])){
stationName = "终点";
stationName = LangProcess.msg("end_point");
}else {
// 判断是否存在打点记录里
if (TeachingServiceImpl.teachingStationMap.containsKey(processData[2])){
@@ -338,7 +346,7 @@ public class ProcessZip {
magic.append(c);
}
if (!magic.toString().equals(PGM_MAGIC_NUMBER)) {
throw new BadRequestException("不支持的PGM格式仅支持P5二进制格式");
throw new BadRequestException(LangProcess.msg("error_p5"));
}
// 解析宽度和高度
@@ -348,7 +356,7 @@ public class ProcessZip {
}
String[] dimensions = dimensionBuilder.toString().trim().split("\\s+");
if (dimensions.length < 2) {
throw new BadRequestException("无效的尺寸格式");
throw new BadRequestException(LangProcess.msg("error_invalid_size"));
}
int width = Integer.parseInt(dimensions[0]);
int height = Integer.parseInt(dimensions[1]);
@@ -370,7 +378,7 @@ public class ProcessZip {
return image;
} catch (Exception e) {
log.info("PGM解析错误: {}", e.getMessage());
throw new BadRequestException("PGM解析错误: "+e.getMessage());
throw new BadRequestException(LangProcess.msg("error_pgm_parse")+e.getMessage());
}
}

View File

@@ -21,6 +21,6 @@ public class VehicleException implements Serializable {
/**
* 错误码
*/
private List<Long> exceptionCodes;
private List<String> exceptionCodes;
}

View File

@@ -1,8 +1,10 @@
package org.nl.apt15e.apt.vehicle.dao;
import lombok.Data;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorInfo;
import java.io.Serializable;
import java.util.List;
/**
* @author dsh
@@ -96,4 +98,20 @@ public class VehicleInfo implements Serializable {
* 是否重启完成 1重启完成
*/
private String ready;
/**
* 叉间避障
*/
private String forkTipObstacles;
/**
* 当前异常列表
*/
private List<ErrorInfo> errorData;
/**
* 异常等级 0无异常(绿灯) 1普通异常(黄灯) 2严重异常(红灯)
*/
private Integer anomalyLevel;
}

View File

@@ -4,6 +4,8 @@ import lombok.extern.slf4j.Slf4j;
import org.nl.apt15e.apt.vehicle.dao.VehicleInfo;
import org.nl.apt15e.apt.vehicle.service.VehicleInfoService;
import org.nl.apt15e.common.logging.annotation.Log;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -30,7 +32,14 @@ public class VehicleInfoController {
@GetMapping("/rebootVehicle")
@Log("重启车辆系统")
public void rebootVehicle() {
vehicleInfoService.rebootVehicle();
public ResponseEntity<Object> rebootVehicle() {
return new ResponseEntity<>(vehicleInfoService.rebootVehicle(), HttpStatus.OK);
}
@GetMapping("/setForkLegsObstacles")
@Log("设置叉腿避障")
public ResponseEntity<Object> setForkLegsObstacles() {
return new ResponseEntity<>(vehicleInfoService.setForkLegsObstacles(), HttpStatus.OK);
}
}

View File

@@ -2,16 +2,34 @@ package org.nl.apt15e.apt.vehicle.service;
import org.nl.apt15e.apt.vehicle.dao.VehicleInfo;
import java.util.Map;
/**
* @author dsh
* 2025/7/2
*/
public interface VehicleInfoService {
/**
* 获取车辆基础信息
* @return
*/
VehicleInfo getVehicleInfo();
void setVehicleInfo(VehicleInfo vehicleInfo);
void rebootVehicle();
/**
* 车辆系统重启
*/
Map rebootVehicle();
/**
* 系统初始化
*/
void systemInitialization();
/**
* 设置叉尖避障
*/
Map<String,Object> setForkLegsObstacles();
}

View File

@@ -1,24 +1,34 @@
package org.nl.apt15e.apt.vehicle.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import comm_protocol.Robottype;
import lombok.extern.slf4j.Slf4j;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorInfo;
import org.nl.apt15e.apt.anomalyInfo.service.ErrorInfoService;
import org.nl.apt15e.apt.map.dto.PointCloudDataDto;
import org.nl.apt15e.apt.map.service.MapInfoService;
import org.nl.apt15e.apt.route.service.RouteInfoService;
import org.nl.apt15e.apt.station.service.StationService;
import org.nl.apt15e.apt.task.enums.TaskStatus;
import org.nl.apt15e.apt.task.service.ITaskService;
import org.nl.apt15e.apt.task.service.dao.Task;
import org.nl.apt15e.apt.task.service.dao.mapper.TaskMapper;
import org.nl.apt15e.apt.task.service.impl.TaskServiceImpl;
import org.nl.apt15e.apt.taskchain.service.ITaskchainService;
import org.nl.apt15e.apt.vehicle.dao.VehicleException;
import org.nl.apt15e.apt.vehicle.dao.VehicleInfo;
import org.nl.apt15e.apt.vehicle.service.VehicleInfoService;
import org.nl.apt15e.apt.websocket.WebSocketPointCloudDataServer;
import org.nl.apt15e.apt.websocket.WebSocketVehicleServer;
import org.nl.apt15e.common.BadRequestException;
import org.nl.apt15e.config.language.LangProcess;
import org.nl.apt15e.config.language.RcsLang;
import org.nl.apt15e.system.enums.ParamCodeConstant;
import org.nl.apt15e.system.service.ParamService;
import org.nl.apt15e.util.HTTPUtil;
@@ -47,6 +57,21 @@ public class VehicleInfoServiceImpl implements VehicleInfoService {
@Resource
private TaskMapper taskMapper;
@Resource
private StationService stationService;
@Resource
private MapInfoService mapInfoService;
@Resource
private RouteInfoService routeInfoService;
@Resource
private ITaskchainService taskchainService;
@Resource
private ErrorInfoService errorInfoService;
@Resource
private ParamService paramService;
@@ -65,21 +90,75 @@ public class VehicleInfoServiceImpl implements VehicleInfoService {
}
@Override
public void rebootVehicle() {
public JSONObject rebootVehicle() {
HttpResponse response = null;
JSONObject result = new JSONObject();
result.put("status", LangProcess.msg("failed"));
try {
response = HTTPUtil.post(URLConstant.VEHICLE_IP_PORT,"/tool/rob/reboot", new JSONObject());
if (response.isOk()){
result.put("status", LangProcess.msg("successful"));
}
return result;
} catch (Exception e) {
log.info("重启系统失败:{}",e.getMessage());
throw new BadRequestException("重启系统失败");
throw new BadRequestException(LangProcess.msg("error_restart_system"));
}
}
@Override
public void systemInitialization() {
HttpResponse response = null;
try {
response = HTTPUtil.post(URLConstant.VEHICLE_IP_PORT,"/tool/rob/recover", new JSONObject());
} catch (Exception e) {
log.info("初始化底层系统失败:{}",e.getMessage());
throw new BadRequestException(LangProcess.msg("error_initializing_system"));
}
// 暂时缺少 调度系统初始化接口
// 清除本地数据
taskMapper.delete(new LambdaQueryWrapper<>());
stationService.remove(new LambdaQueryWrapper<>());
routeInfoService.remove(new LambdaQueryWrapper<>());
mapInfoService.remove(new LambdaQueryWrapper<>());
taskchainService.remove(new LambdaQueryWrapper<>());
}
@Override
public Map<String,Object> setForkLegsObstacles() {
// if (StrUtil.isBlank(stationCode) || StrUtil.isBlank(stationName)){
// throw new BadRequestException("spotCode is empty");
// }
JSONObject params = new JSONObject();
params.put("enable_back_tof", true);
HttpResponse response = null;
try {
response = HTTPUtil.post(URLConstant.VEHICLE_IP_PORT,"/tool/rob/setStates", params);
} catch (Exception e) {
log.info("访问车体关闭叉腿避障接口报错:{}",e.getMessage());
throw new BadRequestException(LangProcess.msg("error_set_forkLegs"));
}
// 检查响应状态码
if (response.isOk() && response.body() != null) {
// 获取响应体内容
JSONObject body = JSON.parseObject(response.body());
log.info("操作叉腿避障:{}",body);
if ("200".equals(body.getString("code"))){
body.put("message",LangProcess.msg("successful"));
return body;
}
}
log.info("关闭叉腿避障失败");
throw new BadRequestException(LangProcess.msg("error_set_forkLegs"));
}
@Async("asynchronousTasks")
public void queryVehicleInfo() {
HttpResponse response = null;
try {
response = HTTPUtil.get(URLConstant.RCS_IP_PORT,"/amr/onlineAmr",null);
response = HTTPUtil.get(URLConstant.RCS_IP_PORT,"/amr/onlineAmr",null,"");
// 检查响应状态码
if (response!=null && response.isOk()) {
// 获取响应体内容
@@ -98,9 +177,24 @@ public class VehicleInfoServiceImpl implements VehicleInfoService {
vehicleInfo.setStateId(data.getLong("stateId"));
vehicleInfo.setState(data.getString("state"));
vehicleInfo.setAreaId(data.getLong("areaId"));
vehicleInfo.setErrorData(new ArrayList<>());
//上报的异常信息
VehicleException vehicleException = JSONObject.toJavaObject(data.getJSONObject("amrException"), VehicleException.class);
JSONObject amrException = data.getJSONObject("amrException");
VehicleException vehicleException = JSONObject.toJavaObject(amrException, VehicleException.class);
vehicleInfo.setExceptionInfo(vehicleException);
List<ErrorInfo> errorInfoList = new ArrayList<>();
// 消息列表
if (ObjectUtil.isNotEmpty(vehicleException.getExceptionCodes())){
errorInfoList = errorInfoService.list(new LambdaQueryWrapper<ErrorInfo>().in(ErrorInfo::getError_code,vehicleException.getExceptionCodes()));
}
// 异常等级 0无异常 1普通异常 2严重异常
OptionalInt maxLevel = errorInfoList.stream().mapToInt(ErrorInfo::getError_category).max();
int anomalyLevel = 0;
if (maxLevel.isPresent()) {
anomalyLevel = maxLevel.getAsInt();
}
vehicleInfo.setAnomalyLevel(anomalyLevel);
vehicleInfo.setErrorData(errorInfoList);
System.out.println("vehicleInfo: " + vehicleInfo);
}
} else {
@@ -114,6 +208,53 @@ public class VehicleInfoServiceImpl implements VehicleInfoService {
}
}
public VehicleInfo queryVehicleInfoI18n(String lang,VehicleInfo vehicleInfo) {
HttpResponse response = null;
try {
response = HTTPUtil.get(URLConstant.RCS_IP_PORT,"/amr/onlineAmr",null,RcsLang.getRcsLanguage(lang));
// 检查响应状态码
if (response!=null && response.isOk()) {
// 获取响应体内容
String body = response.body();
JSONArray jsonArray = JSONObject.parseObject(body).getJSONArray("data");
if (jsonArray.isEmpty()) {
log.info("车辆数据为空");
}
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject data = jsonArray.getJSONObject(i);
vehicleInfo.setId(data.getString("id"));
vehicleInfo.setName(data.getString("name"));
vehicleInfo.setIp(data.getString("ip"));
vehicleInfo.setMapId(data.getLong("mapId"));
vehicleInfo.setMapName(data.getString("mapName"));
vehicleInfo.setStateId(data.getLong("stateId"));
vehicleInfo.setState(data.getString("state"));
vehicleInfo.setAreaId(data.getLong("areaId"));
vehicleInfo.setErrorData(new ArrayList<>());
//上报的异常信息
JSONObject amrException = data.getJSONObject("amrException");
VehicleException vehicleException = JSONObject.toJavaObject(amrException, VehicleException.class);
vehicleInfo.setExceptionInfo(vehicleException);
List<ErrorInfo> errorInfoList = new ArrayList<>();
// 消息列表
if (ObjectUtil.isNotEmpty(vehicleException.getExceptionCodes())){
errorInfoList = errorInfoService.list(new LambdaQueryWrapper<ErrorInfo>().in(ErrorInfo::getError_code,vehicleException.getExceptionCodes()));
}
vehicleInfo.setErrorData(errorInfoList);
System.out.println("vehicleInfo: " + vehicleInfo);
}
} else {
log.info("查询调度车辆信息失败:{}",response);
}
} catch (Exception e) {
log.info("访问调度报错{}", e.getMessage());
}
if (response != null) {
response.close();
}
return vehicleInfo;
}
@Async("asynchronousTasks")
public void sendVehicleInfo() {
CopyOnWriteArraySet<WebSocketVehicleServer> webSocketSet =
@@ -129,7 +270,10 @@ public class VehicleInfoServiceImpl implements VehicleInfoService {
}
webSocketSet.forEach(c -> {
Map<String, Object> vehicleInfoMap = new HashMap<>();
vehicleInfoMap.put("data", vehicleInfo);
log.info("websocket标识:{}",c.getLang());
VehicleInfo webVehicleInfo = vehicleInfo;
webVehicleInfo = this.queryVehicleInfoI18n(c.getLang(),webVehicleInfo);
vehicleInfoMap.put("data", webVehicleInfo);
c.sendDataToClient(vehicleInfoMap);
});
}
@@ -153,8 +297,8 @@ public class VehicleInfoServiceImpl implements VehicleInfoService {
// 初始化车辆IP和调度IP
URLConstant.RCS_IP_PORT = paramService.queryParamObjectByCode(ParamCodeConstant.RCS_URL).getValue();
URLConstant.VEHICLE_IP_PORT = paramService.queryParamObjectByCode(ParamCodeConstant.VEHICLE_URL).getValue();
scheduler.scheduleAtFixedRate(this::queryVehicleInfo,1500);
scheduler.scheduleAtFixedRate(this::sendVehicleInfo, 2000);
scheduler.scheduleAtFixedRate(this::queryVehicleInfo,1000);
scheduler.scheduleAtFixedRate(this::sendVehicleInfo, 1000);
scheduler.scheduleAtFixedRate(this::sendPointCloudData, 1000);
}
}

View File

@@ -41,12 +41,31 @@ public class WebSocketVehicleServer {
*/
private String sid = "";
/**
* 默认语言
*/
private String lang = "zh";
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("sid") String sid) {
this.session = session;
// 获取查询参数中的语言设置
String queryString = session.getRequestURI().getQuery();
if (queryString != null) {
String[] params = queryString.split("&");
for (String param : params) {
if (param.startsWith("lang=")) {
// 获取lang参数值
this.lang = param.substring(5);
break;
}
}
}
//如果存在就先删除一个,防止重复推送消息
webSocketSet.removeIf(webSocket -> webSocket.sid.equals(sid));
webSocketSet.add(this);
@@ -88,7 +107,12 @@ public class WebSocketVehicleServer {
return session;
}
// 发送消息,在定时任务中会调用此方法
// 获取语言的方法
public String getLang() {
return lang;
}
// 推送方法
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}

View File

@@ -0,0 +1,92 @@
package org.nl.apt15e.common.excel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import lombok.extern.slf4j.Slf4j;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorHandling;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorInfo;
import org.nl.apt15e.common.BadRequestException;
import org.nl.apt15e.config.language.LangProcess;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
/**
* @author dsh
* 2025/8/27
*/
@Slf4j
public class ErrorHandlingListener extends AnalysisEventListener<ErrorHandling> {
/**
* 每隔 BATCH_COUNT 条存储数据库然后清理list方便内存回收
*/
private static final int BATCH_COUNT = 1000; // 批处理阈值:cite[2]:cite[5]
private List<ErrorHandling> cachedDataList = new ArrayList<>(BATCH_COUNT);
/**
* 假设我们需要Service进行批量插入
* 也可以使用Mapper但Service层封装批量操作更常见
*/
private IService<ErrorHandling> service;
/**
* 通过构造器传入需要的Service或Mapper
*/
public ErrorHandlingListener(IService<ErrorHandling> service) {
this.service = service;
}
/**
* 每读一行数据,都会调用此方法
* @param data 一行数据类型是泛型T
* @param context
*/
@Override
public void invoke(ErrorHandling data, AnalysisContext context) {
cachedDataList.add(data);
// 达到BATCH_COUNT了需要去存储一次数据库防止数据几万条数据在内存容易OOM
if (cachedDataList.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
cachedDataList.clear();
}
}
/**
* 所有数据解析完成后,会调用此方法
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 确保最后一批数据也持久化到数据库
if (!cachedDataList.isEmpty()) {
saveData();
cachedDataList.clear();
}
log.info("所有Excel数据解析并导入完成");
}
/**
* 批量保存数据到数据库
* 使用MyBatis-Plus的saveBatch方法
*/
@Transactional(rollbackFor = Exception.class)
public void saveData() {
if (!cachedDataList.isEmpty()) {
// 清除所有异常信息 重新导入
service.remove(new QueryWrapper<ErrorHandling>());
// 第二个参数是批次大小
boolean saveResult = service.saveBatch(cachedDataList, BATCH_COUNT);
if (saveResult) {
log.info("成功批量插入 {} 条数据。", cachedDataList.size());
} else {
log.error("批量插入数据失败!");
throw new BadRequestException(LangProcess.msg("failed"));
}
}
}
}

View File

@@ -0,0 +1,92 @@
package org.nl.apt15e.common.excel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import lombok.extern.slf4j.Slf4j;
import org.nl.apt15e.apt.anomalyInfo.dao.ErrorInfo;
import org.nl.apt15e.common.BadRequestException;
import org.nl.apt15e.config.language.LangProcess;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
/**
* @author dsh
* 2025/8/26
*/
@Slf4j
public class ErrorInfoListener extends AnalysisEventListener<ErrorInfo> {
/**
* 每隔 BATCH_COUNT 条存储数据库然后清理list方便内存回收
*/
private static final int BATCH_COUNT = 1000; // 批处理阈值:cite[2]:cite[5]
private List<ErrorInfo> cachedDataList = new ArrayList<>(BATCH_COUNT);
/**
* 假设我们需要Service进行批量插入
* 也可以使用Mapper但Service层封装批量操作更常见
*/
private IService<ErrorInfo> service;
/**
* 通过构造器传入需要的Service或Mapper
*/
public ErrorInfoListener(IService<ErrorInfo> service) {
this.service = service;
}
/**
* 每读一行数据,都会调用此方法
* @param data 一行数据类型是泛型T
* @param context
*/
@Override
public void invoke(ErrorInfo data, AnalysisContext context) {
cachedDataList.add(data);
// 达到BATCH_COUNT了需要去存储一次数据库防止数据几万条数据在内存容易OOM
if (cachedDataList.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
cachedDataList.clear();
}
}
/**
* 所有数据解析完成后,会调用此方法
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 确保最后一批数据也持久化到数据库
if (!cachedDataList.isEmpty()) {
saveData();
cachedDataList.clear();
}
log.info("所有Excel数据解析并导入完成");
}
/**
* 批量保存数据到数据库
* 使用MyBatis-Plus的saveBatch方法
*/
@Transactional(rollbackFor = Exception.class)
public void saveData() {
if (!cachedDataList.isEmpty()) {
// 清除所有异常信息 重新导入
service.remove(new QueryWrapper<ErrorInfo>());
// 第二个参数是批次大小
boolean saveResult = service.saveBatch(cachedDataList, BATCH_COUNT);
if (saveResult) {
log.info("成功批量插入 {} 条数据。", cachedDataList.size());
} else {
log.error("批量插入数据失败!");
throw new BadRequestException(LangProcess.msg("failed"));
}
}
}
}

View File

@@ -0,0 +1,20 @@
package org.nl.apt15e.config;
/**
* @author dsh
* 2025/8/25
*/
public interface CallBack {
/**
* 回调执行方法
*/
void executor();
/**
* 本回调任务名称
* @return /
*/
default String getCallBackName() {
return Thread.currentThread().getId() + ":" + this.getClass().getName();
}
}

View File

@@ -0,0 +1,20 @@
package org.nl.apt15e.config;
import java.io.Serializable;
import java.util.HashMap;
/*
* @author ZZQ
* @Date 2022/11/29 2:55 下午
*/
public class MapOf implements Serializable {
public static <K> HashMap of(K... key){
HashMap map = new HashMap<>();
for (int i = 0; i < (key.length & ~1); i=i+2) {
map.put(key[i],key[i+1]);
}
return map;
}
}

View File

@@ -0,0 +1,141 @@
package org.nl.apt15e.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.env.Environment;
import java.util.ArrayList;
import java.util.List;
/**
* @author dsh
* 2025/8/25
*/
@Slf4j
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
private static ApplicationContext applicationContext = null;
//数据库连接的bean名字
public static String dataSourceBeanName="dataSource";
private static final List<CallBack> CALL_BACKS = new ArrayList<>();
private static boolean addCallback = true;
/**
* 针对 某些初始化方法在SpringContextHolder 未初始化时 提交回调方法。
* 在SpringContextHolder 初始化后,进行回调使用
*
* @param callBack 回调函数
*/
public synchronized static void addCallBacks(CallBack callBack) {
if (addCallback) {
SpringContextHolder.CALL_BACKS.add(callBack);
} else {
log.warn("CallBack{} 已无法添加!立即执行", callBack.getCallBackName());
callBack.executor();
}
}
public static ApplicationContext getApplicationContext() {
try {
} catch (Exception e) {
e.printStackTrace();
}
return applicationContext;
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
assertContextInjected();
return (T) applicationContext.getBean(name);
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
public static <T> T getBean(Class<T> requiredType) {
assertContextInjected();
return applicationContext.getBean(requiredType);
}
/**
* 获取SpringBoot 配置信息
*
* @param property 属性key
* @param defaultValue 默认值
* @param requiredType 返回类型
* @return /
*/
public static <T> T getProperties(String property, T defaultValue, Class<T> requiredType) {
T result = defaultValue;
try {
result = getBean(Environment.class).getProperty(property, requiredType);
} catch (Exception ignored) {}
return result;
}
/**
* 获取SpringBoot 配置信息
*
* @param property 属性key
* @return /
*/
public static String getProperties(String property) {
return getProperties(property, null, String.class);
}
/**
* 获取SpringBoot 配置信息
*
* @param property 属性key
* @param requiredType 返回类型
* @return /
*/
public static <T> T getProperties(String property, Class<T> requiredType) {
return getProperties(property, null, requiredType);
}
/**
* 检查ApplicationContext不为空.
*/
private static void assertContextInjected() {
if (applicationContext == null) {
throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" +
".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder.");
}
}
/**
* 清除SpringContextHolder中的ApplicationContext为Null.
*/
private static void clearHolder() {
log.debug("清除SpringContextHolder中的ApplicationContext:"
+ applicationContext);
applicationContext = null;
}
@Override
public void destroy() {
SpringContextHolder.clearHolder();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringContextHolder.applicationContext != null) {
log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
}
SpringContextHolder.applicationContext = applicationContext;
if (addCallback) {
for (CallBack callBack : SpringContextHolder.CALL_BACKS) {
callBack.executor();
}
CALL_BACKS.clear();
}
SpringContextHolder.addCallback = false;
}
}

View File

@@ -0,0 +1,21 @@
package org.nl.apt15e.config;
import org.nl.apt15e.config.language.InitLocaleResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author dsh
* 2025/8/25
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Bean
public LocaleResolver localeResolver(){
return new InitLocaleResolver();
}
}

View File

@@ -0,0 +1,44 @@
package org.nl.apt15e.config.language;
import cn.hutool.core.util.StrUtil;
import org.nl.apt15e.config.MapOf;
import org.springframework.web.servlet.LocaleResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
import java.util.Map;
/**
* @author dsh
* 2025/8/25
*/
public class InitLocaleResolver implements LocaleResolver {
public static Map<String,String> Language_Country = MapOf.of("vi","vi-VN","id","in-ID","in","in-ID","en-US,en;q=0.9","en-US","en","en-US","zh","zh-CN","ko","ko-KR");
public static String language = "";
@Override
public Locale resolveLocale(HttpServletRequest request) {
String header = request.getHeader("Accept-Language");
if (StrUtil.isNotEmpty(header)){
String lang = Language_Country.get(header);
language = lang;
if (StrUtil.isNotEmpty(lang)){
String[] l = lang.split("-");
//印尼的ISO标准国家代码为id-ID
return new Locale(l[0], l[1]);
}
}
return Locale.getDefault();
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}
public String getLanguage(){
return language;
}
}

View File

@@ -0,0 +1,23 @@
package org.nl.apt15e.config.language;
import cn.hutool.core.util.StrUtil;
import org.nl.apt15e.config.SpringContextHolder;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
/**
* @author dsh
* 2025/8/25
*/
public class LangProcess {
public static String msg(String code,String...args){
MessageSource bean = SpringContextHolder.getBean(MessageSource.class);
if (StrUtil.isEmpty(code)){
return " ";
}
String message = bean.getMessage(code, args, LocaleContextHolder.getLocale());
return message;
}
}

View File

@@ -0,0 +1,21 @@
package org.nl.apt15e.config.language;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.nl.apt15e.config.MapOf;
import java.util.Map;
/**
* @author dsh
* 2025/8/27
*/
@Getter
@AllArgsConstructor
public class RcsLang {
public static Map<String,String> Language_Country = MapOf.of("en","EN","zh","ZH");
public static String getRcsLanguage(String language) {
return Language_Country.get(language);
}
}

View File

@@ -18,6 +18,7 @@ import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.client.WebSocketConnectionManager;
import org.springframework.web.socket.handler.BinaryWebSocketHandler;
import java.text.DecimalFormat;
import java.util.HashSet;
import java.util.Set;
@@ -52,10 +53,17 @@ public class ProtobufWebSocketHandler extends BinaryWebSocketHandler {
JSONObject data_pool = JSONObject.parseObject(robotBase.getDataPool());
String mapping_return = data_pool.getString("mapping_return");
String mapping_percent = data_pool.getString("mapping_percent");
String ready = data_pool.getString("ready");
TeachingServiceImpl.teachingMappingStatus.put("mapping_return", mapping_return);
TeachingServiceImpl.teachingMappingStatus.put("mapping_percent", mapping_percent);
// log.info("建图状态mapping_return:{}建图进度条mapping_percent:{},teachingMappingStatus:{}", mapping_return, mapping_percent,TeachingServiceImpl.teachingMappingStatus);
// 叉尖避障
String back_io_status = data_pool.getString("back_io_status");
VehicleInfoServiceImpl.vehicleInfo.setForkTipObstacles(back_io_status);
// 手自动模式 1手动 0自动
boolean isManual = "0".equals(data_pool.getString("have_hard_manual"));
VehicleInfoServiceImpl.vehicleInfo.setIsManual(isManual);
VehicleInfoServiceImpl.vehicleInfo.setReady(ready);
// 电量
VehicleInfoServiceImpl.vehicleInfo.setBatteryPower((int)robotBase.getBatteryInfo().getSoc());
@@ -63,8 +71,6 @@ public class ProtobufWebSocketHandler extends BinaryWebSocketHandler {
VehicleInfoServiceImpl.vehicleInfo.setX(robotBase.getLocate().getCurrentState().getX());
VehicleInfoServiceImpl.vehicleInfo.setY(robotBase.getLocate().getCurrentState().getY());
VehicleInfoServiceImpl.vehicleInfo.setTheta(robotBase.getLocate().getCurrentState().getTheta());
// 手自动模式
VehicleInfoServiceImpl.vehicleInfo.setIsManual(robotBase.getRobotInactive());
// System.out.println("vehicleInfo2: " + VehicleInfoServiceImpl.vehicleInfo);
break;
@@ -75,18 +81,27 @@ public class ProtobufWebSocketHandler extends BinaryWebSocketHandler {
case LASER_SCAN:
Robottype.LaserData laser = datagram.getLaserScan();
Set<PointCloudDataDto> data = new HashSet<>();
for (Robottype.Point point: laser.getScanList()){
double cosYaw = cos(VehicleInfoServiceImpl.vehicleInfo.getTheta());
double sinYaw = sin(VehicleInfoServiceImpl.vehicleInfo.getTheta());
double x_global = VehicleInfoServiceImpl.vehicleInfo.getX() + cosYaw * point.getX() - sinYaw * point.getY();
double y_global = VehicleInfoServiceImpl.vehicleInfo.getY() + sinYaw * point.getX() + cosYaw * point.getY();
PointCloudDataDto pointCloudDataDto = new PointCloudDataDto();
pointCloudDataDto.setX(x_global);
pointCloudDataDto.setY(y_global);
data.add(pointCloudDataDto);
// 9顶部激光
if (laser.getLocation() == 9){
Set<PointCloudDataDto> data = new HashSet<>();
for (Robottype.Point point: laser.getScanList()){
double cosYaw = cos(VehicleInfoServiceImpl.vehicleInfo.getTheta());
double sinYaw = sin(VehicleInfoServiceImpl.vehicleInfo.getTheta());
double x_global = VehicleInfoServiceImpl.vehicleInfo.getX() + cosYaw * point.getX() - sinYaw * point.getY();
DecimalFormat x_globalDF = new DecimalFormat("#.#");
String x_result = x_globalDF.format(x_global);
double x_globalNum = Double.parseDouble(x_result);
double y_global = VehicleInfoServiceImpl.vehicleInfo.getY() + sinYaw * point.getX() + cosYaw * point.getY();
DecimalFormat y_globalDF = new DecimalFormat("#.#");
String y_result = y_globalDF.format(y_global);
double y_globalNum = Double.parseDouble(y_result);
PointCloudDataDto pointCloudDataDto = new PointCloudDataDto();
pointCloudDataDto.setX(x_globalNum);
pointCloudDataDto.setY(y_globalNum);
data.add(pointCloudDataDto);
}
VehicleInfoServiceImpl.pointCloudData = data;
}
VehicleInfoServiceImpl.pointCloudData = data;
// System.out.println("Received laser_scan: " + list);
break;
}

View File

@@ -4,6 +4,7 @@ import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.i18n.LocaleContextHolder;
/**
* @author dsh
@@ -14,18 +15,19 @@ public class HTTPUtil {
public static HttpResponse post(String url, String method, JSONObject params)throws Exception{
String sendUrl = url + method;
String lang = LocaleContextHolder.getLocale().getLanguage();
return HttpRequest.post(sendUrl)
.setConnectionTimeout(10000)
.setReadTimeout(10000)
.header("token", "admin123")
.header("name", "lx-script")
.header("Content-Type", "application/json")
.header("Lang", "en".equals(lang)?"EN":"ZH")
.body(String.valueOf(params))
.execute();
}
public static HttpResponse get(String url, String method, JSONObject params)throws Exception{
public static HttpResponse get(String url, String method, JSONObject params,String lang)throws Exception{
String sendUrl = url + method;
return HttpRequest.get(sendUrl)
.setConnectionTimeout(10000)
@@ -33,6 +35,7 @@ public class HTTPUtil {
.header("token", "admin123")
.header("name", "lx-script")
.header("Content-Type", "application/json")
.header("Lang", lang)
.form(params)
.execute();

View File

@@ -13,12 +13,12 @@ public class URLConstant {
/**
* RCS调度IP及端口
*/
public static String RCS_IP_PORT = "192.168.100.82:8081";
public static String RCS_IP_PORT = "192.168.100.201:8081";
/**
* 车体后台IP及端口
*/
public static String VEHICLE_IP_PORT = "192.168.100.82:9998";
public static String VEHICLE_IP_PORT = "192.168.100.201:9998";
/**
* 下发任务URL

View File

@@ -1,6 +1,8 @@
server:
# 端口
port: 8011
tomcat:
max-swallow-size: 100MB
spring:
datasource:
druid:

View File

@@ -1,6 +1,8 @@
server:
# 端口
port: 8011
tomcat:
max-swallow-size: 100MB
spring:
datasource:
druid:

View File

@@ -1,6 +1,15 @@
spring:
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
main:
allow-bean-definition-overriding: true
messages:
basename: language/task/task,language/error/error,language/buss/buss
encoding: UTF-8
profiles:
active: dev
active: prod
jackson:
time-zone: GMT+8
@@ -8,7 +17,7 @@ mybatis-plus:
configuration:
map-underscore-to-camel-case: false
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath*:/mapper/**/*.xml
mapper-locations: classpath*:org/nl/apt15e/**/mapper/*.xml
global-config:
banner: false

View File

@@ -0,0 +1,6 @@
starting_point = 起点
end_point = 终点
successful = 操作成功!
failed = 操作失败!
latest = 已经是最新的!
param_is_null = 参数为空!

View File

@@ -0,0 +1,6 @@
starting_point = Starting Point
end_point = End Point
successful = successful!
failed = Failed!
latest = Already up to date!
param_is_null = The parameter is empty!

View File

@@ -0,0 +1,6 @@
starting_point = 起点
end_point = 终点
successful = 操作成功!
failed = 操作失败!
latest = 已经是最新的!
param_is_null = 参数为空!

View File

@@ -0,0 +1,28 @@
error_request_vehicle = 访问车体接口异常:
error_request_rcs = 访问RCS接口异常:
error_starting_mapping = 开始建图失败
error_cut_manually = 切手动失败
error_cut_automatically = 切自动失败
error_end_mapping = 结束建图失败
error_set_station = 设置站点失败
error_get_Maps = 获取地图列表失败
error_deploy_maps = 部署地图失败
error_app_maps = 应用地图失败
error_get_map_pack = 获取地图包失败
error_map_pack_isNull = "地图包数据为空,扫描失败。请重新建图"
error_map_pgm = 地图PGM转换失败
error_yaml_isNull = .YAML文件内容为空
error_formatting_error = 格式错误
error_parsing = YAML解析失败:
error_process_map_pack = 处理地图包数据失败:
error_png_convert_transparency = .png点云图将灰度图像转换为透明背景图像失败:
error_p5 = 不支持的PGM格式仅支持P5二进制格式
error_invalid_size = 无效的尺寸格式
error_pgm_parse = PGM解析错误:
error_synchronized_map = 同步地图失败
error_relocate = 重定位指令下发失败
error_restart = 车体程序重启失败
error_abandon_mapping = 放弃建图失败
error_restart_system = 重启系统失败
error_initializing_system = 初始化底层系统失败
error_set_forkLegs= 操作叉腿避障失败

View File

@@ -0,0 +1,27 @@
error_request_vehicle = Abnormal access to the vehicle body interface
error_request_rcs = Accessing the RCS interface is abnormal
error_starting_mapping = Failed to start mapping
error_cut_manually = Cut manual failure
error_cut_automatically = Cut automatically fails
error_end_mapping = End mapping failed
error_set_station = Setting up the site failed
error_get_Maps = Failed to get the map list
error_deploy_maps = Deploying the map failed
error_app_maps = Applying the map failed
error_get_map_pack = Failed to get the map package
error_map_pack_isNull = The map package data is empty and the scan fails. Please rebuild the map
error_map_pgm = Map PGM conversion failed
error_yaml_isNull = .yaml file content is empty
error_parsing = YAML parsing failed:
error_process_map_pack = Failed to process map packet data:
error_png_convert_transparency = Converting a grayscale image to a transparent background image .png a point cloud plot fails:
error_p5 = PGM format is not supported, only P5 binary format is supported
error_invalid_size = Invalid size format
error_pgm_parse = PGM parsing error:
error_synchronized_map = Syncing maps failed
error_relocate = The relocation instruction failed to be issued
error_restart = The body program restarts failed
error_abandon_mapping = Abandoned mapping failed
error_restart_system = Rebooting the system failed
error_initializing_system = Initializing the underlying system failed
error_set_forkLegs= The operation of the fork leg to avoid obstacles failed

View File

@@ -0,0 +1,27 @@
error_request_vehicle = 访问车体接口异常
error_request_rcs = 访问RCS接口异常
error_starting_mapping = 开始建图失败
error_cut_manually = 切手动失败
error_cut_automatically = 切自动失败
error_end_mapping = 结束建图失败
error_set_station = 设置站点失败
error_get_Maps = 获取地图列表失败
error_deploy_maps = 部署地图失败
error_app_maps = 应用地图失败
error_get_map_pack = 获取地图包失败
error_map_pack_isNull = "地图包数据为空,扫描失败。请重新建图"
error_map_pgm = 地图PGM转换失败
error_yaml_isNull = .YAML文件内容为空
error_parsing = YAML解析失败:
error_process_map_pack = 处理地图包数据失败:
error_png_convert_transparency = .png点云图将灰度图像转换为透明背景图像失败:
error_p5 = 不支持的PGM格式仅支持P5二进制格式
error_invalid_size = 无效的尺寸格式
error_pgm_parse = PGM解析错误:
error_synchronized_map = 同步地图失败
error_relocate = 重定位指令下发失败
error_restart = 车体程序重启失败
error_abandon_mapping = 放弃建图失败
error_restart_system = 重启系统失败
error_initializing_system = 初始化底层系统失败
error_set_forkLegs= 操作叉腿避障失败

View File

@@ -0,0 +1,4 @@
task_Id_isNull=任务不存在!【{0}】
task_Is_exist=当前有正在执行中的任务!
task_Is_not_exist=当前没有任务在执行中!
not_return_point = 没有返回点!

View File

@@ -0,0 +1,4 @@
task_Id_isNull=The task with the task code of {0} was not found
task_Is_exist=There are tasks in progress!
task_Is_not_exist=No tasks are currently in progress!
not_return_point = There is no return point!

View File

@@ -0,0 +1,4 @@
task_Id_isNull=未找到任务编码为{0}的任务
task_Is_exist=当前有正在执行中的任务!
task_Is_not_exist=当前没有任务在执行中!
not_return_point = 没有返回点!