Compare commits

...

9 Commits

Author SHA1 Message Date
cbs
1c868b037b 车辆添加摄像头IP 2025-04-21 09:01:57 +08:00
cbs
1815857395 远遥通讯测试 2025-04-18 17:10:28 +08:00
cbs
031617a5f1 修改配置 2025-04-18 11:54:47 +08:00
cbs
d8d2419eb2 异常任务重新分配机器人 2025-04-18 08:57:01 +08:00
cbs
e67afa8c3d 远遥修改配置 2025-04-17 15:07:27 +08:00
cbs
bf0c12c7ce 添加远遥模块 2025-04-17 14:09:10 +08:00
cbs
651889ad23 地图暂停和恢复 2025-04-17 10:15:57 +08:00
cbs
d595f15872 地图暂停和恢复 2025-04-17 09:08:10 +08:00
cbs
69a0ebe694 任务完成 2025-04-15 17:16:15 +08:00
83 changed files with 2968 additions and 52 deletions

View File

@ -16,6 +16,7 @@
<module>yudao-module-infra</module>
<module>yudao-module-grpc</module>
<module>yudao-module-mqtt</module>
<module>yudao-module-remote</module>
<!-- <module>yudao-module-member</module>-->
<!-- <module>yudao-module-bpm</module>-->
<!-- <module>yudao-module-pay</module>-->

View File

@ -31,6 +31,19 @@ spring:
- Path=/app-api/system/**
filters:
- RewritePath=/app-api/system/v3/api-docs, /v3/api-docs
## remote-server 服务
- id: remote-admin-api # 路由的编号
uri: grayLb://remote-server
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
- Path=/admin-api/remote/**
filters:
- RewritePath=/admin-api/remote/v3/api-docs, /v3/api-docs # 配置,保证转发到 /v3/api-docs
- id: remote-app-api # 路由的编号
uri: grayLb://remote-server
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
- Path=/app-api/remote/**
filters:
- RewritePath=/app-api/remote/v3/api-docs, /v3/api-docs
## infra-server 服务
- id: infra-admin-api # 路由的编号
uri: grayLb://infra-server
@ -188,6 +201,9 @@ knife4j:
- name: system-server
service-name: system-server
url: /admin-api/system/v3/api-docs
- name: remote-server
service-name: remote-server
url: /admin-api/remote/v3/api-docs
- name: infra-server
service-name: infra-server
url: /admin-api/infra/v3/api-docs

View File

@ -28,4 +28,7 @@ public class RobotDimensionsDTO {
@Schema(description = "mac地址")
private String macAddress;
@Schema(description = "转弯半径(单位米)")
private Double robotTurningRadius;
}

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<modules>
<module>yudao-module-remote-api</module>
<module>yudao-module-remote-biz</module>
</modules>
<artifactId>yudao-module-remote</artifactId>
<packaging>pom</packaging>
<name>${project.artifactId}</name>
<description>
system 模块下,我们放通用业务,支撑上层的核心业务。
例如说:用户、部门、权限、数据字典等等
</description>
</project>

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-remote</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-module-remote-api</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
remote 模块 API暴露给其它模块调用
</description>
<dependencies>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-common</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<scope>provided</scope> <!-- 设置为 provided主要是 PageParam 使用到 -->
</dependency>
<!-- 参数校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<optional>true</optional>
</dependency>
<!-- RPC 远程调用相关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,23 @@
package cn.iocoder.cloud.module.remote.enums;
import cn.iocoder.yudao.framework.common.enums.RpcConstants;
/**
* API 相关的枚举
*
* @author 芋道源码
*/
public class ApiConstants {
/**
* 服务名
*
* 注意需要保证和 spring.application.name 保持一致
*/
public static final String NAME = "remote-server";
public static final String PREFIX = RpcConstants.RPC_API_PREFIX + "/remote";
public static final String VERSION = "1.0.0";
}

View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-remote</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-module-remote-biz</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
remote 模块,主要提供能力:
1. 与设备通信
</description>
<dependencies>
<!-- Spring Cloud 基础 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-env</artifactId>
</dependency>
<!-- 依赖服务 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-system-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-remote-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-websocket</artifactId>
</dependency>
<!-- DB 相关 -->
<!--<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId> &lt;!&ndash; 代码生成器,使用它解析表结构 &ndash;&gt;
</dependency>-->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-redis</artifactId>
</dependency>
<!-- RPC 远程调用相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-rpc</artifactId>
</dependency>
<!-- Registry 注册中心相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Config 配置中心相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- Job 定时任务相关 -->
<!--<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-job</artifactId>
</dependency>-->
<!-- 消息队列相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-mq</artifactId>
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId> <!-- 实现代码生成 -->
</dependency>
<!-- 监控相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-monitor</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId> <!-- 实现 Spring Boot Admin Server 服务端 -->
</dependency>
<!-- 三方云服务相关 -->
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId> <!-- 文件客户端:解决 ftp 连接 -->
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId> <!-- 文件客户端:解决 sftp 连接 -->
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId> <!-- 文件客户端解决阿里云、腾讯云、minio 等 S3 连接 -->
</dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId> <!-- 文件客户端:文件类型的识别 -->
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 打包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.remote;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@EnableCaching
@EnableAsync
public class RemoteServerApplication {
public static void main(String[] args) {
// 如果你碰到启动的问题请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
// 如果你碰到 启动的问题请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
// 如果你碰到启动的问题请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
SpringApplication.run(RemoteServerApplication.class, args);
// 如果你碰到启动的问题请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
// 如果你碰到启动的问题请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
// 如果你碰到启动的问题请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
}
}

View File

@ -0,0 +1,48 @@
package cn.iocoder.yudao.module.remote.controller.admin.login;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.remote.service.login.LoginService;
import cn.iocoder.yudao.module.system.api.remote.dto.LoginCheckDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 远遥登录")
@RestController
@RequestMapping("/remote/login")
@Validated
public class LoginController {
@Resource
private LoginService loginService;
@PostMapping("/check")
@Operation(summary = "测试通讯")
@PermitAll
public CommonResult<Boolean> checkCommunication(@Valid @RequestBody LoginCheckDTO loginCheckDTO) {
return success(loginService.checkCommunication(loginCheckDTO));
}
@PostMapping("/saveIpAndPort")
@Operation(summary = "保存IP和端口")
public CommonResult<Boolean> saveIpAndPort(@Valid @RequestBody LoginCheckDTO loginCheckDTO) {
loginService.saveIpAndPort(loginCheckDTO);
return success(true);
}
@PostMapping("/getIpAndPort")
@Operation(summary = "查询IP和端口")
@PermitAll
public CommonResult<LoginCheckDTO> getIpAndPort() {
return success(loginService.getIpAndPort());
}
}

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.remote.controller.admin.robot;
import cn.iocoder.yudao.module.remote.service.robot.RemoteRobotService;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Tag(name = "管理后台 - 远遥车辆")
@RestController
@RequestMapping("/remote/robot")
@Validated
public class RemoteRobotController {
@Autowired
private RemoteRobotService remoteRobotService;
}

View File

@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.remote.framework.security.config;
import cn.iocoder.cloud.module.remote.enums.ApiConstants;
import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
/**
* remote 模块的 Security 配置
*/
@Configuration(proxyBeanMethods = false, value = "remoteSecurityConfiguration")
public class SecurityConfiguration {
@Bean("RemoteAuthorizeRequestsCustomizer")
public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() {
return new AuthorizeRequestsCustomizer() {
@Override
public void customize(AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry registry) {
// TODO 芋艿这个每个项目都需要重复配置得捉摸有没通用的方案
// Swagger 接口文档
registry.requestMatchers("/v3/api-docs/**").permitAll()
.requestMatchers("/webjars/**").permitAll()
.requestMatchers("/swagger-ui").permitAll()
.requestMatchers("/swagger-ui/**").permitAll();
// Druid 监控
registry.requestMatchers("/druid/**").permitAll();
// Spring Boot Actuator 的安全配置
registry.requestMatchers("/actuator").permitAll()
.requestMatchers("/actuator/**").permitAll();
// RPC 服务的安全配置
registry.requestMatchers(ApiConstants.PREFIX + "/**").permitAll();
}
};
}
}

View File

@ -0,0 +1,11 @@
package cn.iocoder.yudao.module.remote.framework.system;
import cn.iocoder.yudao.module.system.api.remote.RemoteLoginApi;
import cn.iocoder.yudao.module.system.api.remote.RemoteRobotApi;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
@EnableFeignClients(clients = {RemoteLoginApi.class, RemoteRobotApi.class})
public class SystemConfiguration {
}

View File

@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.remote.service.login;
import cn.iocoder.yudao.module.system.api.remote.dto.LoginCheckDTO;
import javax.validation.Valid;
public interface LoginService {
Boolean checkCommunication(LoginCheckDTO loginCheckDTO);
/**
* 保存IP和端口
* @param loginCheckDTO
*/
void saveIpAndPort(LoginCheckDTO loginCheckDTO);
/**
* 查询默认IP和端口
* @return
*/
LoginCheckDTO getIpAndPort();
}

View File

@ -0,0 +1,76 @@
package cn.iocoder.yudao.module.remote.service.login;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.module.system.api.remote.RemoteLoginApi;
import cn.iocoder.yudao.module.system.api.remote.dto.LoginCheckDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {
private String checkUrl = "/admin-api/system/remote/controller-information/checkAddress";
@Resource
private RemoteLoginApi remoteLoginApi;
/**
* 测试通讯
*
* @param loginCheckDTO
* @return
*/
@Override
public Boolean checkCommunication(LoginCheckDTO loginCheckDTO) {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(5 * 1000);
RestTemplate restTemplate = new RestTemplate(factory);
String url = "http://" + loginCheckDTO.getSystemIp() + ":" + loginCheckDTO.getSystemPort() + checkUrl;
LinkedMultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.add("Tenant-Id", "1");
headers.add("Content-Type", "application/json");
Map<String, String> map = new HashMap<>();
map.put("systemIp", loginCheckDTO.getSystemIp());
HttpEntity<String> request = new HttpEntity<String>(JSONUtil.toJsonStr(map), headers);
ResponseEntity<String> response = null;
try {
response = restTemplate.postForEntity(url, request, String.class);
} catch (Exception e) {
}
return ObjectUtil.isNotEmpty(response) && loginCheckDTO.getSystemIp().equals(response.getBody());
}
/**
* 保存IP和端口
*
* @param loginCheckDTO
*/
@Override
public void saveIpAndPort(LoginCheckDTO loginCheckDTO) {
remoteLoginApi.saveIpAndPort(loginCheckDTO);
}
@Override
public LoginCheckDTO getIpAndPort() {
return remoteLoginApi.getIpAndPort();
}
}

View File

@ -0,0 +1,4 @@
package cn.iocoder.yudao.module.remote.service.robot;
public interface RemoteRobotService {
}

View File

@ -0,0 +1,10 @@
package cn.iocoder.yudao.module.remote.service.robot;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class RemoteRobotServiceImpl implements RemoteRobotService{
}

View File

@ -0,0 +1,54 @@
spring:
cloud:
nacos:
server-addr: 127.0.0.1:8848 # Nacos 服务器地址
username: # Nacos 账号
password: # Nacos 密码
discovery: # 【配置中心】配置项
namespace: dev # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
metadata:
version: 1.0.0 # 服务实例的版本号,可用于灰度发布
config: # 【注册中心】配置项
namespace: dev # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
# Lock4j 配置项
lock4j:
acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒
expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒
--- #################### 监控相关配置 ####################
# Actuator 监控端点的配置项
management:
endpoints:
web:
base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator
exposure:
include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
spring:
redis:
host: 127.0.0.1 # 地址
port: 6379 # 端口
database: 0 # 数据库索引
# password: 123456 # 密码,建议生产环境开启
boot:
admin:
# Spring Boot Admin Client 客户端的相关配置
client:
instance:
service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME]
# 日志文件配置
logging:
level:
# 配置自己写的 MyBatis Mapper 打印日志
cn.iocoder.yudao.module.system.dal.mysql: debug
cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper: INFO # 配置 SmsChannelMapper 的日志级别为 info
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿先禁用Spring Boot 3.X 存在部分错误的 WARN 提示
file:
name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径

View File

