opt:完善地图相关数据和基础数据
This commit is contained in:
@@ -23,6 +23,11 @@ public class MapInfo {
|
||||
*/
|
||||
private String mapName;
|
||||
|
||||
/**
|
||||
* 地图图片地址
|
||||
*/
|
||||
private String mapImageAddress;
|
||||
|
||||
/**
|
||||
* 图片像素宽
|
||||
*/
|
||||
|
||||
@@ -4,6 +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;
|
||||
@@ -21,8 +22,8 @@ public class MapInfoController {
|
||||
@Resource
|
||||
private MapInfoService mapInfoService;
|
||||
|
||||
@RequestMapping("/getMapInfoByCode")
|
||||
public ResponseEntity<Object> getMapInfoByCode(@RequestParam("mapCode") String mapCode) {
|
||||
return new ResponseEntity<>(mapInfoService.getMapInfoByCode(mapCode), HttpStatus.OK);
|
||||
@GetMapping("/getMapInfoByCode")
|
||||
public ResponseEntity<Object> getMapInfoByCode() {
|
||||
return new ResponseEntity<>(mapInfoService.getMapInfoByCode(), HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,17 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.nl.apt15e.apt.map.dao.MapInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/17
|
||||
*/
|
||||
public interface MapInfoService extends IService<MapInfo> {
|
||||
|
||||
JSONObject getMapInfoByCode(String mapCode);
|
||||
/**
|
||||
* 返回当前正在使用的地图数据
|
||||
*/
|
||||
MapInfo getMapInfoByCode();
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import org.nl.apt15e.common.BadRequestException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/17
|
||||
@@ -22,13 +24,7 @@ import org.springframework.stereotype.Service;
|
||||
public class MapInfoServiceImpl extends ServiceImpl<MapInfoMapper, MapInfo> implements MapInfoService {
|
||||
|
||||
@Override
|
||||
public JSONObject getMapInfoByCode(String mapCode) {
|
||||
if (StrUtil.isEmpty(mapCode)) {
|
||||
throw new BadRequestException("mapCode is null");
|
||||
}
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("code", HttpStatus.OK.value());
|
||||
jsonObject.put("data", this.getOne(new LambdaQueryWrapper<>(MapInfo.class).eq(MapInfo::getMapCode,mapCode)));
|
||||
return jsonObject;
|
||||
public MapInfo getMapInfoByCode() {
|
||||
return this.getOne(new LambdaQueryWrapper<>(MapInfo.class));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,11 +51,11 @@ public class RouteInfo {
|
||||
/**
|
||||
* 导航模式 前进模式, 后退模式 ,无头模式
|
||||
*/
|
||||
private Integer navigation_mode;
|
||||
private String navigation_mode;
|
||||
|
||||
/**
|
||||
* 路线类型 直行,转弯
|
||||
*/
|
||||
private Integer route_type;
|
||||
private String route_type;
|
||||
|
||||
}
|
||||
|
||||
@@ -4,11 +4,13 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.nl.apt15e.apt.route.dao.RouteInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/18
|
||||
*/
|
||||
public interface RouteInfoService extends IService<RouteInfo> {
|
||||
|
||||
JSONObject getAllRouteInfo();
|
||||
List<RouteInfo> getAllRouteInfo();
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
@@ -24,10 +25,7 @@ public class RouteInfoServiceImpl extends ServiceImpl<RouteInfoMapper, RouteInfo
|
||||
private RouteInfoMapper routeInfoMapper;
|
||||
|
||||
@Override
|
||||
public JSONObject getAllRouteInfo() {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("code", HttpStatus.OK.value());
|
||||
jsonObject.put("data", routeInfoMapper.selectList(null));
|
||||
return jsonObject;
|
||||
public List<RouteInfo> getAllRouteInfo() {
|
||||
return routeInfoMapper.selectList(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.nl.apt15e.apt.route.service.rest;
|
||||
import org.nl.apt15e.apt.route.service.RouteInfoService;
|
||||
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;
|
||||
|
||||
@@ -19,7 +20,7 @@ public class RouteInfoController {
|
||||
@Resource
|
||||
private RouteInfoService routeInfoService;
|
||||
|
||||
@RequestMapping("/getRouteInfo")
|
||||
@GetMapping("/getRouteInfo")
|
||||
public ResponseEntity<Object> getRouteInfo(){
|
||||
return new ResponseEntity<>(routeInfoService.getAllRouteInfo(), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@@ -12,18 +12,19 @@ import lombok.Getter;
|
||||
public enum StationTypeEnum {
|
||||
|
||||
//站点类型 Station工位点 Charge充电点 Breaks休息点 Docking对接点 System系统自动生成点
|
||||
STATION(1, "STATION", "工位点"),
|
||||
CHARGE(2, "CHARGE", "充电点"),
|
||||
BREAKS(3, "BREAKS", "休息点"),
|
||||
DOCKING(4, "DOCKING", "对接点"),
|
||||
SYSTEM(5, "SYSTEM", "系统自动生成点"),
|
||||
STATION(1, "Station", "工位点"),
|
||||
CHARGE(2, "Charge", "充电点"),
|
||||
BREAKS(3, "Breaks", "休息点"),
|
||||
DOCKING(4, "Docking", "对接点"),
|
||||
SYSTEM(5, "System", "系统自动生成点"),
|
||||
|
||||
|
||||
//动作类型 Ascend升叉 Descend降叉 Move移动 Customize自定义
|
||||
//动作类型 Ascend升叉 Descend降叉 Move移动 Customize自定义 Return返回
|
||||
ASCEND(1, "Ascend", "升叉"),
|
||||
DESCEND(2, "Descend", "降叉"),
|
||||
MOVE(3, "Move", "移动"),
|
||||
CUSTOMIZE(4, "Customize", "自定义");
|
||||
CUSTOMIZE(4, "Customize", "自定义"),
|
||||
RETURN(5, "Return", "返回");
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,7 +35,7 @@ public class Station implements Serializable {
|
||||
private String station_type;
|
||||
|
||||
/**
|
||||
* 动作类型 (Ascend升叉 Descend降叉 Move移动 Customize自定义)
|
||||
* 动作类型 (Ascend升叉 Descend降叉 Move移动 Customize自定义 Return返回)
|
||||
*/
|
||||
private String action_type;
|
||||
|
||||
|
||||
@@ -14,4 +14,7 @@ public interface StationService extends IService<Station> {
|
||||
|
||||
List<Station> queryAllStation();
|
||||
|
||||
List<Station> queryMapAllStation();
|
||||
|
||||
Station queryStationById(Integer id);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,17 @@ public class StationServiceImpl extends ServiceImpl<StationMapper, Station> impl
|
||||
|
||||
@Override
|
||||
public List<Station> queryAllStation() {
|
||||
return stationMapper.selectList(stationMapper.selectList(new LambdaQueryWrapper<>(Station.class)
|
||||
.eq(Station::getStation_type, StationTypeEnum.STATION.getCode())));
|
||||
return stationMapper.selectList(new LambdaQueryWrapper<>(Station.class)
|
||||
.eq(Station::getStation_type, StationTypeEnum.STATION.getCode()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Station> queryMapAllStation() {
|
||||
return stationMapper.selectList(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Station queryStationById(Integer id) {
|
||||
return stationMapper.selectOne(new LambdaQueryWrapper<Station>().eq(Station::getStation_id, id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,17 @@ public class StationController {
|
||||
private StationService stationService;
|
||||
|
||||
@GetMapping("/queryAllStation")
|
||||
private ResponseEntity<Object> startMapping() {
|
||||
private ResponseEntity<Object> queryAllStation() {
|
||||
return new ResponseEntity<>(stationService.queryAllStation(), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping("/queryMapAllStation")
|
||||
private ResponseEntity<Object> queryMapAllStation() {
|
||||
return new ResponseEntity<>(stationService.queryMapAllStation(), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping("/queryStationById")
|
||||
private ResponseEntity<Object> queryStationById(@RequestParam("station_id") Integer station_id) {
|
||||
return new ResponseEntity<>(stationService.queryStationById(station_id), HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,4 +82,9 @@ public class TeachingController {
|
||||
private ResponseEntity<Object> oneClickDeployment(@RequestParam("mapName") String mapName) {
|
||||
return new ResponseEntity<>(teachingService.oneClickDeployment(mapName), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/abandonMapping")
|
||||
private ResponseEntity<Object> abandonMapping() {
|
||||
return new ResponseEntity<>(teachingService.abandonMapping(),HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,4 +86,10 @@ public interface TeachingService {
|
||||
* @return
|
||||
*/
|
||||
Map<String, Object> oneClickDeployment(String mapName);
|
||||
|
||||
/**
|
||||
* 放弃当前示教建图
|
||||
* @return
|
||||
*/
|
||||
Map<String, Object> abandonMapping();
|
||||
}
|
||||
|
||||
@@ -264,6 +264,8 @@ public class TeachingServiceImpl implements TeachingService {
|
||||
if (response.isOk() && response.body() != null) {
|
||||
// 获取zip包
|
||||
byte[] zipBytes = response.bodyBytes();
|
||||
File fileName = new File(mapName);
|
||||
File tempZipFile = FileUtil.writeBytes(zipBytes, FileUtil.createTempFile(fileName));
|
||||
log.info("解析地图包数据");
|
||||
processZip.processZipResponse(zipBytes);
|
||||
return zipBytes;
|
||||
@@ -409,4 +411,34 @@ public class TeachingServiceImpl implements TeachingService {
|
||||
// }
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> abandonMapping() {
|
||||
JSONObject params = new JSONObject();
|
||||
String attach = "{"+
|
||||
"'sub_command':0,"+
|
||||
"'param':''"+
|
||||
"}";
|
||||
params.put("cmd", 906);
|
||||
params.put("attach", JSON.parseObject(attach));
|
||||
HttpResponse response = null;
|
||||
try {
|
||||
response = HTTPUtil.post("http://192.168.100.82:9998","/tool/rob/sendCMD", params);
|
||||
} catch (Exception e) {
|
||||
log.info("访问车体放弃示教建图接口报错:{}",e.getMessage());
|
||||
throw new BadRequestException("车体放弃示教建图失败");
|
||||
}
|
||||
// 检查响应状态码
|
||||
if (response.isOk() && response.body() != null) {
|
||||
// 获取响应体内容
|
||||
JSONObject body = JSON.parseObject(response.body());
|
||||
log.info("放弃示教建图:{}",body);
|
||||
if ("200".equals(body.getString("code"))){
|
||||
body.put("message","放弃示教建图成功");
|
||||
return body;
|
||||
}
|
||||
}
|
||||
log.info("放弃示教建图失败");
|
||||
throw new BadRequestException("放弃示教建图失败");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,15 @@ 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.common.BadRequestException;
|
||||
import org.nl.apt15e.config.file.FileProperties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBufferByte;
|
||||
import java.io.*;
|
||||
@@ -48,9 +51,11 @@ public class ProcessZip {
|
||||
@Resource
|
||||
private RouteInfoService routeInfoService;
|
||||
|
||||
@Resource
|
||||
private FileProperties properties;
|
||||
|
||||
|
||||
private static final String PGM_MAGIC_NUMBER = "P5";
|
||||
private static final String OUTPUT_DIR = "/logs";
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void processZipResponse(byte[] zipBytes) {
|
||||
@@ -59,6 +64,11 @@ public class ProcessZip {
|
||||
|
||||
MapInfo mapInfo = new MapInfo();
|
||||
|
||||
//存储之前先清除站点表中数据和路径表中的数据
|
||||
stationService.remove(new LambdaQueryWrapper<>());
|
||||
routeInfoService.remove(new LambdaQueryWrapper<>());
|
||||
mapInfoService.remove(new LambdaQueryWrapper<>());
|
||||
|
||||
ZipEntry entry;
|
||||
// 遍历ZIP文件中的每个条目
|
||||
while ((entry = zis.getNextEntry()) != null) {
|
||||
@@ -72,10 +82,6 @@ public class ProcessZip {
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(zis, StandardCharsets.UTF_8));
|
||||
|
||||
//存储站点之前先清除站点表中数据和路径表中的数据
|
||||
stationService.remove(new LambdaQueryWrapper<>());
|
||||
routeInfoService.remove(new LambdaQueryWrapper<>());
|
||||
|
||||
String line;
|
||||
int lineNumber = 0;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
@@ -110,11 +116,15 @@ public class ProcessZip {
|
||||
throw new BadRequestException("地图PGM转换失败: ");
|
||||
}
|
||||
|
||||
// 将灰度图转换为透明背景图
|
||||
pngImage = convertToTransparentBackground(pngImage);
|
||||
|
||||
// 保存PNG文件
|
||||
String pngFileName = entryName.substring(0, entryName.lastIndexOf('.')) + ".png";
|
||||
// 记录地图编码、名称
|
||||
mapInfo.setMapCode(pngFileName);
|
||||
mapInfo.setMapName(pngFileName);
|
||||
mapInfo.setMapImageAddress("/file/"+pngFileName);
|
||||
savePngImage(pngImage, pngFileName);
|
||||
}
|
||||
}
|
||||
@@ -173,6 +183,71 @@ public class ProcessZip {
|
||||
}
|
||||
}
|
||||
|
||||
// 将灰度图像转换为透明背景图像
|
||||
private BufferedImage convertToTransparentBackground(BufferedImage grayImage) {
|
||||
try {
|
||||
|
||||
// 创建支持透明度的ARGB图像
|
||||
BufferedImage transparentImage = new BufferedImage(
|
||||
grayImage.getWidth(),
|
||||
grayImage.getHeight(),
|
||||
BufferedImage.TYPE_INT_ARGB
|
||||
);
|
||||
|
||||
// 获取灰度图像的像素数据
|
||||
byte[] grayPixels = ((DataBufferByte) grayImage.getRaster().getDataBuffer()).getData();
|
||||
int width = grayImage.getWidth();
|
||||
int height = grayImage.getHeight();
|
||||
|
||||
// 创建ARGB像素数组
|
||||
int[] argbPixels = new int[width * height];
|
||||
|
||||
// // 转换每个像素
|
||||
// for (int y = 0; y < height; y++) {
|
||||
// for (int x = 0; x < width; x++) {
|
||||
// int index = y * width + x;
|
||||
// // 灰度值(0-255),0=黑,255=白
|
||||
// int grayValue = grayPixels[index] & 0xFF;
|
||||
//
|
||||
// // 创建ARGB像素(Alpha, Red, Green, Blue)
|
||||
// // 白色背景(>=250)设为完全透明,其他保持黑色但完全不透明
|
||||
// if (grayValue >= 250) {
|
||||
// // 完全透明 (Alpha=0)
|
||||
// argbPixels[index] = 0x00FFFFFF;
|
||||
// } else {
|
||||
// // 完全不透明 (Alpha=255) + 灰度值转为RGB
|
||||
// int rgb = grayValue << 16 | grayValue << 8 | grayValue;
|
||||
// argbPixels[index] = 0xFF000000 | rgb;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// 转换每个像素
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int index = y * width + x;
|
||||
// 灰度值(0-255),0=黑,255=白
|
||||
int grayValue = grayPixels[index] & 0xFF;
|
||||
|
||||
// 创建ARGB像素(Alpha, Red, Green, Blue)
|
||||
if (grayValue >= 250) {
|
||||
// 白色背景(>=250)设为完全透明
|
||||
argbPixels[index] = 0x00FFFFFF; // 透明
|
||||
} else {
|
||||
// 黑色点云转为白色点云(完全不透明)
|
||||
argbPixels[index] = 0xFFFFFFFF; // 不透明的白色
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 设置ARGB像素数据
|
||||
transparentImage.setRGB(0, 0, width, height, argbPixels, 0, width);
|
||||
return transparentImage;
|
||||
}catch (Exception e) {
|
||||
log.info(".png点云图将灰度图像转换为透明背景图像失败:{}",e.getMessage());
|
||||
throw new BadRequestException(".png点云图将灰度图像转换为透明背景图像失败:"+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void processLine(String line, int lineNumber) {
|
||||
// 跳过空行
|
||||
if (line.trim().isEmpty()) {
|
||||
@@ -211,7 +286,7 @@ public class ProcessZip {
|
||||
stationService.save(station);
|
||||
System.out.printf("行号 %d - 有效数据: %s%n", lineNumber, station);
|
||||
//Route路径标识
|
||||
}else if ("Route".equals(processData[0]) && processData.length > 23){
|
||||
}else if ("Route".equals(processData[0]) && processData.length >22 ){
|
||||
System.out.printf("行号 %d - 有效路径数据: %s%n", lineNumber, Arrays.toString(processData));
|
||||
RouteInfo routeInfo = new RouteInfo();
|
||||
routeInfo.setRoute_id(Integer.valueOf(processData[1]));
|
||||
@@ -221,8 +296,8 @@ public class ProcessZip {
|
||||
routeInfo.setStart_y(Double.valueOf(processData[5]));
|
||||
routeInfo.setEnd_x(Double.valueOf(processData[6]));
|
||||
routeInfo.setEnd_y(Double.valueOf(processData[7]));
|
||||
routeInfo.setNavigation_mode(Integer.valueOf(processData[16]));
|
||||
routeInfo.setRoute_type(Integer.valueOf(processData[17]));
|
||||
routeInfo.setNavigation_mode(processData[16].replaceAll("^\"|\"$", ""));
|
||||
routeInfo.setRoute_type(processData[17].replaceAll("^\"|\"$", ""));
|
||||
routeInfoService.save(routeInfo);
|
||||
|
||||
System.out.printf("行号 %d - 有效数据: %s%n", lineNumber, routeInfo);
|
||||
@@ -287,7 +362,7 @@ public class ProcessZip {
|
||||
private void savePngImage(BufferedImage image, String fileName) {
|
||||
try {
|
||||
// 确保输出目录存在
|
||||
File outputDir = new File(OUTPUT_DIR);
|
||||
File outputDir = new File(properties.getPath().getPath());
|
||||
if (!outputDir.exists()) {
|
||||
outputDir.mkdirs();
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public class VehicleInfo implements Serializable {
|
||||
/**
|
||||
* 电量
|
||||
*/
|
||||
private Long batteryPower;
|
||||
private Double batteryPower;
|
||||
|
||||
/**
|
||||
* 异常信息
|
||||
@@ -76,4 +76,9 @@ public class VehicleInfo implements Serializable {
|
||||
* 车辆角度
|
||||
*/
|
||||
private Double theta;
|
||||
|
||||
/**
|
||||
* 是否是手动模式
|
||||
*/
|
||||
private Boolean isManual;
|
||||
}
|
||||
|
||||
@@ -10,4 +10,6 @@ public interface VehicleInfoService {
|
||||
|
||||
VehicleInfo getVehicleInfo();
|
||||
|
||||
void setVehicleInfo(VehicleInfo vehicleInfo);
|
||||
|
||||
}
|
||||
|
||||
@@ -37,6 +37,11 @@ public class VehicleInfoServiceImpl implements VehicleInfoService {
|
||||
return vehicleInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVehicleInfo(VehicleInfo vehicleInfo) {
|
||||
|
||||
}
|
||||
|
||||
@Async("asynchronousTasks")
|
||||
public void queryVehicleInfo() {
|
||||
HttpResponse response = null;
|
||||
@@ -52,18 +57,17 @@ public class VehicleInfoServiceImpl implements VehicleInfoService {
|
||||
}
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
JSONObject data = jsonArray.getJSONObject(i);
|
||||
vehicleInfo = JSONObject.toJavaObject(data, VehicleInfo.class);
|
||||
//电量
|
||||
vehicleInfo.setBatteryPower(data.getLong("batteryPercentile"));
|
||||
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"));
|
||||
//上报的异常信息
|
||||
VehicleException vehicleException = JSONObject.toJavaObject(data.getJSONObject("amrException"), VehicleException.class);
|
||||
vehicleInfo.setExceptionInfo(vehicleException);
|
||||
//x,y,theta
|
||||
JSONObject coordinate = data.getJSONObject("coordinate");
|
||||
vehicleInfo.setX(coordinate.getDouble("x"));
|
||||
vehicleInfo.setY(coordinate.getDouble("y"));
|
||||
vehicleInfo.setTheta(coordinate.getDouble("theta"));
|
||||
System.out.println("Response Body: " + data);
|
||||
System.out.println("vehicleInfo: " + vehicleInfo);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package org.nl.apt15e.config;
|
||||
|
||||
import org.nl.apt15e.config.file.FileProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
@@ -10,7 +13,27 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
* 2025/7/14
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class CorsConfig implements WebMvcConfigurer {
|
||||
|
||||
/** 文件配置 */
|
||||
private final FileProperties properties;
|
||||
|
||||
public CorsConfig(FileProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
FileProperties.ElPath path = properties.getPath();
|
||||
String avatarUtl = "file:" + path.getAvatar().replace("\\","/");
|
||||
String pathUtl = "file:" + path.getPath().replace("\\","/");
|
||||
registry.addResourceHandler("/avatar/**").addResourceLocations(avatarUtl).setCachePeriod(0);
|
||||
registry.addResourceHandler("/file/**").addResourceLocations(pathUtl).setCachePeriod(0);
|
||||
registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/").setCachePeriod(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
|
||||
45
src/main/java/org/nl/apt15e/config/file/FileProperties.java
Normal file
45
src/main/java/org/nl/apt15e/config/file/FileProperties.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package org.nl.apt15e.config.file;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/24
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "file")
|
||||
public class FileProperties {
|
||||
|
||||
/** 文件大小限制 */
|
||||
private Long maxSize;
|
||||
|
||||
/** 头像大小限制 */
|
||||
private Long avatarMaxSize;
|
||||
|
||||
private ElPath mac;
|
||||
|
||||
private ElPath linux;
|
||||
|
||||
private ElPath windows;
|
||||
|
||||
public ElPath getPath(){
|
||||
String os = System.getProperty("os.name");
|
||||
if(os.toLowerCase().startsWith("win")) {
|
||||
return windows;
|
||||
} else if(os.toLowerCase().startsWith("mac")){
|
||||
return mac;
|
||||
}
|
||||
return linux;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ElPath{
|
||||
|
||||
private String path;
|
||||
|
||||
private String avatar;
|
||||
}
|
||||
}
|
||||
@@ -1,73 +1,111 @@
|
||||
//package org.nl.apt15e.config.thread;
|
||||
//
|
||||
//import comm_protocol.Robottype;
|
||||
//import comm_protocol.Uidata;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.stereotype.Component;
|
||||
//import org.springframework.web.socket.BinaryMessage;
|
||||
//import org.springframework.web.socket.CloseStatus;
|
||||
//import org.springframework.web.socket.TextMessage;
|
||||
//import org.springframework.web.socket.WebSocketSession;
|
||||
//import org.springframework.web.socket.handler.BinaryWebSocketHandler;
|
||||
//
|
||||
//import static comm_protocol.Uidata.UiDatagram.ItemCase.*;
|
||||
//
|
||||
///**
|
||||
// * @author dsh
|
||||
// * 2025/7/9
|
||||
// */
|
||||
//@Slf4j
|
||||
//@Component
|
||||
//public class ProtobufWebSocketHandler extends BinaryWebSocketHandler {
|
||||
//
|
||||
// @Override
|
||||
// protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
|
||||
// try {
|
||||
// // 解析Protobuf数据
|
||||
// byte[] payload = message.getPayload().array();
|
||||
// Uidata.UiDatagram datagram = Uidata.UiDatagram.parseFrom(payload);
|
||||
//
|
||||
// switch (datagram.getItemCase()) {
|
||||
// case ONLINE_INFO:
|
||||
// Uidata.UiOnline online = datagram.getOnlineInfo();
|
||||
// System.out.println("Received online_info: " + online);
|
||||
// break;
|
||||
//
|
||||
// case HEARTBEAT:
|
||||
// Uidata.UiHeartbeat heartbeat = datagram.getHeartbeat();
|
||||
// System.out.println("Received heartbeat: " + heartbeat);
|
||||
// break;
|
||||
//
|
||||
// case LASER_SCAN:
|
||||
package org.nl.apt15e.config.thread;
|
||||
|
||||
import comm_protocol.Robottype;
|
||||
import comm_protocol.Uidata;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nl.apt15e.apt.vehicle.service.impl.VehicleInfoServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.socket.BinaryMessage;
|
||||
import org.springframework.web.socket.CloseStatus;
|
||||
import org.springframework.web.socket.TextMessage;
|
||||
import org.springframework.web.socket.WebSocketSession;
|
||||
import org.springframework.web.socket.client.WebSocketConnectionManager;
|
||||
import org.springframework.web.socket.handler.BinaryWebSocketHandler;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static comm_protocol.Uidata.UiDatagram.ItemCase.*;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/9
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@EnableScheduling
|
||||
public class ProtobufWebSocketHandler extends BinaryWebSocketHandler {
|
||||
|
||||
private static Boolean isConnected = false;
|
||||
@Autowired
|
||||
private WebSocketConnectionManager connectionManager;
|
||||
private WebSocketSession currentSession;
|
||||
|
||||
|
||||
@Override
|
||||
protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
|
||||
try {
|
||||
// 解析Protobuf数据
|
||||
byte[] payload = message.getPayload().array();
|
||||
Uidata.UiDatagram datagram = Uidata.UiDatagram.parseFrom(payload);
|
||||
|
||||
switch (datagram.getItemCase()) {
|
||||
case ROBOT_BASE:
|
||||
Robottype.RobotBase robotBase = datagram.getRobotBase();
|
||||
// 电量
|
||||
VehicleInfoServiceImpl.vehicleInfo.setBatteryPower(robotBase.getBatteryInfo().getSoc());
|
||||
//x,y,theta
|
||||
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;
|
||||
|
||||
case HEARTBEAT:
|
||||
Uidata.UiHeartbeat heartbeat = datagram.getHeartbeat();
|
||||
System.out.println("Received heartbeat: " + heartbeat);
|
||||
break;
|
||||
|
||||
case LASER_SCAN:
|
||||
// Robottype.LaserData laser = datagram.getLaserScan();
|
||||
// System.out.println("Received laser_scan: " + laser);
|
||||
// break;
|
||||
//
|
||||
// case IMAGE:
|
||||
// // 处理图像数据
|
||||
// break;
|
||||
//
|
||||
// case CONTROL_SPEED:
|
||||
// // 处理速度控制
|
||||
// break;
|
||||
//
|
||||
// case ITEM_NOT_SET:
|
||||
// System.err.println("UiDatagram item not set!");
|
||||
// break;
|
||||
// }
|
||||
// session.close();
|
||||
// } catch (Exception e) {
|
||||
// log.error("Error processing protobuf message", e);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void afterConnectionEstablished(WebSocketSession session) {
|
||||
// log.info("Connected to WebSocket server: {}", session.getUri());
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
|
||||
// log.info("Connection closed: {}", status);
|
||||
// }
|
||||
//}
|
||||
// System.out.println("Received laser_scan: " + laser.getScanList());
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error processing protobuf message", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConnectionEstablished(WebSocketSession session) {
|
||||
log.info("Connected to WebSocket server: {}", session.getUri());
|
||||
isConnected = true;
|
||||
currentSession = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
|
||||
log.info("Connection closed: {}", status);
|
||||
isConnected = false;
|
||||
currentSession = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTransportError(WebSocketSession session, Throwable exception) {
|
||||
log.info("传输错误: {}", exception.getMessage());
|
||||
isConnected = false;
|
||||
currentSession = null;
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = 5000)
|
||||
public synchronized void reconnectTask() {
|
||||
if (!isConnected) {
|
||||
try {
|
||||
log.info("websocket 正在进行重连..");
|
||||
// 先停止当前连接(如果正在运行)
|
||||
if (connectionManager.isRunning()) {
|
||||
connectionManager.stop();
|
||||
}
|
||||
// 启动新连接
|
||||
connectionManager.start();
|
||||
}catch (Exception e) {
|
||||
log.error("websocket重连失败:{}",e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +1,52 @@
|
||||
//package org.nl.apt15e.config.thread;
|
||||
//
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.context.annotation.Bean;
|
||||
//import org.springframework.context.annotation.Configuration;
|
||||
//import org.springframework.stereotype.Component;
|
||||
//import org.springframework.web.socket.client.WebSocketClient;
|
||||
//import org.springframework.web.socket.client.WebSocketConnectionManager;
|
||||
//import org.springframework.web.socket.client.standard.StandardWebSocketClient;
|
||||
//
|
||||
//import javax.websocket.ContainerProvider;
|
||||
//import javax.websocket.WebSocketContainer;
|
||||
//
|
||||
///**
|
||||
// * @author dsh
|
||||
// * 2025/7/9
|
||||
// */
|
||||
//@Slf4j
|
||||
//@Configuration
|
||||
//public class WebsocketClientConfig {
|
||||
//
|
||||
// @Bean
|
||||
// public WebSocketClient webSocketClient() {
|
||||
// // 创建WebSocket容器并配置缓冲区大小
|
||||
// WebSocketContainer container = ContainerProvider.getWebSocketContainer();
|
||||
// // 256KB
|
||||
// container.setDefaultMaxBinaryMessageBufferSize(100 * 1024);
|
||||
// container.setDefaultMaxTextMessageBufferSize(100 * 1024);
|
||||
//
|
||||
// return new StandardWebSocketClient(container);
|
||||
// }
|
||||
//
|
||||
// @Bean
|
||||
// public WebSocketConnectionManager webSocketConnectionManager() {
|
||||
// String serverUrl = "ws://192.168.100.82:9998/ws/AGVInfo";
|
||||
//
|
||||
// WebSocketConnectionManager manager = new WebSocketConnectionManager(
|
||||
// this.webSocketClient(),
|
||||
// new ProtobufWebSocketHandler(),
|
||||
// serverUrl
|
||||
// );
|
||||
// manager.setAutoStartup(true);
|
||||
// return manager;
|
||||
// }
|
||||
//}
|
||||
package org.nl.apt15e.config.thread;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.socket.WebSocketHandler;
|
||||
import org.springframework.web.socket.client.WebSocketClient;
|
||||
import org.springframework.web.socket.client.WebSocketConnectionManager;
|
||||
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.websocket.ContainerProvider;
|
||||
import javax.websocket.WebSocketContainer;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/9
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class WebsocketClientConfig {
|
||||
|
||||
@Bean
|
||||
public WebSocketClient webSocketClient() {
|
||||
// 创建WebSocket容器并配置缓冲区大小
|
||||
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
|
||||
// 256KB
|
||||
container.setDefaultMaxBinaryMessageBufferSize(100 * 1024);
|
||||
container.setDefaultMaxTextMessageBufferSize(100 * 1024);
|
||||
|
||||
return new StandardWebSocketClient(container);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebSocketConnectionManager webSocketConnectionManager() {
|
||||
String serverUrl = "ws://192.168.100.82:9998/ws/AGVInfo";
|
||||
|
||||
WebSocketConnectionManager manager = new WebSocketConnectionManager(
|
||||
this.webSocketClient(),
|
||||
new ProtobufWebSocketHandler(),
|
||||
serverUrl
|
||||
);
|
||||
manager.setAutoStartup(false);
|
||||
return manager;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ public class URLConstant {
|
||||
/**
|
||||
* RCS调度IP及端口
|
||||
*/
|
||||
public final static String RCS_IP_PORT = "127.0.0.1:8011";
|
||||
public final static String RCS_IP_PORT = "192.168.100.82:8081";
|
||||
|
||||
/**
|
||||
* 下发任务URL
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
server:
|
||||
# 端口
|
||||
port: 8081
|
||||
port: 8011
|
||||
spring:
|
||||
datasource:
|
||||
druid:
|
||||
db-type: com.alibaba.druid.pool.DruidDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/apt_data?serverTimezone=GMT%2B8&characterEncoding=utf-8&userSSL=false
|
||||
url: jdbc:mysql://localhost:3306/nl_apt15e?serverTimezone=GMT%2B8&characterEncoding=utf-8&userSSL=false
|
||||
username: root
|
||||
password: 123456
|
||||
# 初始连接数
|
||||
@@ -49,4 +49,19 @@ spring:
|
||||
merge-sql: true
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
||||
multi-statement-allow: true
|
||||
|
||||
# 文件存储路径
|
||||
file:
|
||||
mac:
|
||||
path: ~/file/
|
||||
avatar: ~/avatar/
|
||||
linux:
|
||||
path: /home/eladmin/file/
|
||||
avatar: /home/eladmin/avatar/
|
||||
windows:
|
||||
path: C:\eladmin\file\
|
||||
avatar: C:\eladmin\avatar\
|
||||
# 文件大小 /M
|
||||
maxSize: 100
|
||||
avatarMaxSize: 5
|
||||
@@ -49,4 +49,19 @@ spring:
|
||||
merge-sql: true
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
||||
multi-statement-allow: true
|
||||
|
||||
# 文件存储路径
|
||||
file:
|
||||
mac:
|
||||
path: ~/file/
|
||||
avatar: ~/avatar/
|
||||
linux:
|
||||
path: /home/eladmin/file/
|
||||
avatar: /home/eladmin/avatar/
|
||||
windows:
|
||||
path: C:\eladmin\file\
|
||||
avatar: C:\eladmin\avatar\
|
||||
# 文件大小 /M
|
||||
maxSize: 100
|
||||
avatarMaxSize: 5
|
||||
Reference in New Issue
Block a user