@ -0,0 +1,54 @@
spring:
cloud:
nacos:
server-addr: 127.0.0.1:8848 # Nacos 服务器地址
username: # Nacos 账号
password: # Nacos 密码
discovery: # 【配置中心】配置项
namespace: dev # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
metadata:
version: 1.0.0 # 服务实例的版本号,可用于灰度发布
config: # 【注册中心】配置项
namespace: dev # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
# Lock4j 配置项
lock4j:
acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒
expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒
--- #################### 监控相关配置 ####################
# Actuator 监控端点的配置项
management:
endpoints:
web:
base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator
exposure:
include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
spring:
redis:
host: 127.0.0.1 # 地址
port: 6379 # 端口
database: 0 # 数据库索引
# password: 123456 # 密码,建议生产环境开启
boot:
admin:
# Spring Boot Admin Client 客户端的相关配置
client:
instance:
service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME]
# 日志文件配置
logging:
level:
# 配置自己写的 MyBatis Mapper 打印日志
cn.iocoder.yudao.module.system.dal.mysql: debug
cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper: INFO # 配置 SmsChannelMapper 的日志级别为 info
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿先禁用Spring Boot 3.X 存在部分错误的 WARN 提示
file:
name: C:\system\install\log/${spring.application.name}.log

View File

@ -0,0 +1,34 @@
spring:
cloud:
nacos:
server-addr: 127.0.0.1:8848 # Nacos 服务器地址
username: # Nacos 账号
password: # Nacos 密码
discovery: # 【配置中心】配置项
namespace: dev # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
metadata:
version: 1.0.0 # 服务实例的版本号,可用于灰度发布
config: # 【注册中心】配置项
namespace: dev # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
# Lock4j 配置项
lock4j:
acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒
expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒
--- #################### 监控相关配置 ####################
# Actuator 监控端点的配置项
management:
endpoints:
web:
base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator
exposure:
include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
logging:
file:
name: D:/project/rcs/logs/${spring.application.name}.log

View File

@ -0,0 +1,105 @@
spring:
application:
name: remote-server
main:
allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。
allow-bean-definition-overriding: true # 允许 Bean 覆盖,例如说 Feign 等会存在重复定义的服务
profiles:
active: local
mvc:
pathmatch:
matching-strategy: ANT_PATH_MATCHER # 解决 SpringFox 与 SpringBoot 2.6.x 不兼容的问题,参见 SpringFoxHandlerProviderBeanPostProcessor 类
# Jackson 配置项
jackson:
serialization:
write-dates-as-timestamps: true # 设置 LocalDateTime 的格式,使用时间戳
write-date-timestamps-as-nanoseconds: false # 设置不使用 nanoseconds 的格式。例如说 1611460870.401,而是直接 1611460870401
write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳
fail-on-empty-beans: false # 允许序列化无属性的 Bean
server:
port: 48084
logging:
file:
name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径
springdoc:
api-docs:
enabled: true # 1. 是否开启 Swagger 接文档的元数据
path: /v3/api-docs
swagger-ui:
enabled: true # 2.1 是否开启 Swagger 文档的官方 UI 界面
path: /swagger-ui
default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档
knife4j:
enable: true # 2.2 是否开启 Swagger 文档的 Knife4j UI 界面
setting:
language: zh_cn
yudao:
info:
version: 1.0.0
base-package: cn.iocoder.yudao.module.remote
web:
admin-ui:
url: http://dashboard.yudao.iocoder.cn # Admin 管理后台 UI 的地址
xss:
enable: false
exclude-urls: # 如下 url仅仅是为了演示去掉配置也没关系
- ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求
swagger:
title: 管理后台
description: 提供管理员管理的所有功能
version: ${yudao.info.version}
tenant: # 多租户相关配置项
enable: true
ignore-urls:
- /admin-api/system/tenant/get-id-by-name # 基于名字获取租户,不许带租户编号
- /admin-api/system/tenant/get-by-website # 基于域名获取租户,不许带租户编号
- /admin-api/system/captcha/get-image # 获取图片验证码,和租户无关
- /admin-api/system/captcha/get # 获取图片验证码,和租户无关
- /admin-api/system/captcha/check # 校验图片验证码,和租户无关
- /admin-api/system/sms/callback/* # 短信回调接口,无法带上租户编号
- /rpc-api/system/tenant/valid # 防止递归。避免调用 /rpc-api/system/tenant/valid 接口时,又去触发 /rpc-api/system/tenant/valid 去校验
- /rpc-api/system/tenant/id-list # 获得租户列表的时候,无需传递租户编号
- /rpc-api/system/oauth2/token/check # 访问令牌校验时,无需传递租户编号;主要解决上传文件的场景,前端不会传递 tenant-id
ignore-tables:
- system_tenant
- system_tenant_package
- system_dict_data
- system_dict_type
- system_error_code
- system_menu
- system_sms_channel
- system_sms_template
- system_sms_log
- system_sensitive_word
- system_oauth2_client
- system_mail_account
- system_mail_template
- system_mail_log
- system_notify_template
ignore-caches:
- user_role_ids
- permission_menu_ids
- oauth_client
- notify_template
- mail_account
- mail_template
- sms_template
sms-code: # 短信验证码相关的配置项
expire-times: 10m
send-frequency: 1m
send-maximum-quantity-per-day: 10
begin-code: 9999 # 这里配置 9999 的原因是,测试方便。
end-code: 9999 # 这里配置 9999 的原因是,测试方便。
debug: false

View File

@ -0,0 +1,23 @@
--- #################### 注册中心相关配置 ####################
spring:
cloud:
nacos:
server-addr: 127.0.0.1:8848
discovery:
namespace: dev # 命名空间。这里使用 dev 开发环境
metadata:
version: 1.0.0 # 服务实例的版本号,可用于灰度发布
--- #################### 配置中心相关配置 ####################
spring:
cloud:
nacos:
# Nacos Config 配置项,对应 NacosConfigProperties 配置属性类
config:
server-addr: 127.0.0.1:8848 # Nacos 服务器地址
namespace: dev # 命名空间 dev 的ID不能直接使用 dev 名称。创建命名空间的时候需要指定ID为 dev这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name
file-extension: yaml # 使用的 Nacos 配置集的 dataId 的文件拓展名,同时也是 Nacos 配置集的配置格式,默认为 properties

View File

@ -0,0 +1,23 @@
--- #################### 注册中心相关配置 ####################
spring:
cloud:
nacos:
server-addr: 127.0.0.1:8848
discovery:
namespace: dev # 命名空间。这里使用 dev 开发环境
metadata:
version: 1.0.0 # 服务实例的版本号,可用于灰度发布
--- #################### 配置中心相关配置 ####################
spring:
cloud:
nacos:
# Nacos Config 配置项,对应 NacosConfigProperties 配置属性类
config:
server-addr: 127.0.0.1:8848 # Nacos 服务器地址
namespace: dev # 命名空间 dev 的ID不能直接使用 dev 名称。创建命名空间的时候需要指定ID为 dev这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name
file-extension: yaml # 使用的 Nacos 配置集的 dataId 的文件拓展名,同时也是 Nacos 配置集的配置格式,默认为 properties

View File

@ -0,0 +1,23 @@
--- #################### 注册中心相关配置 ####################
spring:
cloud:
nacos:
server-addr: 127.0.0.1:8848
discovery:
namespace: prod # 命名空间。这里使用 dev 开发环境
metadata:
version: 1.0.0 # 服务实例的版本号,可用于灰度发布
--- #################### 配置中心相关配置 ####################
spring:
cloud:
nacos:
# Nacos Config 配置项,对应 NacosConfigProperties 配置属性类
config:
server-addr: 127.0.0.1:8848 # Nacos 服务器地址
namespace: prod # 命名空间 dev 的ID不能直接使用 dev 名称。创建命名空间的时候需要指定ID为 dev这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name
file-extension: yaml # 使用的 Nacos 配置集的 dataId 的文件拓展名,同时也是 Nacos 配置集的配置格式,默认为 properties

View File

@ -0,0 +1,15 @@
spring:
application:
name: remote-server
profiles:
active: local #local
# active: prod
server:
port: 48084
# 日志文件配置。注意,如果 logging.file.name 不放在 bootstrap.yaml 配置文件,而是放在 application.yaml 中,会导致出现 LOG_FILE_IS_UNDEFINED 文件
logging:
file:
name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径

View File

@ -0,0 +1,76 @@
<configuration>
<!-- 引用 Spring Boot 的 logback 基础配置 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<!-- 变量 yudao.info.base-package基础业务包 -->
<springProperty scope="context" name="yudao.info.base-package" source="yudao.info.base-package"/>
<!-- 格式化输出:%d 表示日期,%X{tid} SkWalking 链路追踪编号,%thread 表示线程名,%-5level级别从左显示 5 个字符宽度,%msg日志消息%n是换行符 -->
<property name="PATTERN_DEFAULT" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} | %X{requestId} | %highlight(${LOG_LEVEL_PATTERN:-%5p} ${PID:- }) | %boldYellow(%thread [%tid]) %boldGreen(%-40.40logger{39}) | %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<!-- 控制台 Appender -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">     
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<pattern>${PATTERN_DEFAULT}</pattern>
</layout>
</encoder>
</appender>
<!-- 文件 Appender -->
<!-- 参考 Spring Boot 的 file-appender.xml 编写 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<pattern>${PATTERN_DEFAULT}</pattern>
</layout>
</encoder>
<!-- 日志文件名 -->
<file>${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 滚动后的日志文件名 -->
<fileNamePattern>${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}</fileNamePattern>
<!-- 启动服务时,是否清理历史日志,一般不建议清理 -->
<cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
<!-- 日志文件,到达多少容量,进行滚动 -->
<maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize>
<!-- 日志文件的总大小0 表示不限制 -->
<totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap>
<!-- 日志文件的保留天数 -->
<maxHistory>${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30}</maxHistory>
</rollingPolicy>
</appender>
<!-- 异步写入日志,提升性能 -->
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志。默认的,如果队列的 80% 已满,则会丢弃 TRACT、DEBUG、INFO 级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能。默认值为 256 -->
<queueSize>256</queueSize>
<appender-ref ref="FILE"/>
</appender>
<!-- SkyWalking GRPC 日志收集实现日志中心。注意SkyWalking 8.4.0 版本开始支持 -->
<appender name="GRPC" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<pattern>${PATTERN_DEFAULT}</pattern>
</layout>
</encoder>
</appender>
<!-- 本地环境 -->
<springProfile name="local">
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="GRPC"/> <!-- 本地环境下,如果不想接入 SkyWalking 日志服务,可以注释掉本行 -->
<appender-ref ref="ASYNC"/> <!-- 本地环境下,如果不想打印日志,可以注释掉本行 -->
</root>
</springProfile>
<!-- 其它环境 -->
<springProfile name="dev,test,stage,prod,default">
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ASYNC"/>
<appender-ref ref="GRPC"/>
</root>
</springProfile>
</configuration>

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.system.api.remote;
import cn.iocoder.yudao.module.system.api.remote.dto.LoginCheckDTO;
import cn.iocoder.yudao.module.system.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿fallbackFactory =
@Tag(name = "RPC 服务 - 远遥登录相关的服务调用")
public interface RemoteLoginApi {
String PREFIX = ApiConstants.PREFIX + "/remote";
@PostMapping(PREFIX + "/saveIpAndPort")
@Operation(summary = "保存IP和端口")
void saveIpAndPort(@RequestBody LoginCheckDTO loginCheckDTO);
@PostMapping(PREFIX + "/getIpAndPort")
@Operation(summary = "查询默认IP和端口")
LoginCheckDTO getIpAndPort();
}

View File

@ -0,0 +1,13 @@
package cn.iocoder.yudao.module.system.api.remote;
import cn.iocoder.yudao.module.system.enums.ApiConstants;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.cloud.openfeign.FeignClient;
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿fallbackFactory =
@Tag(name = "RPC 服务 - 远遥车辆相关")
public interface RemoteRobotApi {
String PREFIX = ApiConstants.PREFIX + "/remote";
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.system.api.remote.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
@Data
public class LoginCheckDTO {
@Schema(description = "通讯地址")
@NotEmpty(message = "通讯地址不能为空")
@Size(max = 20, message = "通讯地址长度不符合要求")
private String systemIp;
@Schema(description = "通讯端口")
@NotEmpty(message = "端口不能为空")
@Size(max = 10, message = "端口长度不符合要求")
private String systemPort;
}

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.system.api.remote.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
public class RemoteRobotDTO {
@Schema(description = "楼层")
private Integer floor;
@Schema(description = "区域")
private String area;
@Schema(description = "车辆明细")
private List<RemoteRobotDetailDTO> robotList;
}

View File

@ -0,0 +1,13 @@
package cn.iocoder.yudao.module.system.api.remote.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class RemoteRobotDetailDTO {
@Schema(description = "AGV编号")
private String robotNo;
}

View File

@ -33,7 +33,7 @@ public class RobotCompleteTaskDTO {
/**
* 解决方法
*/
private String solution;
private String solution = "";
/**
* 子任务
*/

View File

@ -187,8 +187,9 @@ public interface ErrorCodeConstants {
// ========== 车辆信息 1-002-034-000 ==========
ErrorCode ROBOT_INFORMATION_NOT_EXISTS = new ErrorCode(1-002-034-001, "车辆信息不存在");
ErrorCode ROBOT_MAC_ADDRESS_EXISTS = new ErrorCode(1-002-034-002, "MAC地址重复");
ErrorCode ROBOT_ROBOT_NO_EXISTS = new ErrorCode(1-002-034-003, "机器人编号重复");
ErrorCode ROBOT_LAST_TASK_NO_EXISTS = new ErrorCode(1-002-034-004, "机器人前一个任务不存在或已经完成");
ErrorCode ROBOT_ROBOT_NO_EXISTS = new ErrorCode(1-002-034-003, "车辆编号重复");
ErrorCode ROBOT_ROBOT_IP_EXISTS = new ErrorCode(1-002-034-004, "车辆IP重复");
ErrorCode ROBOT_LAST_TASK_NO_EXISTS = new ErrorCode(1-002-034-004, "车辆前一个任务不存在或已经完成");
ErrorCode ROBOT_LAST_TASK_DELETE = new ErrorCode(1-002-034-005, "超过限制的时间,无法继续执行前一个任务");
ErrorCode ROBOT_NOT_FOUND_WAIT_ITEM = new ErrorCode(1-002-034-006, "没有空闲的停车点");
ErrorCode ROBOT_NOT_FOUND_FREE_CHARGING_STATION = new ErrorCode(1-002-034-007, "没有空闲的充电桩");
@ -196,7 +197,7 @@ public interface ErrorCodeConstants {
ErrorCode ROBOT_REJECTION = new ErrorCode(1-002-034-011, "车辆已锁定");
// ========== 机器人任务主表 1-002-035-000 ==========
ErrorCode TASK_NOT_EXISTS = new ErrorCode(1-002-035-001, "机器人任务主表不存在");
ErrorCode TASK_NOT_EXISTS = new ErrorCode(1-002-035-001, "车辆任务主表不存在");
ErrorCode TASK_DATA_NOT_FULL = new ErrorCode(1-002-035-002, "任务数据不完整");
ErrorCode TASK_CYCLE_NOT_OPEN = new ErrorCode(1-002-035-003, "循环任务的配置未开启!");
ErrorCode TASK_ONLY_CHOOSE_LOCATION = new ErrorCode(1-002-035-004, "搬空任务只能选择线库或者区域");
@ -217,7 +218,7 @@ public interface ErrorCodeConstants {
ErrorCode ROBOT_DO_TASK_FAIL = new ErrorCode(1-002-035-112, "车机反馈不能接任务");
// ========== 机器人任务明细 1-002-036-000 ==========
ErrorCode TASK_DETAIL_NOT_EXISTS = new ErrorCode(1-002-036-001, "机器人任务明细不存在");
ErrorCode TASK_DETAIL_NOT_EXISTS = new ErrorCode(1-002-036-001, "车辆任务明细不存在");
ErrorCode TASK_DETAIL_CHANGE_ROBOT = new ErrorCode(1-002-036-002, "非新单据不能修改车辆");
// ========== 机器人任务明细 1-002-037-000 ==========
@ -233,16 +234,16 @@ public interface ErrorCodeConstants {
ErrorCode THE_LINE_LIBRARY_POINTS_ARE_NOT_LOCATED_IN_THE_SAME_AREA = new ErrorCode(1_002_038_006, "线库点位不在同一区域内");
ErrorCode THERE_ARE_ALREADY_STORAGE_LOCATIONS_IN_OTHER_LINE_WAREHOUSES = new ErrorCode(1_002_038_007, "已有库位在其他线库内");
ErrorCode THERE_ARE_ALREADY_STORAGE_LOCATIONS_IN_OTHER_STORAGE_AREAS = new ErrorCode(1_002_038_008, "已有库位在其它区域内");
ErrorCode MAP_DOES_NOT_EXIST_AGV = new ErrorCode(1_002_038_009, "此楼层区域不存在机器人");
ErrorCode MAP_DOES_NOT_EXIST_AGV = new ErrorCode(1_002_038_009, "此楼层区域不存在车辆需要暂停或恢复");
// ========== 机器人自动移库 1-002-039-000 ==========
ErrorCode TASK_AUTO_MOVE_NOT_EXISTS = new ErrorCode(1_002_039_001, "机器人自动移库不存在");
ErrorCode TASK_AUTO_MOVE_NOT_EXISTS = new ErrorCode(1_002_039_001, "车辆自动移库不存在");
// ========== 机器人告警信息 1_002_040_001==========
ErrorCode WARN_MSG_NOT_EXISTS = new ErrorCode(1_002_040_001, "机器人告警信息不存在");
ErrorCode WARN_MSG_NOT_EXISTS = new ErrorCode(1_002_040_001, "车辆告警信息不存在");
// ========== 机器人告警码值映射 1_002_041_001 ==========
ErrorCode WARN_CODE_MAPPING_NOT_EXISTS = new ErrorCode(1_002_041_001, "机器人告警码值映射不存在");
ErrorCode WARN_CODE_MAPPING_NOT_EXISTS = new ErrorCode(1_002_041_001, "车辆告警码值映射不存在");
// ========== 通用配置 1_002_042_001 ==========
ErrorCode CONFIG_NOT_EXISTS = new ErrorCode(1_002_042_001 , "通用配置不存在");
@ -263,9 +264,18 @@ public interface ErrorCodeConstants {
// ========== 车辆前往等待点记录 1_002_048_001 ==========
ErrorCode MOVE_TO_WAIT_NOT_EXISTS = new ErrorCode(1_002_048_001, "车辆前往等待点记录不存在");
// ========== 机器人动作记录 1_002_049_001==========
ErrorCode OPERATION_LOG_NOT_EXISTS = new ErrorCode(1_002_049_001, "机器人动作记录不存在");
ErrorCode OPERATION_LOG_NOT_EXISTS = new ErrorCode(1_002_049_001, "车辆动作记录不存在");
// ========== 用户操作记录 1_002_050_001 ==========
ErrorCode USER_OPERATION_LOG_NOT_EXISTS = new ErrorCode(1_002_050_001, "用户操作记录不存在");
// ========== 车辆衔接任务 1_002_051_001 ==========
ErrorCode TASK_PROCEED_NOT_EXISTS = new ErrorCode(1_002_051_001, "车辆衔接任务不存在");
// ========== 车辆(地图)急停记录 1_002_052_001 ==========
ErrorCode MAP_STOP_NOT_EXISTS = new ErrorCode(1_002_052_001, "车辆(地图)急停记录不存在");
// ========== 远遥设备信息 1_002_053_001 ==========
ErrorCode CONTROLLER_INFORMATION_NOT_EXISTS = new ErrorCode(1_002_053_001, "远遥设备信息不存在");
// ========== 车辆摄像头信息 1_002_054_001 ==========
ErrorCode CAMERA_NOT_EXISTS = new ErrorCode(1_002_054_001, "车辆摄像头信息不存在");
ErrorCode CAMERA_IP_EXIST = new ErrorCode(1_002_054_001, "车辆摄像头IP已经存在");
ErrorCode CAMERA_IP_REPEAT = new ErrorCode(1_002_054_001, "存在重复的摄像头IP");
}

View File

@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.system.api.remote;
import cn.iocoder.yudao.module.system.api.remote.dto.LoginCheckDTO;
import cn.iocoder.yudao.module.system.service.remote.RemoteControllerInformationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Slf4j
@RestController // 提供 RESTful API 接口 Feign 调用
@Validated
public class RemoteLoginApiImpl implements RemoteLoginApi{
@Resource
private RemoteControllerInformationService controllerInformationService;
/**
* 保存IP和端口
* @param loginCheckDTO
*/
@Override
public void saveIpAndPort(LoginCheckDTO loginCheckDTO) {
controllerInformationService.saveIpAndPort(loginCheckDTO);
}
/**
* 查询远遥默认IP和端口
* @return
*/
@Override
public LoginCheckDTO getIpAndPort() {
return controllerInformationService.getDefaultIpAndPort();
}
}

View File

@ -120,7 +120,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
String robotDoingActionKey = RobotTaskChcheConstant.ROBOT_QUERY_DOING_ACTION + robotCompleteTaskDTO.getMac();
if (ObjectUtil.isEmpty(robotCompleteTaskDTO.getOrderId())) {
log.info("没有任务id :{}",JSON.toJSONString(robotCompleteTaskDTO));
log.info("没有任务id :{}", JSON.toJSONString(robotCompleteTaskDTO));
return;
}
@ -146,7 +146,6 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
/**
* 上一条明细设置为完成
*
* @param mac
* @return
*/
public RobotTaskDetailActionLogDO setLastLogDone(Long orderId) {
@ -229,11 +228,14 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
} else if (PathTaskTypeEnum.TAKE_RELEASE.getType().equals(robotCompleteTaskDTO.getOrderType())) {
RobotTaskDetailDO robotTaskDetailDO = robotTaskDetailMapper.selectById(robotCompleteTaskDTO.getOrderId());
if (RobotTaskStageEnum.TAKEING.getType().equals(robotTaskDetailDO.getTaskStage())) {
if (CommandTypeEnum.WORK_PICK_UP_GOODS.getType().equals(robotCompleteTaskDTO.getCommandStatus().getCommandType())) {
log.info("告诉路径规划任务完成 :{}, 状态: {}", robotCompleteTaskDTO.getOrderId(), PathIsReachEnum.END_WORK.getType());
pathPlanningService.updateBehavior(String.valueOf(robotCompleteTaskDTO.getOrderId()), robotTaskDetailDO.getRobotNo()
, "", PathIsReachEnum.END_WORK.getType());
} else if (RobotTaskStageEnum.RELEASEING.getType().equals(robotTaskDetailDO.getTaskStage())) {
robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.TAKEING.getType());
robotTaskDetailMapper.updateById(robotTaskDetailDO);
return;
} else if (CommandTypeEnum.WORK_DROP_OFF_GOODS.getType().equals(robotCompleteTaskDTO.getCommandStatus().getCommandType())) {
taskDone(robotCompleteTaskDTO);
}
} else if (PathTaskTypeEnum.MOVE_TO_WAIT.getType().equals(robotCompleteTaskDTO.getOrderType())) {
@ -276,6 +278,20 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
// taskService.closeTaskDetail(robotCompleteTaskDTO.getOrderId().toString(),robotCompleteTaskDTO.getMac());
String robotNo = robotInformationService.getRobotNoByMac(robotCompleteTaskDTO.getMac());
String msg = "";
if (PathTaskTypeEnum.TAKE_RELEASE.getType().equals(robotCompleteTaskDTO.getOrderType())
|| PathTaskTypeEnum.TAKE.getType().equals(robotCompleteTaskDTO.getOrderType())) {
RobotTaskDetailDO robotTaskDetailDO = robotTaskDetailMapper.selectById(robotCompleteTaskDTO.getOrderId());
if (RobotTaskStageEnum.GO_TAKE.getType().equals(robotTaskDetailDO.getTaskStage())
|| RobotTaskStageEnum.UN_START.getType().equals(robotTaskDetailDO.getTaskStage())) {
robotTaskDetailDO.setTaskStatus(RobotTaskDetailStatusEnum.NEW.getType());
robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.UN_START.getType());
robotTaskDetailDO.setRobotNo("");
robotTaskDetailMapper.updateById(robotTaskDetailDO);
String taskNo = taskDetailService.getTaskNoByDetailId(robotCompleteTaskDTO.getOrderId());
msg = robotNo + "_" + "车辆发生异常,重新分配其他车辆执行此任务" + taskNo;
}
}
//先不释放库位状态
/*if (RobotTaksOrderTypeEnum.TASK.getType().equals(robotCompleteTaskDTO.getOrderType())) {
RobotTaskDetailDO robotTaskDetailDO = closeTaskDetail(robotCompleteTaskDTO.getOrderId());
@ -306,17 +322,22 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
}*/
String solve = "";
String taskNo = "";
if (!PathTaskTypeEnum.MOVE_TO_WAIT.getType().equals(robotCompleteTaskDTO.getOrderType())
&& !PathTaskTypeEnum.AUTO_CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())) {
String taskNo = taskDetailService.getTaskNoByDetailId(robotCompleteTaskDTO.getOrderId());
&& !PathTaskTypeEnum.AUTO_CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())
&& ObjectUtil.isEmpty(msg)) {
taskNo = taskDetailService.getTaskNoByDetailId(robotCompleteTaskDTO.getOrderId());
solve = " 并且到任务列表关闭任务 " + taskNo;
taskDetailService.setTaskDetailError(robotCompleteTaskDTO.getOrderId());
}
msg = ObjectUtil.isEmpty(msg) ? robotNo + "_" + robotCompleteTaskDTO.getMessage() : msg;
RobotWarnMsgDO warnMsg = RobotWarnMsgDO.builder().warnLevel(4)
.warnCode(robotCompleteTaskDTO.getStatusCode())
.robotNo(robotNo)
.warnType(RobotWarnType.ROBOT_WARN.getType())
.warnMsg(robotNo + "_" + robotCompleteTaskDTO.getMessage())
.warnMsg(msg)
.warnSolve(robotCompleteTaskDTO.getSolution() + solve)
.build();
warnMsgMapper.insert(warnMsg);
@ -545,7 +566,8 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
@Override
public void robotDoneTask(RobotCompleteTaskDTO robotCompleteTaskDTO) {
taskExecutor.execute(() -> {
String requestId = UUID.randomUUID().toString().replace("-","");;
String requestId = UUID.randomUUID().toString().replace("-", "");
;
MDC.put(CommonConstant.REQUEST_ID, requestId);
try {
doRobotDoneTask(robotCompleteTaskDTO);

View File

@ -18,10 +18,10 @@ public class SystemApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) {
try {
/*try {
toolsService.simulationPose();
} catch (Exception e) {
log.error("同步仿真的点位信息失败 :{}",e.getMessage());
}
}*/
}
}

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.controller.admin.positionmap;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.dto.PositionMapDTO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapDO;
import cn.iocoder.yudao.module.system.service.positionmap.PositionMapService;
@ -54,6 +55,7 @@ public class PositionMapController {
@GetMapping("/emergencyStopOrRecovery")
@Operation(summary = "一键急停or一键恢复地图上所有AGV")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@Parameter(name = "type", description = "类型(1:停止, 0:恢复)", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:position-map:emergencyStopOrRecovery')")
public CommonResult<Boolean> emergencyStopOrRecovery(@RequestParam("id") Long id, @RequestParam("type") Integer type) {
positionMapService.emergencyStopOrRecovery(id,type);
@ -63,10 +65,11 @@ public class PositionMapController {
@GetMapping("/getMap")
@Operation(summary = "获得仓库点位地图Map")
@PreAuthorize("@ss.hasPermission('system:position-map:query')")
public CommonResult<Map<Integer, List<PositionMapDO>>> getPositionMapList() {
List<PositionMapDO> list = positionMapService.list();
Map<Integer, List<PositionMapDO>> map = list.stream().collect(Collectors.groupingBy(PositionMapDO::getFloor));
return success(map);
public CommonResult<Map<Integer, List<PositionMapDTO>>> getPositionMapList() {
Map<Integer, List<PositionMapDTO>> result = positionMapService.getPositionMapList();
/*List<PositionMapDO> list = positionMapService.list();
Map<Integer, List<PositionMapDO>> map = list.stream().collect(Collectors.groupingBy(PositionMapDO::getFloor));*/
return success(result);
}
@PostMapping("/upload")

View File

@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.system.controller.admin.positionmap.dto;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 仓库点位地图新增/修改 Request VO")
@Data
public class PositionMapDTO {
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2349")
private Long id;
@Schema(description = "楼层")
private Integer floor;
@Schema(description = "区域")
private String area;
@Schema(description = "AGV地图ymlJson信息")
private String yamlJson;
@Schema(description = "AGV地图图片路径")
private String pngUrl;
@Schema(description = "AGV地图yaml路径")
private String yamlUrl;
@Schema(description = "地图暂停/恢复 (0:未暂停, 1:暂停)")
private Integer stopOrRestore = 0;
}

View File

@ -0,0 +1,108 @@
package cn.iocoder.yudao.module.system.controller.admin.remote;
import cn.iocoder.yudao.module.system.controller.admin.remote.vo.RemoteControllerInformationPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.remote.vo.RemoteControllerInformationRespVO;
import cn.iocoder.yudao.module.system.controller.admin.remote.vo.RemoteControllerInformationSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.remote.RemoteControllerInformationDO;
import cn.iocoder.yudao.module.system.service.remote.RemoteControllerInformationService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.annotation.security.PermitAll;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
@Tag(name = "管理后台 - 远遥设备信息")
@RestController
@RequestMapping("/system/remote/controller-information") //不能修改/删除
@Validated
public class RemoteControllerInformationController {
@Resource
private RemoteControllerInformationService controllerInformationService;
@PostMapping("/create")
@Operation(summary = "创建远遥设备信息")
@PreAuthorize("@ss.hasPermission('remote:controller-information:create')")
public CommonResult<Long> createControllerInformation(@Valid @RequestBody RemoteControllerInformationSaveReqVO createReqVO) {
return success(controllerInformationService.createControllerInformation(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新远遥设备信息")
@PreAuthorize("@ss.hasPermission('remote:controller-information:update')")
public CommonResult<Boolean> updateControllerInformation(@Valid @RequestBody RemoteControllerInformationSaveReqVO updateReqVO) {
controllerInformationService.updateControllerInformation(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除远遥设备信息")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('remote:controller-information:delete')")
public CommonResult<Boolean> deleteControllerInformation(@RequestParam("id") Long id) {
controllerInformationService.deleteControllerInformation(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得远遥设备信息")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('remote:controller-information:query')")
public CommonResult<RemoteControllerInformationRespVO> getControllerInformation(@RequestParam("id") Long id) {
RemoteControllerInformationDO controllerInformation = controllerInformationService.getControllerInformation(id);
return success(BeanUtils.toBean(controllerInformation, RemoteControllerInformationRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得远遥设备信息分页")
@PreAuthorize("@ss.hasPermission('remote:controller-information:query')")
public CommonResult<PageResult<RemoteControllerInformationRespVO>> getControllerInformationPage(@Valid RemoteControllerInformationPageReqVO pageReqVO) {
PageResult<RemoteControllerInformationDO> pageResult = controllerInformationService.getControllerInformationPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, RemoteControllerInformationRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出远遥设备信息 Excel")
@PreAuthorize("@ss.hasPermission('remote:controller-information:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportControllerInformationExcel(@Valid RemoteControllerInformationPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<RemoteControllerInformationDO> list = controllerInformationService.getControllerInformationPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "远遥设备信息.xls", "数据", RemoteControllerInformationRespVO.class,
BeanUtils.toBean(list, RemoteControllerInformationRespVO.class));
}
/**
* 不能修改/删除
* @return
*/
@PostMapping("/checkAddress")
@Operation(summary = "校验远遥的地址")
@PermitAll
public String checkAddress(@RequestBody RemoteControllerInformationSaveReqVO createReqVO) {
return createReqVO.getSystemIp();
}
}

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.system.controller.admin.remote.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 远遥设备信息分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class RemoteControllerInformationPageReqVO extends PageParam {
@Schema(description = "远遥的设备IP")
private String remoteIp;
@Schema(description = "AGV编号")
private String robotNo;
@Schema(description = "远遥模式(0:自动模式, 1:手动模式, 2:自由模式)")
private Integer remoteMode;
@Schema(description = "协控(0:关闭协控, 1:开启协控)")
private Integer collaborativeControl;
@Schema(description = "远遥的其他信息")
private String remoteMsg;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "服务IP")
private String systemIp;
@Schema(description = "服务端口")
private String systemPort;
}

View File

@ -0,0 +1,48 @@
package cn.iocoder.yudao.module.system.controller.admin.remote.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - 远遥设备信息 Response VO")
@Data
@ExcelIgnoreUnannotated
public class RemoteControllerInformationRespVO {
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "26526")
@ExcelProperty("主键ID")
private Long id;
@Schema(description = "远遥的设备IP")
@ExcelProperty("远遥的设备IP")
private String remoteIp;
@Schema(description = "AGV编号")
@ExcelProperty("AGV编号")
private String robotNo;
@Schema(description = "远遥模式(0:自动模式, 1:手动模式, 2:自由模式)")
@ExcelProperty("远遥模式(0:自动模式, 1:手动模式, 2:自由模式)")
private Integer remoteMode;
@Schema(description = "协控(0:关闭协控, 1:开启协控)")
@ExcelProperty("协控(0:关闭协控, 1:开启协控)")
private Integer collaborativeControl;
@Schema(description = "远遥的其他信息")
@ExcelProperty("远遥的其他信息")
private String remoteMsg;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
@Schema(description = "服务IP")
private String systemIp;
@Schema(description = "服务端口")
private String systemPort;
}

View File

@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.system.controller.admin.remote.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
@Schema(description = "管理后台 - 远遥设备信息新增/修改 Request VO")
@Data
public class RemoteControllerInformationSaveReqVO {
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "26526")
private Long id;
@Schema(description = "远遥的设备IP")
private String remoteIp;
@Schema(description = "AGV编号")
private String robotNo;
@Schema(description = "远遥模式(0:自动模式, 1:手动模式, 2:自由模式)")
private Integer remoteMode;
@Schema(description = "协控(0:关闭协控, 1:开启协控)")
private Integer collaborativeControl;
@Schema(description = "远遥的其他信息")
private String remoteMsg;
@Schema(description = "服务IP")
private String systemIp;
@Schema(description = "服务端口")
private String systemPort;
}

View File

@ -0,0 +1,93 @@
package cn.iocoder.yudao.module.system.controller.admin.robot;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraRespVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotCameraDO;
import cn.iocoder.yudao.module.system.service.robot.camera.RobotCameraService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 车辆摄像头信息")
@RestController
@RequestMapping("/robot/camera")
@Validated
public class RobotCameraController {
@Resource
private RobotCameraService cameraService;
@PostMapping("/create")
@Operation(summary = "创建车辆摄像头信息")
@PreAuthorize("@ss.hasPermission('robot:camera:create')")
public CommonResult<Long> createCamera(@Valid @RequestBody RobotCameraSaveReqVO createReqVO) {
return success(cameraService.createCamera(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新车辆摄像头信息")
@PreAuthorize("@ss.hasPermission('robot:camera:update')")
public CommonResult<Boolean> updateCamera(@Valid @RequestBody RobotCameraSaveReqVO updateReqVO) {
cameraService.updateCamera(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除车辆摄像头信息")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('robot:camera:delete')")
public CommonResult<Boolean> deleteCamera(@RequestParam("id") Long id) {
cameraService.deleteCamera(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得车辆摄像头信息")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('robot:camera:query')")
public CommonResult<RobotCameraRespVO> getCamera(@RequestParam("id") Long id) {
RobotCameraDO camera = cameraService.getCamera(id);
return success(BeanUtils.toBean(camera, RobotCameraRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得车辆摄像头信息分页")
@PreAuthorize("@ss.hasPermission('robot:camera:query')")
public CommonResult<PageResult<RobotCameraRespVO>> getCameraPage(@Valid RobotCameraPageReqVO pageReqVO) {
PageResult<RobotCameraDO> pageResult = cameraService.getCameraPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, RobotCameraRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出车辆摄像头信息 Excel")
@PreAuthorize("@ss.hasPermission('robot:camera:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportCameraExcel(@Valid RobotCameraPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<RobotCameraDO> list = cameraService.getCameraPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "车辆摄像头信息.xls", "数据", RobotCameraRespVO.class,
BeanUtils.toBean(list, RobotCameraRespVO.class));
}
}

View File

@ -31,7 +31,7 @@ import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
@Tag(name = "管理后台 - 车辆充电记录")
@RestController
@RequestMapping("/robot/charge-log")
@RequestMapping("/system/robot/charge-log")
@Validated
public class RobotChargeLogController {

View File

@ -0,0 +1,105 @@
package cn.iocoder.yudao.module.system.controller.admin.robot;
import cn.iocoder.yudao.module.system.controller.admin.robot.mapstop.RobotMapStopPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.mapstop.RobotMapStopRespVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.mapstop.RobotMapStopSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotMapStopDO;
import cn.iocoder.yudao.module.system.service.robot.mapstop.RobotMapStopService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
@Tag(name = "管理后台 - 车辆(地图)急停记录")
@RestController
@RequestMapping("/system/robot/map-stop")
@Validated
public class RobotMapStopController {
@Resource
private RobotMapStopService mapStopService;
@PostMapping("/create")
@Operation(summary = "创建车辆(地图)急停记录")
@PreAuthorize("@ss.hasPermission('robot:map-stop:create')")
public CommonResult<Long> createMapStop(@Valid @RequestBody RobotMapStopSaveReqVO createReqVO) {
return success(mapStopService.createMapStop(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新车辆(地图)急停记录")
@PreAuthorize("@ss.hasPermission('robot:map-stop:update')")
public CommonResult<Boolean> updateMapStop(@Valid @RequestBody RobotMapStopSaveReqVO updateReqVO) {
mapStopService.updateMapStop(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除车辆(地图)急停记录")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('robot:map-stop:delete')")
public CommonResult<Boolean> deleteMapStop(@RequestParam("id") Long id) {
mapStopService.deleteMapStop(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得车辆(地图)急停记录")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('robot:map-stop:query')")
public CommonResult<RobotMapStopRespVO> getMapStop(@RequestParam("id") Long id) {
RobotMapStopDO mapStop = mapStopService.getMapStop(id);
return success(BeanUtils.toBean(mapStop, RobotMapStopRespVO.class));
}
@GetMapping("/getByMapId")
@Operation(summary = "根据地图id获取暂停的地图")
@Parameter(name = "id", description = "地图id", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('robot:map-stop:getByMapId')")
public CommonResult<List<RobotMapStopDO>> getByMapId(@RequestParam("id") Long id) {
List<RobotMapStopDO> mapStop = mapStopService.getByMapId(id);
return success(mapStop);
}
@GetMapping("/page")
@Operation(summary = "获得车辆(地图)急停记录分页")
@PreAuthorize("@ss.hasPermission('robot:map-stop:query')")
public CommonResult<PageResult<RobotMapStopRespVO>> getMapStopPage(@Valid RobotMapStopPageReqVO pageReqVO) {
PageResult<RobotMapStopDO> pageResult = mapStopService.getMapStopPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, RobotMapStopRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出车辆(地图)急停记录 Excel")
@PreAuthorize("@ss.hasPermission('robot:map-stop:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportMapStopExcel(@Valid RobotMapStopPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<RobotMapStopDO> list = mapStopService.getMapStopPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "车辆(地图)急停记录.xls", "数据", RobotMapStopRespVO.class,
BeanUtils.toBean(list, RobotMapStopRespVO.class));
}
}

View File

@ -0,0 +1,32 @@
package cn.iocoder.yudao.module.system.controller.admin.robot.camera;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Schema(description = "管理后台 - 车辆摄像头信息新增/修改 Request VO")
@Data
public class RobotCameraAddVO {
@Schema(description = "摄像头位置(0:上, 1:左, 2:右, 3:下, 4:后)")
@NotNull(message = "请选择摄像头位置")
private Integer cameraPosition;
@Schema(description = "摄像头IP--长度20")
@Size(min = 0,max = 20 ,message = "摄像头IP长度超过限制")
private String cameraIp;
@Schema(description = "摄像头端口--长度10")
@Size(min = 0,max = 10 ,message = "摄像头端口长度超过限制")
private String cameraPort;
@Schema(description = "摄像头账号--长度30", example = "24863")
@Size(min = 0,max = 30 ,message = "摄像头账号长度超过限制")
private String cameraAccount;
@Schema(description = "摄像头密码--长度40")
@Size(min = 0,max = 40 ,message = "摄像头密码长度超过限制")
private String cameraPassword;
}

View File

@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.system.controller.admin.robot.camera;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 车辆摄像头信息分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class RobotCameraPageReqVO extends PageParam {
@Schema(description = "AGV编号")
private String robotNo;
@Schema(description = "摄像头位置(0:上, 1:左, 2:右, 3:下, 4:后)")
private Integer cameraPosition;
@Schema(description = "摄像头IP")
private String cameraIp;
@Schema(description = "摄像头端口")
private String cameraPort;
@Schema(description = "摄像头账号", example = "24863")
private String cameraAccount;
@Schema(description = "摄像头密码")
private String cameraPassword;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,47 @@
package cn.iocoder.yudao.module.system.controller.admin.robot.camera;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - 车辆摄像头信息 Response VO")
@Data
@ExcelIgnoreUnannotated
public class RobotCameraRespVO {
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30856")
@ExcelProperty("主键ID")
private Long id;
@Schema(description = "AGV编号")
@ExcelProperty("AGV编号")
private String robotNo;
@Schema(description = "摄像头位置(0:上, 1:左, 2:右, 3:下, 4:后)")
@ExcelProperty("摄像头位置(0:上, 1:左, 2:右, 3:下, 4:后)")
private Integer cameraPosition;
@Schema(description = "摄像头IP")
@ExcelProperty("摄像头IP")
private String cameraIp;
@Schema(description = "摄像头端口")
@ExcelProperty("摄像头端口")
private String cameraPort;
@Schema(description = "摄像头账号", example = "24863")
@ExcelProperty("摄像头账号")
private String cameraAccount;
@Schema(description = "摄像头密码")
@ExcelProperty("摄像头密码")
private String cameraPassword;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.system.controller.admin.robot.camera;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
@Schema(description = "管理后台 - 车辆摄像头信息新增/修改 Request VO")
@Data
public class RobotCameraSaveReqVO {
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30856")
private Long id;
@Schema(description = "AGV编号")
private String robotNo;
@Schema(description = "摄像头位置(0:上, 1:左, 2:右, 3:下, 4:后)")
private Integer cameraPosition;
@Schema(description = "摄像头IP")
private String cameraIp;
@Schema(description = "摄像头端口")
private String cameraPort;
@Schema(description = "摄像头账号", example = "24863")
private String cameraAccount;
@Schema(description = "摄像头密码")
private String cameraPassword;
}

View File

@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.system.controller.admin.robot.mapstop;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 车辆(地图)急停记录分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class RobotMapStopPageReqVO extends PageParam {
@Schema(description = "急停仓库点位地图表id", example = "20550")
private Long positionMapId;
@Schema(description = "急停的AGV编号")
private String robotNo;
@Schema(description = "类型0地图、1车辆", example = "2")
private Integer stopType;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.system.controller.admin.robot.mapstop;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - 车辆(地图)急停记录 Response VO")
@Data
@ExcelIgnoreUnannotated
public class RobotMapStopRespVO {
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1220")
@ExcelProperty("主键ID")
private Long id;
@Schema(description = "急停仓库点位地图表id", example = "20550")
@ExcelProperty("急停仓库点位地图表id")
private Long positionMapId;
@Schema(description = "急停的AGV编号")
@ExcelProperty("急停的AGV编号")
private String robotNo;
@Schema(description = "类型0地图、1车辆", example = "2")
@ExcelProperty("类型0地图、1车辆")
private Integer stopType;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.system.controller.admin.robot.mapstop;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
@Schema(description = "管理后台 - 车辆(地图)急停记录新增/修改 Request VO")
@Data
public class RobotMapStopSaveReqVO {
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1220")
private Long id;
@Schema(description = "急停仓库点位地图表id", example = "20550")
private Long positionMapId;
@Schema(description = "急停的AGV编号")
private String robotNo;
@Schema(description = "类型0地图、1车辆", example = "2")
private Integer stopType;
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.system.controller.admin.robot.vo;
import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraAddVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
@ -7,6 +8,7 @@ import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.List;
import java.util.Set;
@Schema(description = "管理后台 - 车辆信息新增/修改 Request VO")
@ -58,6 +60,9 @@ public class RobotInformationSaveReqVO {
private String robotIp;
@Schema(description = "车辆端口")
@Range(min = 0, max = 6, message = "车辆端口长度超过限制")
@Range(min = 0, max = 999999, message = "车辆端口长度超过限制")
private Long robotPort;
@Schema(description = "摄像头相关的配置")
private List<RobotCameraAddVO> cameraAddVOList;
}

View File

@ -42,4 +42,7 @@ public class RobotModelPageReqVO extends PageParam {
@Schema(description = "中心到车尾距离(单位米)")
private String robotCenterTail;
@Schema(description = "转弯半径(单位米)")
private String robotTurningRadius;
}

View File

@ -44,4 +44,6 @@ public class RobotModelRespVO {
@Schema(description = "中心到车尾距离(单位米)")
private String robotCenterTail;
@Schema(description = "转弯半径(单位米)")
private String robotTurningRadius;
}

View File

@ -34,4 +34,6 @@ public class RobotModelSaveReqVO {
@Schema(description = "中心到车尾距离(单位米)")
private String robotCenterTail;
@Schema(description = "转弯半径(单位米)")
private String robotTurningRadius;
}

View File

@ -93,4 +93,7 @@ public class RobotTaskDetailPageReqVO extends PageParam {
@Schema(description = "放货库位ware_position_map_item的id")
private Long toMapItemId;
@Schema(description = "是否发生异常(0:正常、1异常)")
private Integer occurError;
}

View File

@ -115,4 +115,7 @@ public class RobotTaskDetailRespVO {
@Schema(description = "放货库位ware_position_map_item的id")
private Long toMapItemId;
@Schema(description = "是否发生异常(0:正常、1异常)")
private Integer occurError;
}

View File

@ -94,4 +94,7 @@ public class RobotTaskDetailSaveReqVO {
@Schema(description = "放货库位ware_position_map_item的id")
private Long toMapItemId;
@Schema(description = "是否发生异常(0:正常、1异常)")
private Integer occurError;
}

View File

@ -0,0 +1,60 @@
package cn.iocoder.yudao.module.system.dal.dataobject.remote;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 远遥设备信息 DO
*
* @author 陈宾顺
*/
@TableName("remote_controller_information")
@KeySequence("remote_controller_information_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RemoteControllerInformationDO extends BaseDO {
/**
* 主键ID
*/
@TableId
private Long id;
/**
* 远遥的设备IP
*/
private String remoteIp;
/**
* AGV编号
*/
private String robotNo;
/**
* 远遥模式(0:自动模式, 1:手动模式, 2:自由模式)
*/
private Integer remoteMode;
/**
* 协控(0:关闭协控, 1:开启协控)
*/
private Integer collaborativeControl;
/**
* 远遥的其他信息
*/
private String remoteMsg;
/**
* 服务IP
*/
private String systemIp;
/**
* 服务端口
*/
private String systemPort;
}

View File

@ -0,0 +1,55 @@
package cn.iocoder.yudao.module.system.dal.dataobject.robot;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 车辆摄像头信息 DO
*
* @author 陈宾顺
*/
@TableName("robot_camera")
@KeySequence("robot_camera_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RobotCameraDO extends BaseDO {
/**
* 主键ID
*/
@TableId
private Long id;
/**
* AGV编号
*/
private String robotNo;
/**
* 摄像头位置(0:, 1:, 2:, 3:, 4:)
*/
private Integer cameraPosition;
/**
* 摄像头IP
*/
private String cameraIp;
/**
* 摄像头端口
*/
private String cameraPort;
/**
* 摄像头账号
*/
private String cameraAccount;
/**
* 摄像头密码
*/
private String cameraPassword;
}

View File

@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.system.dal.dataobject.robot;
import lombok.*;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 车辆(地图)急停记录 DO
*
* @author 陈宾顺
*/
@TableName("robot_map_stop")
@KeySequence("robot_map_stop_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RobotMapStopDO extends BaseDO {
/**
* 主键ID
*/
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/**
* 急停仓库点位地图表id
*/
private Long positionMapId;
/**
* 急停的AGV编号
*/
private String robotNo;
/**
* 类型0地图1车辆
*/
private Integer stopType;
}

View File

@ -62,4 +62,9 @@ public class RobotModelDO extends BaseDO {
*/
private String robotCenterTail;
/**
* 转弯半径(单位米)
*/
private String robotTurningRadius;
}

View File

@ -137,6 +137,10 @@ public class RobotTaskDetailDO extends BaseDO {
* ware_position_map_item的id的id
*/
private Long toMapItemId;
/**
* 是否发生异常(0:正常1异常)
*/
private Integer occurError;
//todo 需要改为ware_position_map_item的id
}

View File

@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.system.dal.mysql.remote;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.system.controller.admin.remote.vo.RemoteControllerInformationPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.remote.RemoteControllerInformationDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 远遥设备信息 Mapper
*
* @author 陈宾顺
*/
@Mapper
public interface RemoteControllerInformationMapper extends BaseMapperX<RemoteControllerInformationDO> {
default PageResult<RemoteControllerInformationDO> selectPage(RemoteControllerInformationPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<RemoteControllerInformationDO>()
.eqIfPresent(RemoteControllerInformationDO::getRemoteIp, reqVO.getRemoteIp())
.eqIfPresent(RemoteControllerInformationDO::getRobotNo, reqVO.getRobotNo())
.eqIfPresent(RemoteControllerInformationDO::getRemoteMode, reqVO.getRemoteMode())
.eqIfPresent(RemoteControllerInformationDO::getCollaborativeControl, reqVO.getCollaborativeControl())
.eqIfPresent(RemoteControllerInformationDO::getRemoteMsg, reqVO.getRemoteMsg())
.betweenIfPresent(RemoteControllerInformationDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(RemoteControllerInformationDO::getId));
}
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.system.dal.mysql.robot;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotCameraDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 车辆摄像头信息 Mapper
*
* @author 陈宾顺
*/
@Mapper
public interface RobotCameraMapper extends BaseMapperX<RobotCameraDO> {
default PageResult<RobotCameraDO> selectPage(RobotCameraPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<RobotCameraDO>()
.eqIfPresent(RobotCameraDO::getRobotNo, reqVO.getRobotNo())
.eqIfPresent(RobotCameraDO::getCameraPosition, reqVO.getCameraPosition())
.eqIfPresent(RobotCameraDO::getCameraIp, reqVO.getCameraIp())
.eqIfPresent(RobotCameraDO::getCameraPort, reqVO.getCameraPort())
.eqIfPresent(RobotCameraDO::getCameraAccount, reqVO.getCameraAccount())
.eqIfPresent(RobotCameraDO::getCameraPassword, reqVO.getCameraPassword())
.betweenIfPresent(RobotCameraDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(RobotCameraDO::getId));
}
void deleteByRobotNo(@Param("robotNo") String robotNo);
}

View File

@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.system.dal.mysql.robot;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.system.controller.admin.robot.mapstop.RobotMapStopPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotMapStopDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 车辆(地图)急停记录 Mapper
*
* @author 陈宾顺
*/
@Mapper
public interface RobotMapStopMapper extends BaseMapperX<RobotMapStopDO> {
default PageResult<RobotMapStopDO> selectPage(RobotMapStopPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<RobotMapStopDO>()
.eqIfPresent(RobotMapStopDO::getPositionMapId, reqVO.getPositionMapId())
.eqIfPresent(RobotMapStopDO::getRobotNo, reqVO.getRobotNo())
.eqIfPresent(RobotMapStopDO::getStopType, reqVO.getStopType())
.betweenIfPresent(RobotMapStopDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(RobotMapStopDO::getId));
}
/**
* 根据地图id删除
* @param mapId
*/
void deleteRobotMapStopByMapId(@Param("mapId") Long mapId);
}

View File

@ -544,8 +544,8 @@ public class PathPlanningServiceImpl implements PathPlanningService {
.startingPointId(positionMapLineDO.getEndPointId())
.endPointId(positionMapLineDO.getStartingPointId())
.direction(1)
.forwardSpeedLimit(positionMapLineDO.getReverseSpeedLimit())
.reverseSpeedLimit(positionMapLineDO.getForwardSpeedLimit())
.forwardSpeedLimit(positionMapLineDO.getForwardSpeedLimit())
.reverseSpeedLimit(positionMapLineDO.getReverseSpeedLimit())
.beginControlX(positionMapLineDO.getEndControlX())
.beginControlY(positionMapLineDO.getEndControlY())
.endControlX(positionMapLineDO.getBeginControlX())

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.system.service.positionmap;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.dto.PositionMapDTO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapDO;
@ -11,6 +12,7 @@ import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* 仓库点位地图 Service 接口
@ -101,4 +103,10 @@ public interface PositionMapService extends IService<PositionMapDO> {
* @return
*/
List<PositionMapDO> getAllMap();
/**
* 获取地图及显示地图是否暂停
* @return
*/
Map<Integer, List<PositionMapDTO>> getPositionMapList();
}

View File

@ -10,25 +10,27 @@ import cn.iocoder.yudao.module.mqtt.api.common.CommonApi;
import cn.iocoder.yudao.module.mqtt.api.task.dto.RobotSimulationPoseDTO;
import cn.iocoder.yudao.module.system.constant.robot.RobotTopicConstant;
import cn.iocoder.yudao.module.system.controller.admin.log.vo.UserOperationLogSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.dto.PositionMapDTO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.information.DeviceInformationDO;
import cn.iocoder.yudao.module.system.controller.admin.robot.mapstop.RobotMapStopSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapDO;
import cn.iocoder.yudao.module.system.dal.mysql.positionmap.PositionMapMapper;
import cn.iocoder.yudao.module.system.enums.common.ZeroOneEnum;
import cn.iocoder.yudao.module.system.enums.robot.task.RobotCommandTypeEnum;
import cn.iocoder.yudao.module.system.service.log.UserOperationLogService;
import cn.iocoder.yudao.module.system.service.robot.RobotInformationService;
import cn.iocoder.yudao.module.system.service.robot.mapstop.RobotMapStopService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;
import org.yaml.snakeyaml.Yaml;
@ -74,6 +76,9 @@ public class PositionMapServiceImpl extends ServiceImpl<PositionMapMapper, Posit
@Resource
private CommonApi commonApi;
@Resource
private RobotMapStopService robotMapStopService;
@Override
public Long createPositionMap(PositionMapSaveReqVO createReqVO) {
// 插入
@ -137,7 +142,7 @@ public class PositionMapServiceImpl extends ServiceImpl<PositionMapMapper, Posit
byte[] bytes = yamlFile.getBytes();
// Parse the YAML file
Yaml yaml = new Yaml();
Map<String, Object> data = yaml.load(new String(bytes,StandardCharsets.UTF_8));
Map<String, Object> data = yaml.load(new String(bytes, StandardCharsets.UTF_8));
Object floor = data.get("floor");
Object area = data.get("area");
@ -318,25 +323,53 @@ public class PositionMapServiceImpl extends ServiceImpl<PositionMapMapper, Posit
@Override
@Transactional(rollbackFor = Exception.class)
public void emergencyStopOrRecovery(Long id, Integer type) {
// 先获取当前地图上的所有AGV信息
PositionMapDO positionMapDO = positionMapMapper.selectById(id);
List<String> robotNos =
informationService.getRobotByFloorAndArea(String.valueOf(positionMapDO.getFloor()), positionMapDO.getArea());
RobotSimulationPoseDTO robotSimulationPose = new RobotSimulationPoseDTO();
List<String> robotNos = new ArrayList<>();
String str = "";
String mapStr = positionMapDO.getFloor() + "" + positionMapDO.getArea() + " 所有车辆";
//暂停
if (ZeroOneEnum.ONE.getType().equals(type)) {
robotNos = informationService.getRobotByFloorAndArea(String.valueOf(positionMapDO.getFloor()), positionMapDO.getArea());
robotSimulationPose.setCommandType(RobotCommandTypeEnum.EMERGENCY_STOP.getType());
str = RobotCommandTypeEnum.EMERGENCY_STOP.getMsg();
mapStr = "一键暂停 " + mapStr;
} else {
//恢复
robotNos = robotMapStopService.getStopRobotNoByMapIds(id);
robotSimulationPose.setCommandType(RobotCommandTypeEnum.RECOVERY.getType());
str = RobotCommandTypeEnum.RECOVERY.getMsg();
mapStr = "一键恢复 " + mapStr;
robotMapStopService.deleteRobotMapStopByMapId(id);
}
if (ObjectUtil.isEmpty(robotNos)) {
throw exception(MAP_DOES_NOT_EXIST_AGV);
}
if (ZeroOneEnum.ONE.getType().equals(type)) {
robotMapStopService.createRobotMapStop(id, robotNos);
RobotMapStopSaveReqVO robotMapStopSave = new RobotMapStopSaveReqVO();
robotMapStopSave.setPositionMapId(id);
robotMapStopSave.setStopType(ZeroOneEnum.ZERO.getType());
robotMapStopService.createMapStop(robotMapStopSave);
}
sendEmergencyStopOrRecoveryToRobot(robotSimulationPose, robotNos, str);
UserOperationLogSaveReqVO operationLog = UserOperationLogSaveReqVO.builder()
.operateAction(mapStr)
.nickName(SecurityFrameworkUtils.getLoginUserNickname()).build();
userOperationLogService.createUserOperationLog(operationLog);
}
public void sendEmergencyStopOrRecoveryToRobot(RobotSimulationPoseDTO robotSimulationPose, List<String> robotNos, String str) {
for (String robotNo : robotNos) {
String mac = informationService.getMacByRobotNo(robotNo);
RobotSimulationPoseDTO robotSimulationPose = new RobotSimulationPoseDTO();
String str = "";
if (ZeroOneEnum.ONE.getType().equals(type)) {
robotSimulationPose.setCommandType(RobotCommandTypeEnum.EMERGENCY_STOP.getType());
str = RobotCommandTypeEnum.EMERGENCY_STOP.getMsg();
} else {
robotSimulationPose.setCommandType(RobotCommandTypeEnum.RECOVERY.getType());
str = RobotCommandTypeEnum.RECOVERY.getMsg();
}
commonApi.commonMethod(robotSimulationPose, RobotTopicConstant.ROBOT_COMMAND_TOPIC + mac);
UserOperationLogSaveReqVO operationLog = UserOperationLogSaveReqVO.builder()
.operateAction(str + robotNo)
@ -350,4 +383,26 @@ public class PositionMapServiceImpl extends ServiceImpl<PositionMapMapper, Posit
return positionMapMapper.selectList(new LambdaQueryWrapperX<PositionMapDO>().orderByDesc(PositionMapDO::getId));
}
@Override
public Map<Integer, List<PositionMapDTO>> getPositionMapList() {
List<PositionMapDO> allMap = getAllMap();
if (ObjectUtil.isEmpty(allMap)) {
return Collections.emptyMap();
}
List<PositionMapDTO> list = BeanUtils.toBean(allMap, PositionMapDTO.class);
List<Long> stopMapIds = robotMapStopService.getStopMapIds();
if (ObjectUtil.isEmpty(stopMapIds)) {
return list.stream().collect(Collectors.groupingBy(PositionMapDTO::getFloor));
}
for (PositionMapDTO positionMap : list) {
if (stopMapIds.contains(positionMap.getId())) {
positionMap.setStopOrRestore(ZeroOneEnum.ONE.getType());
}
}
return list.stream().collect(Collectors.groupingBy(PositionMapDTO::getFloor));
}
}

View File

@ -0,0 +1,70 @@
package cn.iocoder.yudao.module.system.service.remote;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.system.api.remote.dto.LoginCheckDTO;
import cn.iocoder.yudao.module.system.controller.admin.remote.vo.RemoteControllerInformationPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.remote.vo.RemoteControllerInformationSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.remote.RemoteControllerInformationDO;
import com.baomidou.mybatisplus.extension.service.IService;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
/**
* 远遥设备信息 Service 接口
*
* @author 陈宾顺
*/
public interface RemoteControllerInformationService extends IService<RemoteControllerInformationDO> {
/**
* 创建远遥设备信息
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createControllerInformation(@Valid RemoteControllerInformationSaveReqVO createReqVO);
/**
* 更新远遥设备信息
*
* @param updateReqVO 更新信息
*/
void updateControllerInformation(@Valid RemoteControllerInformationSaveReqVO updateReqVO);
/**
* 删除远遥设备信息
*
* @param id 编号
*/
void deleteControllerInformation(Long id);
/**
* 获得远遥设备信息
*
* @param id 编号
* @return 远遥设备信息
*/
RemoteControllerInformationDO getControllerInformation(Long id);
/**
* 获得远遥设备信息分页
*
* @param pageReqVO 分页查询
* @return 远遥设备信息分页
*/
PageResult<RemoteControllerInformationDO> getControllerInformationPage(RemoteControllerInformationPageReqVO pageReqVO);
/**
* 保存远遥的IP和端口
* @param loginCheckDTO
*/
void saveIpAndPort(LoginCheckDTO loginCheckDTO);
/**
* 查询远遥默认IP和端口
* @return
*/
LoginCheckDTO getDefaultIpAndPort();
}

View File

@ -0,0 +1,147 @@
package cn.iocoder.yudao.module.system.service.remote;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.api.remote.dto.LoginCheckDTO;
import cn.iocoder.yudao.module.system.controller.admin.log.vo.UserOperationLogSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.remote.vo.RemoteControllerInformationPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.remote.vo.RemoteControllerInformationSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.remote.RemoteControllerInformationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO;
import cn.iocoder.yudao.module.system.dal.mysql.remote.RemoteControllerInformationMapper;
import cn.iocoder.yudao.module.system.service.log.UserOperationLogService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.CONTROLLER_INFORMATION_NOT_EXISTS;
/**
* 远遥设备信息 Service 实现类
*
* @author 陈宾顺
*/
@Service
@Validated
public class RemoteControllerInformationServiceImpl extends ServiceImpl<RemoteControllerInformationMapper, RemoteControllerInformationDO> implements RemoteControllerInformationService {
@Resource
private RemoteControllerInformationMapper controllerInformationMapper;
@Resource
private UserOperationLogService userOperationLogService;
@Override
public Long createControllerInformation(RemoteControllerInformationSaveReqVO createReqVO) {
// 插入
RemoteControllerInformationDO controllerInformation = BeanUtils.toBean(createReqVO, RemoteControllerInformationDO.class);
controllerInformationMapper.insert(controllerInformation);
// 返回
return controllerInformation.getId();
}
@Override
public void updateControllerInformation(RemoteControllerInformationSaveReqVO updateReqVO) {
// 校验存在
validateControllerInformationExists(updateReqVO.getId());
// 更新
RemoteControllerInformationDO updateObj = BeanUtils.toBean(updateReqVO, RemoteControllerInformationDO.class);
controllerInformationMapper.updateById(updateObj);
}
@Override
public void deleteControllerInformation(Long id) {
// 校验存在
validateControllerInformationExists(id);
// 删除
controllerInformationMapper.deleteById(id);
}
private void validateControllerInformationExists(Long id) {
if (controllerInformationMapper.selectById(id) == null) {
throw exception(CONTROLLER_INFORMATION_NOT_EXISTS);
}
}
@Override
public RemoteControllerInformationDO getControllerInformation(Long id) {
return controllerInformationMapper.selectById(id);
}
@Override
public PageResult<RemoteControllerInformationDO> getControllerInformationPage(RemoteControllerInformationPageReqVO pageReqVO) {
return controllerInformationMapper.selectPage(pageReqVO);
}
/**
* 保存IP和端口
*
* @param loginCheck
*/
@Override
public void saveIpAndPort(LoginCheckDTO loginCheck) {
String remoteIp = ServletUtils.getClientIP();
RemoteControllerInformationDO information = controllerInformationMapper.selectOne(new LambdaQueryWrapper<RemoteControllerInformationDO>()
.eq(RemoteControllerInformationDO::getRemoteIp, remoteIp)
.last("limit 1"));
UserOperationLogSaveReqVO operationLog = null;
if (ObjectUtil.isEmpty(information)) {
RemoteControllerInformationDO build = RemoteControllerInformationDO.builder()
.remoteIp(remoteIp)
.systemPort(loginCheck.getSystemPort())
.systemIp(loginCheck.getSystemIp())
.build();
controllerInformationMapper.insert(build);
operationLog = UserOperationLogSaveReqVO.builder()
.operateAction("添加远遥设备IP " + loginCheck.getSystemIp() + " 端口 " + loginCheck.getSystemPort())
.nickName(SecurityFrameworkUtils.getLoginUserNickname()).build();
} else {
information.setSystemIp(loginCheck.getSystemIp());
information.setSystemPort(loginCheck.getSystemPort());
controllerInformationMapper.updateById(information);
operationLog = UserOperationLogSaveReqVO.builder()
.operateAction("修改远遥设备IP " + loginCheck.getSystemIp() + " 端口 " + loginCheck.getSystemPort())
.nickName(SecurityFrameworkUtils.getLoginUserNickname()).build();
}
userOperationLogService.createUserOperationLog(operationLog);
}
/**
* 查询远遥默认IP和端口
* @return
*/
@Override
public LoginCheckDTO getDefaultIpAndPort() {
String remoteIp = ServletUtils.getClientIP();
RemoteControllerInformationDO information = controllerInformationMapper.selectOne(new LambdaQueryWrapper<RemoteControllerInformationDO>()
.eq(RemoteControllerInformationDO::getRemoteIp, remoteIp)
.last("limit 1"));
LoginCheckDTO loginCheck = new LoginCheckDTO();
if (ObjectUtil.isEmpty(information)) {
return loginCheck;
}
loginCheck.setSystemIp(information.getSystemIp());
loginCheck.setSystemPort(information.getSystemPort());
return loginCheck;
}
}

View File

@ -7,6 +7,7 @@ import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
@ -29,9 +30,11 @@ import cn.iocoder.yudao.module.system.constant.robot.RobotStatusCodeConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotTopicConstant;
import cn.iocoder.yudao.module.system.controller.admin.log.vo.UserOperationLogSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraAddVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.proceed.RobotTaskProceedSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.*;
import cn.iocoder.yudao.module.system.controller.admin.tool.dto.CleanAgvDTO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseLocationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.information.DeviceInformationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.informationmapassociation.InformationMapAssociationDO;
@ -68,6 +71,7 @@ import cn.iocoder.yudao.module.system.service.informationmapassociation.Informat
import cn.iocoder.yudao.module.system.service.log.RobotTaskDetailActionLogService;
import cn.iocoder.yudao.module.system.service.log.UserOperationLogService;
import cn.iocoder.yudao.module.system.service.positionmap.PositionMapItemService;
import cn.iocoder.yudao.module.system.service.robot.camera.RobotCameraService;
import cn.iocoder.yudao.module.system.service.robot.pathplanning.RobotPathPlanningService;
import cn.iocoder.yudao.module.system.service.robot.proceed.RobotTaskProceedService;
import cn.iocoder.yudao.module.system.service.wait.MoveToWaitService;
@ -85,6 +89,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import javax.validation.ConstraintViolationException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -166,22 +171,40 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
@Value("${zn.restore_task_restart:true}")
private Boolean restoreTaskRestart;
@Resource
private RobotCameraService cameraService;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createInformation(RobotInformationSaveReqVO createReqVO) {
//判断mac地址是否重复
RobotInformationDO query = new RobotInformationDO();
query.setMacAddress(createReqVO.getMacAddress());
List<RobotInformationDO> existRobotMac = informationMapper.queryAllByLimit(query);
RobotInformationDO existRobotMac = informationMapper.selectOne(new LambdaQueryWrapper<RobotInformationDO>()
.eq(RobotInformationDO::getMacAddress, createReqVO.getMacAddress())
.last("limit 1"));
if (ObjectUtil.isNotEmpty(existRobotMac)) {
throw exception(ROBOT_MAC_ADDRESS_EXISTS);
}
//判断机器人编号
query.setMacAddress(null);
query.setRobotNo(createReqVO.getRobotNo());
List<RobotInformationDO> existRobotNo = informationMapper.queryAllByLimit(query);
RobotInformationDO existRobotNo = informationMapper.selectOne(new LambdaQueryWrapper<RobotInformationDO>()
.eq(RobotInformationDO::getRobotNo, createReqVO.getRobotNo())
.last("limit 1"));
if (ObjectUtil.isNotEmpty(existRobotNo)) {
throw exception(ROBOT_ROBOT_NO_EXISTS);
}
RobotInformationDO existRobotIp = informationMapper.selectOne(new LambdaQueryWrapper<RobotInformationDO>()
.eq(RobotInformationDO::getRobotIp, createReqVO.getRobotIp())
.last("limit 1"));
if (ObjectUtil.isNotEmpty(existRobotIp)) {
throw exception(ROBOT_ROBOT_IP_EXISTS);
}
if (ObjectUtil.isNotEmpty(createReqVO.getCameraAddVOList())) {
List<RobotCameraAddVO> cameraAddVOList = createReqVO.getCameraAddVOList();
cameraService.checkCameraExist(cameraAddVOList);
cameraService.createCameraList(cameraAddVOList,createReqVO.getRobotNo());
}
RobotModelDO robotModelDO = modelMapper.selectById(createReqVO.getRobotModelId());
createReqVO.setRobotModelNumber(robotModelDO.getRobotModelNumber());
createReqVO.setUrl(robotModelDO.getUrl());
@ -217,11 +240,14 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateInformation(RobotInformationSaveReqVO updateReqVO) {
// 校验存在
validateInformationExists(updateReqVO.getId());
RobotInformationDO robotInformationDO = informationMapper.selectById(updateReqVO.getId());
cameraService.deleteCameraByRobotNo(robotInformationDO.getRobotNo());
if (!updateReqVO.getRobotNo().equals(robotInformationDO.getRobotNo())
|| !updateReqVO.getMacAddress().equals(robotInformationDO.getMacAddress())) {
List<RobotTaskDO> list = taskMapper.selectDoingTaskByRobotNo(robotInformationDO.getRobotNo());
@ -249,6 +275,19 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
if (robotNoExist) {
throw exception(ROBOT_ROBOT_NO_EXISTS);
}
//校验IP
RobotInformationDO existRobotIp = informationMapper.selectOne(new LambdaQueryWrapper<RobotInformationDO>()
.eq(RobotInformationDO::getRobotIp, updateReqVO.getRobotIp())
.ne(RobotInformationDO::getId, updateReqVO.getId())
.last("limit 1"));
if (ObjectUtil.isNotEmpty(existRobotIp)) {
throw exception(ROBOT_ROBOT_IP_EXISTS);
}
if (ObjectUtil.isNotEmpty(updateReqVO.getCameraAddVOList())) {
List<RobotCameraAddVO> cameraAddVOList = updateReqVO.getCameraAddVOList();
cameraService.checkCameraExist(cameraAddVOList);
cameraService.createCameraList(cameraAddVOList,updateReqVO.getRobotNo());
}
// 更新
RobotInformationDO updateObj = BeanUtils.toBean(updateReqVO, RobotInformationDO.class);
informationMapper.updateById(updateObj);
@ -288,6 +327,8 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
validateInformationExists(id);
RobotInformationDO robotInformationDO = informationMapper.selectById(id);
cameraService.deleteCameraByRobotNo(robotInformationDO.getRobotNo());
List<RobotTaskDO> list = taskMapper.selectDoingTaskByRobotNo(robotInformationDO.getRobotNo());
if (ObjectUtil.isNotEmpty(list)) {

View File

@ -94,4 +94,10 @@ public interface RobotTaskDetailService {
* @return
*/
List<Long> getDoIngTaskItemIdsByItemIds(List<Long> pointList);
/**
* 设置任务出现异常
* @param orderId
*/
void setTaskDetailError(Long orderId);
}

View File

@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskDetailMapper;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskMapper;
import cn.iocoder.yudao.module.system.enums.common.ZeroOneEnum;
import cn.iocoder.yudao.module.system.enums.robot.RobotTaskDetailStatusEnum;
import cn.iocoder.yudao.module.system.enums.robot.RobotTaskStatusEnum;
import cn.iocoder.yudao.module.system.enums.robot.task.RobotTaskStageEnum;
@ -178,4 +179,12 @@ public class RobotTaskDetailServiceImpl implements RobotTaskDetailService {
public List<Long> getDoIngTaskItemIdsByItemIds(List<Long> pointList) {
return taskDetailMapper.getDoIngTaskItemIdsByItemIds(pointList);
}
@Override
public void setTaskDetailError(Long id) {
RobotTaskDetailDO robotTaskDetailDO = new RobotTaskDetailDO();
robotTaskDetailDO.setId(id);
robotTaskDetailDO.setOccurError(ZeroOneEnum.ONE.getType());
taskDetailMapper.updateById(robotTaskDetailDO);
}
}

View File

@ -0,0 +1,78 @@
package cn.iocoder.yudao.module.system.service.robot.camera;
import java.util.*;
import javax.validation.*;
import javax.validation.constraints.NotEmpty;
import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraAddVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotCameraDO;
import com.baomidou.mybatisplus.extension.service.IService;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
/**
* 车辆摄像头信息 Service 接口
*
* @author 陈宾顺
*/
public interface RobotCameraService extends IService<RobotCameraDO> {
/**
* 创建车辆摄像头信息
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createCamera(@Valid RobotCameraSaveReqVO createReqVO);
/**
* 更新车辆摄像头信息
*
* @param updateReqVO 更新信息
*/
void updateCamera(@Valid RobotCameraSaveReqVO updateReqVO);
/**
* 删除车辆摄像头信息
*
* @param id 编号
*/
void deleteCamera(Long id);
/**
* 获得车辆摄像头信息
*
* @param id 编号
* @return 车辆摄像头信息
*/
RobotCameraDO getCamera(Long id);
/**
* 获得车辆摄像头信息分页
*
* @param pageReqVO 分页查询
* @return 车辆摄像头信息分页
*/
PageResult<RobotCameraDO> getCameraPage(RobotCameraPageReqVO pageReqVO);
/**
* 校验摄像头IP和端口是否存在
* @param cameraAddVOList
*/
void checkCameraExist(List<RobotCameraAddVO> cameraAddVOList);
/**
* 添加摄像头
* @param cameraAddVOList
* @param robotNo
*/
void createCameraList(List<RobotCameraAddVO> cameraAddVOList, String robotNo);
/**
* 根据车辆编号删除摄像头
* @param robotNo
*/
void deleteCameraByRobotNo(String robotNo);
}

View File

@ -0,0 +1,127 @@
package cn.iocoder.yudao.module.system.service.robot.camera;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraAddVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraRespVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotCameraDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotCameraMapper;
import cn.iocoder.yudao.module.system.enums.robot.RobotStatusEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
/**
* 车辆摄像头信息 Service 实现类
*
* @author 陈宾顺
*/
@Service
@Validated
public class RobotCameraServiceImpl extends ServiceImpl<RobotCameraMapper, RobotCameraDO> implements RobotCameraService {
@Resource
private RobotCameraMapper cameraMapper;
@Override
public Long createCamera(RobotCameraSaveReqVO createReqVO) {
// 插入
RobotCameraDO camera = BeanUtils.toBean(createReqVO, RobotCameraDO.class);
cameraMapper.insert(camera);
// 返回
return camera.getId();
}
@Override
public void updateCamera(RobotCameraSaveReqVO updateReqVO) {
// 校验存在
validateCameraExists(updateReqVO.getId());
// 更新
RobotCameraDO updateObj = BeanUtils.toBean(updateReqVO, RobotCameraDO.class);
cameraMapper.updateById(updateObj);
}
@Override
public void deleteCamera(Long id) {
// 校验存在
validateCameraExists(id);
// 删除
cameraMapper.deleteById(id);
}
private void validateCameraExists(Long id) {
if (cameraMapper.selectById(id) == null) {
throw exception(CAMERA_NOT_EXISTS);
}
}
@Override
public RobotCameraDO getCamera(Long id) {
return cameraMapper.selectById(id);
}
@Override
public PageResult<RobotCameraDO> getCameraPage(RobotCameraPageReqVO pageReqVO) {
return cameraMapper.selectPage(pageReqVO);
}
/**
* 判断IP是否存在
* @param cameraAddVOList
*/
@Override
public void checkCameraExist(List<RobotCameraAddVO> cameraAddVOList) {
List<String> list = cameraAddVOList.stream().map(RobotCameraAddVO::getCameraIp).collect(Collectors.toList());
if (Sets.newHashSet(list).size() < list.size()) {
throw exception(CAMERA_IP_REPEAT);
}
List<RobotCameraDO> robotCameraDOs = cameraMapper.selectList(new LambdaQueryWrapper<RobotCameraDO>()
.in(RobotCameraDO::getCameraIp, list));
if (ObjectUtil.isEmpty(robotCameraDOs)) {
return;
}
List<String> ips = robotCameraDOs.stream().map(RobotCameraDO::getCameraIp).collect(Collectors.toList());
String join = StringUtils.join(ips, ",");
throw exception(CAMERA_IP_EXIST,"以下摄像头IP已经存在 "+join);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void createCameraList(List<RobotCameraAddVO> cameraAddVOList, String robotNo) {
List<RobotCameraDO> cameraDOList = BeanUtils.toBean(cameraAddVOList, RobotCameraDO.class);
for (RobotCameraDO robotCameraDO : cameraDOList) {
robotCameraDO.setRobotNo(robotNo);
}
cameraMapper.insert(cameraDOList);
}
/**
* 根据车辆编号删除
* @param robotNo
*/
@Override
public void deleteCameraByRobotNo(String robotNo) {
cameraMapper.deleteByRobotNo(robotNo);
}
}

View File

@ -0,0 +1,90 @@
package cn.iocoder.yudao.module.system.service.robot.mapstop;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.system.controller.admin.robot.mapstop.RobotMapStopPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.mapstop.RobotMapStopSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotMapStopDO;
import com.baomidou.mybatisplus.extension.service.IService;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
/**
* 车辆(地图)急停记录 Service 接口
*
* @author 陈宾顺
*/
public interface RobotMapStopService extends IService<RobotMapStopDO> {
/**
* 创建车辆(地图)急停记录
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createMapStop(@Valid RobotMapStopSaveReqVO createReqVO);
/**
* 更新车辆(地图)急停记录
*
* @param updateReqVO 更新信息
*/
void updateMapStop(@Valid RobotMapStopSaveReqVO updateReqVO);
/**
* 删除车辆(地图)急停记录
*
* @param id 编号
*/
void deleteMapStop(Long id);
/**
* 获得车辆(地图)急停记录
*
* @param id 编号
* @return 车辆(地图)急停记录
*/
RobotMapStopDO getMapStop(Long id);
/**
* 获得车辆(地图)急停记录分页
*
* @param pageReqVO 分页查询
* @return 车辆(地图)急停记录分页
*/
PageResult<RobotMapStopDO> getMapStopPage(RobotMapStopPageReqVO pageReqVO);
/**
* 查询暂停的地图
* @return
*/
List<Long> getStopMapIds();
/**
* 查询这张地图暂停的车辆
* @param id
* @return
*/
List<String> getStopRobotNoByMapIds(Long id);
/**
* 添加暂停
* @param id
* @param robotNos
*/
void createRobotMapStop(Long id, List<String> robotNos);
/**
* 根据地图id删除
* @param id
*/
void deleteRobotMapStopByMapId(Long id);
/**
* 根据地图id查询该地图的暂停信息
* @param id
* @return
*/
List<RobotMapStopDO> getByMapId(Long id);
}

View File

@ -0,0 +1,141 @@
package cn.iocoder.yudao.module.system.service.robot.mapstop;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.system.controller.admin.robot.mapstop.RobotMapStopPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.mapstop.RobotMapStopSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapItemDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotMapStopDO;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotMapStopMapper;
import cn.iocoder.yudao.module.system.enums.common.ZeroOneEnum;
import cn.iocoder.yudao.module.system.enums.item.PositionMapItemEnum;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAP_STOP_NOT_EXISTS;
/**
* 车辆(地图)急停记录 Service 实现类
*
* @author 陈宾顺
*/
@Service
@Validated
public class RobotMapStopServiceImpl extends ServiceImpl<RobotMapStopMapper, RobotMapStopDO> implements RobotMapStopService {
@Resource
private RobotMapStopMapper mapStopMapper;
@Override
public Long createMapStop(RobotMapStopSaveReqVO createReqVO) {
// 插入
RobotMapStopDO mapStop = BeanUtils.toBean(createReqVO, RobotMapStopDO.class);
mapStopMapper.insert(mapStop);
// 返回
return mapStop.getId();
}
@Override
public void updateMapStop(RobotMapStopSaveReqVO updateReqVO) {
// 校验存在
validateMapStopExists(updateReqVO.getId());
// 更新
RobotMapStopDO updateObj = BeanUtils.toBean(updateReqVO, RobotMapStopDO.class);
mapStopMapper.updateById(updateObj);
}
@Override
public void deleteMapStop(Long id) {
// 校验存在
validateMapStopExists(id);
// 删除
mapStopMapper.deleteById(id);
}
private void validateMapStopExists(Long id) {
if (mapStopMapper.selectById(id) == null) {
throw exception(MAP_STOP_NOT_EXISTS);
}
}
@Override
public RobotMapStopDO getMapStop(Long id) {
return mapStopMapper.selectById(id);
}
@Override
public PageResult<RobotMapStopDO> getMapStopPage(RobotMapStopPageReqVO pageReqVO) {
return mapStopMapper.selectPage(pageReqVO);
}
@Override
public List<Long> getStopMapIds() {
List<RobotMapStopDO> positionMapItems = mapStopMapper.selectList(new LambdaQueryWrapperX<RobotMapStopDO>()
.eq(RobotMapStopDO::getStopType, ZeroOneEnum.ZERO.getType()));
if (ObjectUtil.isEmpty(positionMapItems)) {
return new ArrayList<>();
}
return positionMapItems.stream()
.map(RobotMapStopDO::getPositionMapId)
.collect(Collectors.toList());
}
@Override
public List<String> getStopRobotNoByMapIds(Long id) {
List<RobotMapStopDO> positionMapItems = mapStopMapper.selectList(new LambdaQueryWrapperX<RobotMapStopDO>()
.eq(RobotMapStopDO::getStopType, ZeroOneEnum.ONE.getType())
.eq(RobotMapStopDO::getPositionMapId, id));
if (ObjectUtil.isEmpty(positionMapItems)) {
return new ArrayList<>();
}
return positionMapItems.stream()
.map(RobotMapStopDO::getRobotNo)
.collect(Collectors.toList());
}
/**
*
* @param id
* @param robotNos
*/
@Override
public void createRobotMapStop(Long id, List<String> robotNos) {
List<RobotMapStopDO> list = new ArrayList<>();
for (String robotNo : robotNos) {
RobotMapStopDO mapStop = new RobotMapStopDO();
mapStop.setPositionMapId(id);
mapStop.setRobotNo(robotNo);
mapStop.setStopType(ZeroOneEnum.ONE.getType());
list.add(mapStop);
}
mapStopMapper.insertBatch(list);
}
@Override
public void deleteRobotMapStopByMapId(Long id) {
mapStopMapper.deleteRobotMapStopByMapId(id);
}
@Override
public List<RobotMapStopDO> getByMapId(Long id) {
List<RobotMapStopDO> positionMapItems = mapStopMapper.selectList(new LambdaQueryWrapperX<RobotMapStopDO>()
.eq(RobotMapStopDO::getStopType, ZeroOneEnum.ZERO.getType())
.eq(RobotMapStopDO::getPositionMapId, id));
return positionMapItems;
}
}

View File

@ -133,6 +133,8 @@ logging:
cn.iocoder.yudao.module.system.dal.mysql: debug
cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper: INFO # 配置 SmsChannelMapper 的日志级别为 info
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿先禁用Spring Boot 3.X 存在部分错误的 WARN 提示
file:
name: D:/project/rcs/logs/${spring.application.name}.log
--- #################### 微信公众号、小程序相关配置 ####################
wx:
@ -235,6 +237,3 @@ zn:
task_chche_time: 604800 #任务缓存的时间, 默认一星期
is_simulation: true # 是否为仿真环境
logging:
file:
name: D:/project/rcs/logs/${spring.application.name}.log

View File

@ -0,0 +1,12 @@
<?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="cn.iocoder.yudao.module.system.dal.mysql.remote.RemoteControllerInformationMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>

View File

@ -0,0 +1,19 @@
<?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="cn.iocoder.yudao.module.system.dal.mysql.robot.RobotCameraMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
<delete id="deleteByRobotNo">
delete
from
robot_camera
where
robot_no = #{robotNo}
</delete>
</mapper>

View File

@ -175,7 +175,8 @@
t2.robot_wide AS robotWide,
t2.robot_center_headstock AS robotCenterHeadstock,
t2.robot_center_tail AS robotCenterTail,
t1.mac_address as macAddress
t1.mac_address as macAddress,
t2.robot_turning_radius as robotTurningRadius
FROM
robot_information t1
LEFT JOIN robot_model t2 ON t1.robot_model_id = t2.id

View File

@ -0,0 +1,19 @@
<?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="cn.iocoder.yudao.module.system.dal.mysql.robot.RobotMapStopMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
<delete id="deleteRobotMapStopByMapId">
delete
from
robot_map_stop
where
position_map_id = #{mapId}
</delete>
</mapper>