diff --git a/bonus-admin/src/main/java/com/bonus/web/controller/data/LineController.java b/bonus-admin/src/main/java/com/bonus/web/controller/data/LineController.java
index 47d1d3c..062d41d 100644
--- a/bonus-admin/src/main/java/com/bonus/web/controller/data/LineController.java
+++ b/bonus-admin/src/main/java/com/bonus/web/controller/data/LineController.java
@@ -49,4 +49,20 @@ public class LineController {
public AjaxResult getVideoStreamAPI(ParamsDto dto) {
return lineService.getVideoStreamAPI(dto);
}
+
+
+ @ApiOperation(notes = "设备操作",value = "设备操作")
+ @RequiresPermissions("data:device:oper")
+ @PostMapping("/operDevice")
+ @SysLog(title = "设备管理", businessType = OperaType.UPDATE, logType = 1, module = "设备管理->视频管理", details = "设备操作")
+ public AjaxResult operDevice(@RequestBody ParamsDto dto) {
+ return lineService.operDevice(dto);
+ }
+
+ @ApiOperation(notes = "录制视频",value = "录制视频")
+ @PostMapping("/recordingVideo")
+ @SysLog(title = "设备管理", businessType = OperaType.UPDATE, logType = 1, module = "设备管理->视频管理", details = "录制视频")
+ public AjaxResult recordingVideo(@RequestBody ParamsDto dto) {
+ return lineService.recordingVideo(dto);
+ }
}
diff --git a/bonus-admin/src/main/java/com/bonus/web/service/data/LineService.java b/bonus-admin/src/main/java/com/bonus/web/service/data/LineService.java
index c17444e..776c513 100644
--- a/bonus-admin/src/main/java/com/bonus/web/service/data/LineService.java
+++ b/bonus-admin/src/main/java/com/bonus/web/service/data/LineService.java
@@ -1,8 +1,12 @@
package com.bonus.web.service.data;
+import com.bonus.algorithm.service.DeviceOperService;
import com.bonus.algorithm.service.DrawLinesService;
+import com.bonus.algorithm.service.EndVideoService;
+import com.bonus.algorithm.service.StartVideoService;
import com.bonus.common.core.domain.AjaxResult;
import com.bonus.common.domain.algorithm.dto.DrawLinesRequest;
+import com.bonus.common.domain.algorithm.dto.OperDeviceRequest;
import com.bonus.common.domain.algorithm.vo.DrawLinesResponse;
import com.bonus.common.domain.data.dto.LineDto;
import com.bonus.common.domain.data.dto.ParamsDto;
@@ -18,6 +22,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import javax.annotation.Resource;
+import java.io.IOException;
import java.util.Objects;
/**
@@ -40,6 +45,15 @@ public class LineService {
@Resource(name = "DrawLinesService")
private DrawLinesService drawLinesService;
+ @Resource(name = "DeviceOperService")
+ private DeviceOperService deviceOperService;
+
+ @Resource(name = "StartVideoService")
+ private StartVideoService startVideoService;
+
+ @Resource(name = "EndVideoService")
+ private EndVideoService endVideoService;
+
/**
* 查询初始线的位置
* @param dto
@@ -121,4 +135,68 @@ public class LineService {
}
return AjaxResult.success(vo);
}
+
+ /**
+ * 设备操作
+ * @param dto
+ * @return AjaxResult
+ * @author cwchen
+ * @date 2026/1/19 9:28
+ */
+ public AjaxResult operDevice(ParamsDto dto) {
+ try {
+ OperDeviceRequest request = new OperDeviceRequest();
+ if (StringUtils.isNotBlank(dto.getMode())) {
+ request.setMode(Long.parseLong(dto.getMode()));
+ request.setAlarm(true);
+ } else {
+ request.setMode(1L);
+ request.setAlarm(dto.isAlarm());
+ }
+ DrawLinesResponse drawLinesResponse = deviceOperService.callOperDeviceService(request);
+ if (Objects.nonNull(drawLinesResponse)) {
+ if(drawLinesResponse.isSuccess()){
+ return AjaxResult.success();
+ }else{
+ return AjaxResult.error(drawLinesResponse.getMessage());
+ }
+ }else{
+ return AjaxResult.error(ResultCode.INTERFACE_CALL_FAILED.getMessage());
+ }
+ } catch (IOException e) {
+ log.error(e.toString(),e);
+ return AjaxResult.error(ResultCode.INTERFACE_CALL_FAILED.getMessage());
+ }
+ }
+
+
+ /**
+ * 开始录制视频 和 结束录制视频
+ * @param dto
+ * @return AjaxResult
+ * @author cwchen
+ * @date 2026/1/19 14:48
+ */
+ public AjaxResult recordingVideo(ParamsDto dto) {
+ try {
+ DrawLinesResponse drawLinesResponse = null;
+ if(Objects.equals(dto.getRecordingType(),"1")){
+ drawLinesResponse = startVideoService.callStartVideoService();
+ }else{
+ drawLinesResponse = endVideoService.callEndVideoService();
+ }
+ if (Objects.nonNull(drawLinesResponse)) {
+ if(drawLinesResponse.isSuccess()){
+ return AjaxResult.success();
+ }else{
+ return AjaxResult.error(drawLinesResponse.getMessage());
+ }
+ }else{
+ return AjaxResult.error(ResultCode.INTERFACE_CALL_FAILED.getMessage());
+ }
+ } catch (IOException e) {
+ log.error(e.toString(),e);
+ return AjaxResult.error(ResultCode.INTERFACE_CALL_FAILED.getMessage());
+ }
+ }
}
diff --git a/bonus-admin/src/main/java/com/bonus/web/service/data/NetworkService.java b/bonus-admin/src/main/java/com/bonus/web/service/data/NetworkService.java
index 7dc7f6d..8cc6dfa 100644
--- a/bonus-admin/src/main/java/com/bonus/web/service/data/NetworkService.java
+++ b/bonus-admin/src/main/java/com/bonus/web/service/data/NetworkService.java
@@ -1,7 +1,6 @@
package com.bonus.web.service.data;
import com.bonus.common.core.domain.AjaxResult;
-import com.bonus.common.domain.data.dto.LineDto;
import com.bonus.common.domain.data.dto.NetworkEthernetDto;
import com.bonus.common.domain.data.dto.NetworkSimDto;
import com.bonus.common.domain.data.dto.ParamsDto;
@@ -77,7 +76,7 @@ public class NetworkService {
return AjaxResult.error(validResult);
}
if(Objects.equals(dto.getEnableDhcp(),"0")){
- String validResult2 = validatorsUtils.valid(dto, NetworkEthernetDto.ENABLE.class);
+ String validResult2 = validatorsUtils.valid(dto, NetworkEthernetDto.NOENABLE.class);
if (StringUtils.isNotBlank(validResult2)) {
return AjaxResult.error(validResult2);
}
@@ -88,7 +87,7 @@ public class NetworkService {
return AjaxResult.error(validResult);
}
if(Objects.equals(dto.getEnableDhcp(),"0")){
- String validResult2 = validatorsUtils.valid(dto, NetworkEthernetDto.ENABLE.class);
+ String validResult2 = validatorsUtils.valid(dto, NetworkEthernetDto.NOENABLE.class);
if (StringUtils.isNotBlank(validResult2)) {
return AjaxResult.error(validResult2);
}
diff --git a/bonus-admin/src/main/java/com/bonus/web/service/data/SystemInfoService.java b/bonus-admin/src/main/java/com/bonus/web/service/data/SystemInfoService.java
index 4c9e2a4..0d8577a 100644
--- a/bonus-admin/src/main/java/com/bonus/web/service/data/SystemInfoService.java
+++ b/bonus-admin/src/main/java/com/bonus/web/service/data/SystemInfoService.java
@@ -1,15 +1,22 @@
package com.bonus.web.service.data;
+import com.bonus.algorithm.service.DeviceOperService;
import com.bonus.common.core.domain.AjaxResult;
+import com.bonus.common.domain.algorithm.dto.OperDeviceRequest;
+import com.bonus.common.domain.algorithm.vo.DrawLinesResponse;
import com.bonus.common.domain.data.dto.ParamsDto;
import com.bonus.common.domain.data.vo.SystemInfoVo;
+import com.bonus.common.enums.ResultCode;
import com.bonus.data.service.DISystemInfoService;
import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import javax.annotation.Resource;
+import java.io.IOException;
+import java.util.Objects;
/**
* @className:SystemInfoService
@@ -25,8 +32,12 @@ public class SystemInfoService {
@Resource(name = "DISystemInfoService")
private DISystemInfoService systemInfoService;
+ @Resource(name = "DeviceOperService")
+ private DeviceOperService deviceOperService;
+
/**
* 查询系统信息
+ *
* @param dto
* @return AjaxResult
* @author cwchen
@@ -38,7 +49,7 @@ public class SystemInfoService {
vo = systemInfoService.getDeviceInfo(dto);
return AjaxResult.success(vo == null ? new SystemInfoVo() : vo);
} catch (Exception e) {
- log.error(e.toString(),e);
+ log.error(e.toString(), e);
vo = new SystemInfoVo();
}
return AjaxResult.success(vo);
@@ -46,6 +57,7 @@ public class SystemInfoService {
/**
* 修改设备信息
+ *
* @param dto
* @return AjaxResult
* @author cwchen
@@ -57,7 +69,7 @@ public class SystemInfoService {
systemInfoService.updateDevice(dto);
return AjaxResult.success();
} catch (Exception e) {
- log.error(e.toString(),e);
+ log.error(e.toString(), e);
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return AjaxResult.error();
}
@@ -65,6 +77,7 @@ public class SystemInfoService {
/**
* 修改告警状态
+ *
* @param dto
* @return AjaxResult
* @author cwchen
@@ -72,13 +85,23 @@ public class SystemInfoService {
*/
public AjaxResult updateAlarmStatus(ParamsDto dto) {
try {
- // 1.是否调用第三方接口
- systemInfoService.updateAlarmStatus(dto);
- return AjaxResult.success();
- } catch (Exception e) {
- log.error(e.toString(),e);
- TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
- return AjaxResult.error();
+ OperDeviceRequest request = new OperDeviceRequest();
+ request.setMode(1L);
+ request.setAlarm(Objects.equals(dto.getAlarmStatus(), "1"));
+ DrawLinesResponse drawLinesResponse = deviceOperService.callOperDeviceService(request);
+ if (Objects.nonNull(drawLinesResponse)) {
+ if (drawLinesResponse.isSuccess()) {
+ systemInfoService.updateAlarmStatus(dto);
+ return AjaxResult.success();
+ } else {
+ return AjaxResult.error(drawLinesResponse.getMessage());
+ }
+ } else {
+ return AjaxResult.error(ResultCode.INTERFACE_CALL_FAILED.getMessage());
+ }
+ } catch (IOException e) {
+ log.error(e.toString(), e);
+ return AjaxResult.error(ResultCode.INTERFACE_CALL_FAILED.getMessage());
}
}
}
diff --git a/bonus-admin/src/main/resources/application-algorithm.yml b/bonus-admin/src/main/resources/application-algorithm.yml
index de8e10e..97b1a17 100644
--- a/bonus-admin/src/main/resources/application-algorithm.yml
+++ b/bonus-admin/src/main/resources/application-algorithm.yml
@@ -1,5 +1,9 @@
algorithm:
service:
url: http://192.168.0.108:8080/api/v1/video/setTripwire # 画线算法接口请求地址
+ operUrl: http://192.168.0.108:8080/api/v1/battery/control # 设备操作接口请求地址
+ detailUrl: http://192.168.0.108:8080/api/v1/battery/status # 设备状态接口请求地址
+ startVideoUrl: http://192.168.0.108:8080/api/v1/record/start # 开始录制接口请求地址
+ endVideoUrl: http://192.168.0.108:8080/api/v1/record/stop # 结束录制接口请求地址
timeout: 30000 # 画线算法请求超时时间
max-connections: 100
\ No newline at end of file
diff --git a/bonus-admin/src/main/resources/application-dev.yml b/bonus-admin/src/main/resources/application-dev.yml
index fabb37b..099cd9f 100644
--- a/bonus-admin/src/main/resources/application-dev.yml
+++ b/bonus-admin/src/main/resources/application-dev.yml
@@ -8,6 +8,7 @@ bonus:
copyrightYear: 2025
# 文件路径 示例( Windows配置D:/bonus/uploadPath,Linux配置 /home/bonus/uploadPath)
profile: D:/bonus/uploadPath
+ lsFile: /home/jar/smart-car-dev
# 获取ip地址开关
addressEnabled: false
# 验证码类型 math 数字计算 char 字符验证
diff --git a/bonus-admin/src/main/resources/application-druid.yml b/bonus-admin/src/main/resources/application-druid.yml
index 2030d2d..6b8ce15 100644
--- a/bonus-admin/src/main/resources/application-druid.yml
+++ b/bonus-admin/src/main/resources/application-druid.yml
@@ -6,12 +6,12 @@ spring:
druid:
# 主库数据源
master:
- url: jdbc:mysql://192.168.0.14:2009/smart-car-dev?useUnicode=true&allowMultiQueries=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
- username: root
- password: Bonus@admin123!
-# url: jdbc:mysql://127.0.0.1:3306/smart_bid_dev?useUnicode=true&allowMultiQueries=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+# url: jdbc:mysql://192.168.0.14:2009/smart-car-dev?useUnicode=true&allowMultiQueries=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# username: root
-# password: ccw1998@yyt1999
+# password: Bonus@admin123!
+ url: jdbc:mysql://192.168.0.108:3306/smart-car-dev?useUnicode=true&allowMultiQueries=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: RemoteDev
+ password: forlinx
# 从库数据源
slave:
# 从数据源开关/默认关闭
diff --git a/bonus-admin/src/main/resources/application-test.yml b/bonus-admin/src/main/resources/application-test.yml
index 531ae20..355b4ff 100644
--- a/bonus-admin/src/main/resources/application-test.yml
+++ b/bonus-admin/src/main/resources/application-test.yml
@@ -7,7 +7,8 @@ bonus:
# 版权年份
copyrightYear: 2025
# 文件路径 示例( Windows配置D:/bonus/uploadPath,Linux配置 /home/bonus/uploadPath)
- profile: /home/bonus/uploadPath
+ profile: /home/forlinx/Vehicle_Road_Counter
+ lsFile: /home/jar/smart-car-dev
# 获取ip地址开关
addressEnabled: false
# 验证码类型 math 数字计算 char 字符验证
@@ -20,7 +21,7 @@ sql:
# 开发环境配置
server:
# 服务器的HTTP端口,默认为8091
- port: 8091
+ port: 8099
servlet:
# 应用的访问路径
context-path: /smartCar
@@ -70,13 +71,13 @@ spring:
# redis 配置
redis:
# 地址
- host: 192.168.0.14
+ host: 192.168.0.108
# 端口,默认为6379
- port: 2004
+ port: 6379
# 数据库索引
database: 6
# 密码
- password: Plzbns@Redis123!
+ password: forlinx
# 连接超时时间
timeout: 10s
lettuce:
diff --git a/bonus-admin/src/main/resources/application.yml b/bonus-admin/src/main/resources/application.yml
index b423e36..e4263b7 100644
--- a/bonus-admin/src/main/resources/application.yml
+++ b/bonus-admin/src/main/resources/application.yml
@@ -1,6 +1,6 @@
spring:
profiles:
- active: @profiles.active@,druid,ocr,file,rabbitmq
+ active: @profiles.active@,druid,ocr,file,rabbitmq,algorithm
# 解决SpringBoot 2.6+与SpringFox兼容性问题
mvc:
pathmatch:
diff --git a/bonus-algorithm/src/main/java/com/bonus/algorithm/service/DeviceDetailService.java b/bonus-algorithm/src/main/java/com/bonus/algorithm/service/DeviceDetailService.java
new file mode 100644
index 0000000..db5a68e
--- /dev/null
+++ b/bonus-algorithm/src/main/java/com/bonus/algorithm/service/DeviceDetailService.java
@@ -0,0 +1,198 @@
+package com.bonus.algorithm.service;
+
+import com.bonus.common.domain.algorithm.dto.OperDeviceRequest;
+import com.bonus.common.domain.algorithm.vo.DeviceDetailResponse;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.net.URI;
+
+/**
+ * @className: DeviceOperService
+ * @author: cwchen
+ * @date: 2026-01-08-9:26
+ * @version: 1.0
+ * @description: 设备详情详情接口调用-业务逻辑层
+ */
+@Service(value = "DeviceDetailService")
+@Slf4j
+public class DeviceDetailService {
+
+ private static final String UTF_8 = "UTF-8";
+
+ @Value("${algorithm.service.detailUrl}")
+ private String algorithmServiceUrl;
+
+ @Value("${algorithm.service.timeout}")
+ private int timeout;
+
+ private final CloseableHttpClient httpClient;
+ private final ObjectMapper objectMapper;
+
+ public DeviceDetailService() {
+ RequestConfig requestConfig = RequestConfig.custom()
+ .setConnectTimeout(timeout)
+ .setSocketTimeout(timeout)
+ .setConnectionRequestTimeout(timeout)
+ .build();
+
+ this.httpClient = HttpClients.custom()
+ .setDefaultRequestConfig(requestConfig)
+ .build();
+ this.objectMapper = new ObjectMapper();
+ }
+
+ /**
+ * 调用设备详情接口
+ *
+ * @return 设备详情响应结果
+ * @throws IOException 当设备详情服务调用失败时抛出
+ */
+ public DeviceDetailResponse callDeviceDetailService() throws IOException {
+ HttpGet httpGet = null;
+ try {
+ httpGet = createHttpGet();
+ return executeOcrRequest(httpGet);
+ } catch (IOException e) {
+ log.error("调用设备详情服务失败", e);
+ return null;
+ } finally {
+ cleanupResources(httpGet);
+ }
+ }
+
+ /**
+ * 验证设备详情请求参数
+ */
+ private void validateOperDeviceRequest(OperDeviceRequest operDeviceRequest) {
+ if (operDeviceRequest == null) {
+ throw new IllegalArgumentException("设备详情请求参数不能为空");
+ }
+ }
+
+ /**
+ * 创建HTTP GET请求
+ */
+ private HttpGet createHttpGet() {
+ // 声明 HttpGet 对象
+ HttpGet httpGet = null;
+ try {
+ // 1. 使用 URIBuilder 构建带参数的 URL
+ URIBuilder uriBuilder = new URIBuilder(algorithmServiceUrl);
+ // 2. 构建 URI 并创建 HttpGet
+ URI uri = uriBuilder.build();
+ httpGet = new HttpGet(uri);
+ } catch (Exception e) {
+ throw new RuntimeException("创建HTTP GET请求失败", e);
+ }
+
+ return httpGet;
+ }
+
+ /**
+ * 将请求对象转换为JSON字符串
+ */
+ private String convertToJson(OperDeviceRequest request) throws JsonProcessingException {
+ ObjectMapper objectMapper = new ObjectMapper();
+ return objectMapper.writeValueAsString(request);
+ }
+
+ /**
+ * 执行设备详情请求
+ */
+ private DeviceDetailResponse executeOcrRequest(HttpGet httpGet) throws IOException {
+ log.info("开始调用设备详情服务识别");
+
+ try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
+ return processHttpResponse(response);
+ }
+ }
+
+ /**
+ * 处理HTTP响应
+ */
+ private DeviceDetailResponse processHttpResponse(CloseableHttpResponse response) throws IOException {
+ log.info("响应内容:{}",response);
+ int statusCode = response.getStatusLine().getStatusCode();
+ String responseBody = getResponseBody(response);
+
+ log.info("设备详情服务响应状态: {}", statusCode);
+ log.debug("设备详情服务响应内容: {}", responseBody); // 改为debug级别,避免日志过大
+
+ // 检查HTTP状态码
+ if (statusCode != 200) {
+ log.error("设备详情服务HTTP请求失败,状态码: {}, 响应: {}", statusCode, responseBody);
+ return null;
+ }
+
+ DeviceDetailResponse DeviceDetailResponse = parseResponseBody(responseBody);
+ return DeviceDetailResponse;
+ }
+
+ /**
+ * 获取响应体
+ */
+ private String getResponseBody(CloseableHttpResponse response) throws IOException {
+ HttpEntity entity = response.getEntity();
+ return EntityUtils.toString(entity, UTF_8);
+ }
+
+ /**
+ * 解析响应体
+ */
+ private DeviceDetailResponse parseResponseBody(String responseBody) throws IOException {
+ try {
+ return objectMapper.readValue(responseBody, DeviceDetailResponse.class);
+ } catch (IOException e) {
+ log.error("解析设备详情请求响应失败,响应内容: {}", responseBody, e);
+ return null;
+ }
+ }
+
+ /**
+ * 清理资源
+ */
+ private void cleanupResources(HttpGet httpGet) {
+ // 清理HTTP连接
+ if (httpGet != null) {
+ httpGet.releaseConnection();
+ }
+
+ }
+
+ /**
+ * 关闭HTTP客户端
+ */
+ public void close() {
+ try {
+ if (httpClient != null) {
+ httpClient.close();
+ log.info("设备详情服务HTTP客户端已关闭");
+ }
+ } catch (IOException e) {
+ log.error("关闭HTTP客户端失败", e);
+ }
+ }
+
+ /**
+ * 销毁方法,用于Spring容器关闭时调用
+ */
+ public void destroy() {
+ close();
+ }
+}
diff --git a/bonus-algorithm/src/main/java/com/bonus/algorithm/service/DeviceOperService.java b/bonus-algorithm/src/main/java/com/bonus/algorithm/service/DeviceOperService.java
new file mode 100644
index 0000000..ee11d67
--- /dev/null
+++ b/bonus-algorithm/src/main/java/com/bonus/algorithm/service/DeviceOperService.java
@@ -0,0 +1,206 @@
+package com.bonus.algorithm.service;
+
+import com.bonus.common.domain.algorithm.dto.DrawLinesRequest;
+import com.bonus.common.domain.algorithm.dto.OperDeviceRequest;
+import com.bonus.common.domain.algorithm.vo.DrawLinesResponse;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+
+/**
+ * @className: DeviceOperService
+ * @author: cwchen
+ * @date: 2026-01-08-9:26
+ * @version: 1.0
+ * @description: 设备操作接口调用-业务逻辑层
+ */
+@Service(value = "DeviceOperService")
+@Slf4j
+public class DeviceOperService {
+
+ private static final String UTF_8 = "UTF-8";
+
+ @Value("${algorithm.service.operUrl}")
+ private String algorithmServiceUrl;
+
+ @Value("${algorithm.service.timeout}")
+ private int timeout;
+
+ private final CloseableHttpClient httpClient;
+ private final ObjectMapper objectMapper;
+
+ public DeviceOperService() {
+ RequestConfig requestConfig = RequestConfig.custom()
+ .setConnectTimeout(timeout)
+ .setSocketTimeout(timeout)
+ .setConnectionRequestTimeout(timeout)
+ .build();
+
+ this.httpClient = HttpClients.custom()
+ .setDefaultRequestConfig(requestConfig)
+ .build();
+ this.objectMapper = new ObjectMapper();
+ }
+
+ /**
+ * 调用设备操作接口
+ *
+ * @param operDeviceRequest 设备操作请求参数
+ * @return 设备操作响应结果
+ * @throws IOException 当设备操作服务调用失败时抛出
+ */
+ public DrawLinesResponse callOperDeviceService(OperDeviceRequest operDeviceRequest) throws IOException {
+ validateOperDeviceRequest(operDeviceRequest);
+
+ HttpPost httpPost = null;
+ try {
+ httpPost = createHttpPost(operDeviceRequest);
+ return executeOcrRequest(httpPost);
+ } catch (IOException e) {
+ log.error("调用设备操作服务失败", e);
+ return null;
+ } finally {
+ cleanupResources(httpPost);
+ }
+ }
+
+ /**
+ * 验证设备操作请求参数
+ */
+ private void validateOperDeviceRequest(OperDeviceRequest operDeviceRequest) {
+ if (operDeviceRequest == null) {
+ throw new IllegalArgumentException("设备操作请求参数不能为空");
+ }
+ }
+
+ /**
+ * 创建HTTP POST请求
+ */
+ private HttpPost createHttpPost(OperDeviceRequest operDeviceRequest) {
+ HttpPost httpPost = new HttpPost(algorithmServiceUrl);
+
+ try {
+ // 将请求对象转换为JSON字符串
+ String jsonRequest = convertToJson(operDeviceRequest);
+
+ // 设置请求体为JSON
+ StringEntity entity = new StringEntity(jsonRequest, ContentType.APPLICATION_JSON);
+ httpPost.setEntity(entity);
+
+ // 设置请求头
+ httpPost.setHeader("Accept", "application/json");
+ httpPost.setHeader("Content-Type", "application/json; charset=UTF-8");
+
+ } catch (Exception e) {
+ log.error("创建HTTP POST请求失败,请求参数: {}", operDeviceRequest, e);
+ throw new RuntimeException("创建HTTP POST请求失败", e);
+ }
+
+ return httpPost;
+ }
+
+ /**
+ * 将请求对象转换为JSON字符串
+ */
+ private String convertToJson(OperDeviceRequest request) throws JsonProcessingException {
+ ObjectMapper objectMapper = new ObjectMapper();
+ return objectMapper.writeValueAsString(request);
+ }
+
+ /**
+ * 执行设备操作请求
+ */
+ private DrawLinesResponse executeOcrRequest(HttpPost httpPost) throws IOException {
+ log.info("开始调用设备操作服务识别");
+
+ try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
+ return processHttpResponse(response);
+ }
+ }
+
+ /**
+ * 处理HTTP响应
+ */
+ private DrawLinesResponse processHttpResponse(CloseableHttpResponse response) throws IOException {
+ log.info("响应内容:{}",response);
+ int statusCode = response.getStatusLine().getStatusCode();
+ String responseBody = getResponseBody(response);
+
+ log.info("设备操作服务响应状态: {}", statusCode);
+ log.debug("设备操作服务响应内容: {}", responseBody); // 改为debug级别,避免日志过大
+
+ // 检查HTTP状态码
+ if (statusCode != 200) {
+ log.error("设备操作服务HTTP请求失败,状态码: {}, 响应: {}", statusCode, responseBody);
+ return null;
+ }
+
+ DrawLinesResponse drawLinesResponse = parseResponseBody(responseBody);
+ return drawLinesResponse;
+ }
+
+ /**
+ * 获取响应体
+ */
+ private String getResponseBody(CloseableHttpResponse response) throws IOException {
+ HttpEntity entity = response.getEntity();
+ return EntityUtils.toString(entity, UTF_8);
+ }
+
+ /**
+ * 解析响应体
+ */
+ private DrawLinesResponse parseResponseBody(String responseBody) throws IOException {
+ try {
+ return objectMapper.readValue(responseBody, DrawLinesResponse.class);
+ } catch (IOException e) {
+ log.error("解析设备操作请求响应失败,响应内容: {}", responseBody, e);
+ return null;
+ }
+ }
+
+ /**
+ * 清理资源
+ */
+ private void cleanupResources(HttpPost httpPost) {
+ // 清理HTTP连接
+ if (httpPost != null) {
+ httpPost.releaseConnection();
+ }
+
+ }
+
+ /**
+ * 关闭HTTP客户端
+ */
+ public void close() {
+ try {
+ if (httpClient != null) {
+ httpClient.close();
+ log.info("设备操作服务HTTP客户端已关闭");
+ }
+ } catch (IOException e) {
+ log.error("关闭HTTP客户端失败", e);
+ }
+ }
+
+ /**
+ * 销毁方法,用于Spring容器关闭时调用
+ */
+ public void destroy() {
+ close();
+ }
+}
diff --git a/bonus-algorithm/src/main/java/com/bonus/algorithm/service/EndVideoService.java b/bonus-algorithm/src/main/java/com/bonus/algorithm/service/EndVideoService.java
new file mode 100644
index 0000000..da8278e
--- /dev/null
+++ b/bonus-algorithm/src/main/java/com/bonus/algorithm/service/EndVideoService.java
@@ -0,0 +1,186 @@
+package com.bonus.algorithm.service;
+
+import com.bonus.common.domain.algorithm.dto.OperDeviceRequest;
+import com.bonus.common.domain.algorithm.vo.DrawLinesResponse;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+
+/**
+ * @className: EndVideoService
+ * @author: cwchen
+ * @date: 2026-01-08-9:26
+ * @version: 1.0
+ * @description: 结束录制视频接口调用-业务逻辑层
+ */
+@Service(value = "EndVideoService")
+@Slf4j
+public class EndVideoService {
+
+ private static final String UTF_8 = "UTF-8";
+
+ @Value("${algorithm.service.endVideoUrl}")
+ private String algorithmServiceUrl;
+
+ @Value("${algorithm.service.timeout}")
+ private int timeout;
+
+ private final CloseableHttpClient httpClient;
+ private final ObjectMapper objectMapper;
+
+ public EndVideoService() {
+ RequestConfig requestConfig = RequestConfig.custom()
+ .setConnectTimeout(timeout)
+ .setSocketTimeout(timeout)
+ .setConnectionRequestTimeout(timeout)
+ .build();
+
+ this.httpClient = HttpClients.custom()
+ .setDefaultRequestConfig(requestConfig)
+ .build();
+ this.objectMapper = new ObjectMapper();
+ }
+
+ /**
+ * 调用结束录制视频接口
+ *
+ * @return 结束录制视频响应结果
+ * @throws IOException 当结束录制视频服务调用失败时抛出
+ */
+ public DrawLinesResponse callEndVideoService() throws IOException {
+ HttpPost httpPost = null;
+ try {
+ httpPost = createHttpPost();
+ return executeOcrRequest(httpPost);
+ } catch (IOException e) {
+ log.error("调用结束录制视频服务失败", e);
+ return null;
+ } finally {
+ cleanupResources(httpPost);
+ }
+ }
+
+ /**
+ * 创建HTTP POST请求
+ */
+ private HttpPost createHttpPost() {
+ HttpPost httpPost = new HttpPost(algorithmServiceUrl);
+
+ try {
+ // 设置请求头
+ httpPost.setHeader("Accept", "application/json");
+ httpPost.setHeader("Content-Type", "application/json; charset=UTF-8");
+
+ } catch (Exception e) {
+ log.error("创建HTTP POST请求失败", e);
+ throw new RuntimeException("创建HTTP POST请求失败", e);
+ }
+
+ return httpPost;
+ }
+
+ /**
+ * 将请求对象转换为JSON字符串
+ */
+ private String convertToJson(OperDeviceRequest request) throws JsonProcessingException {
+ ObjectMapper objectMapper = new ObjectMapper();
+ return objectMapper.writeValueAsString(request);
+ }
+
+ /**
+ * 执行结束录制视频请求
+ */
+ private DrawLinesResponse executeOcrRequest(HttpPost httpPost) throws IOException {
+ log.info("开始调用结束录制视频服务识别");
+
+ try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
+ return processHttpResponse(response);
+ }
+ }
+
+ /**
+ * 处理HTTP响应
+ */
+ private DrawLinesResponse processHttpResponse(CloseableHttpResponse response) throws IOException {
+ log.info("响应内容:{}",response);
+ int statusCode = response.getStatusLine().getStatusCode();
+ String responseBody = getResponseBody(response);
+
+ log.info("结束录制视频服务响应状态: {}", statusCode);
+ log.debug("结束录制视频服务响应内容: {}", responseBody); // 改为debug级别,避免日志过大
+
+ // 检查HTTP状态码
+ if (statusCode != 200) {
+ log.error("结束录制视频服务HTTP请求失败,状态码: {}, 响应: {}", statusCode, responseBody);
+ return null;
+ }
+
+ DrawLinesResponse drawLinesResponse = parseResponseBody(responseBody);
+ return drawLinesResponse;
+ }
+
+ /**
+ * 获取响应体
+ */
+ private String getResponseBody(CloseableHttpResponse response) throws IOException {
+ HttpEntity entity = response.getEntity();
+ return EntityUtils.toString(entity, UTF_8);
+ }
+
+ /**
+ * 解析响应体
+ */
+ private DrawLinesResponse parseResponseBody(String responseBody) throws IOException {
+ try {
+ return objectMapper.readValue(responseBody, DrawLinesResponse.class);
+ } catch (IOException e) {
+ log.error("解析结束录制视频请求响应失败,响应内容: {}", responseBody, e);
+ return null;
+ }
+ }
+
+ /**
+ * 清理资源
+ */
+ private void cleanupResources(HttpPost httpPost) {
+ // 清理HTTP连接
+ if (httpPost != null) {
+ httpPost.releaseConnection();
+ }
+
+ }
+
+ /**
+ * 关闭HTTP客户端
+ */
+ public void close() {
+ try {
+ if (httpClient != null) {
+ httpClient.close();
+ log.info("结束录制视频服务HTTP客户端已关闭");
+ }
+ } catch (IOException e) {
+ log.error("关闭HTTP客户端失败", e);
+ }
+ }
+
+ /**
+ * 销毁方法,用于Spring容器关闭时调用
+ */
+ public void destroy() {
+ close();
+ }
+}
diff --git a/bonus-algorithm/src/main/java/com/bonus/algorithm/service/StartVideoService.java b/bonus-algorithm/src/main/java/com/bonus/algorithm/service/StartVideoService.java
new file mode 100644
index 0000000..48f7cf8
--- /dev/null
+++ b/bonus-algorithm/src/main/java/com/bonus/algorithm/service/StartVideoService.java
@@ -0,0 +1,188 @@
+package com.bonus.algorithm.service;
+
+import com.bonus.common.domain.algorithm.dto.OperDeviceRequest;
+import com.bonus.common.domain.algorithm.vo.DrawLinesResponse;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+
+/**
+ * @className: StartVideoService
+ * @author: cwchen
+ * @date: 2026-01-08-9:26
+ * @version: 1.0
+ * @description: 开始录制视频接口调用-业务逻辑层
+ */
+@Service(value = "StartVideoService")
+@Slf4j
+public class StartVideoService {
+
+ private static final String UTF_8 = "UTF-8";
+
+ @Value("${algorithm.service.startVideoUrl}")
+ private String algorithmServiceUrl;
+
+ @Value("${algorithm.service.timeout}")
+ private int timeout;
+
+ private final CloseableHttpClient httpClient;
+ private final ObjectMapper objectMapper;
+
+ public StartVideoService() {
+ RequestConfig requestConfig = RequestConfig.custom()
+ .setConnectTimeout(timeout)
+ .setSocketTimeout(timeout)
+ .setConnectionRequestTimeout(timeout)
+ .build();
+
+ this.httpClient = HttpClients.custom()
+ .setDefaultRequestConfig(requestConfig)
+ .build();
+ this.objectMapper = new ObjectMapper();
+ }
+
+ /**
+ * 调用录制视频接口
+ *
+ * @return 录制视频响应结果
+ * @throws IOException 当录制视频服务调用失败时抛出
+ */
+ public DrawLinesResponse callStartVideoService() throws IOException {
+
+ HttpPost httpPost = null;
+ try {
+ httpPost = createHttpPost();
+ return executeOcrRequest(httpPost);
+ } catch (IOException e) {
+ log.error("调用录制视频服务失败", e);
+ return null;
+ } finally {
+ cleanupResources(httpPost);
+ }
+ }
+
+ /**
+ * 创建HTTP POST请求
+ */
+ private HttpPost createHttpPost() {
+ HttpPost httpPost = new HttpPost(algorithmServiceUrl);
+
+ try {
+
+ // 设置请求头
+ httpPost.setHeader("Accept", "application/json");
+ httpPost.setHeader("Content-Type", "application/json; charset=UTF-8");
+
+ } catch (Exception e) {
+ log.error("创建HTTP POST请求失败", e);
+ throw new RuntimeException("创建HTTP POST请求失败", e);
+ }
+
+ return httpPost;
+ }
+
+ /**
+ * 将请求对象转换为JSON字符串
+ */
+ private String convertToJson(OperDeviceRequest request) throws JsonProcessingException {
+ ObjectMapper objectMapper = new ObjectMapper();
+ return objectMapper.writeValueAsString(request);
+ }
+
+ /**
+ * 执行录制视频请求
+ */
+ private DrawLinesResponse executeOcrRequest(HttpPost httpPost) throws IOException {
+ log.info("开始调用录制视频服务识别");
+
+ try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
+ return processHttpResponse(response);
+ }
+ }
+
+ /**
+ * 处理HTTP响应
+ */
+ private DrawLinesResponse processHttpResponse(CloseableHttpResponse response) throws IOException {
+ log.info("响应内容:{}",response);
+ int statusCode = response.getStatusLine().getStatusCode();
+ String responseBody = getResponseBody(response);
+
+ log.info("录制视频服务响应状态: {}", statusCode);
+ log.debug("录制视频服务响应内容: {}", responseBody); // 改为debug级别,避免日志过大
+
+ // 检查HTTP状态码
+ if (statusCode != 200) {
+ log.error("录制视频服务HTTP请求失败,状态码: {}, 响应: {}", statusCode, responseBody);
+ return null;
+ }
+
+ DrawLinesResponse drawLinesResponse = parseResponseBody(responseBody);
+ return drawLinesResponse;
+ }
+
+ /**
+ * 获取响应体
+ */
+ private String getResponseBody(CloseableHttpResponse response) throws IOException {
+ HttpEntity entity = response.getEntity();
+ return EntityUtils.toString(entity, UTF_8);
+ }
+
+ /**
+ * 解析响应体
+ */
+ private DrawLinesResponse parseResponseBody(String responseBody) throws IOException {
+ try {
+ return objectMapper.readValue(responseBody, DrawLinesResponse.class);
+ } catch (IOException e) {
+ log.error("解析录制视频请求响应失败,响应内容: {}", responseBody, e);
+ return null;
+ }
+ }
+
+ /**
+ * 清理资源
+ */
+ private void cleanupResources(HttpPost httpPost) {
+ // 清理HTTP连接
+ if (httpPost != null) {
+ httpPost.releaseConnection();
+ }
+
+ }
+
+ /**
+ * 关闭HTTP客户端
+ */
+ public void close() {
+ try {
+ if (httpClient != null) {
+ httpClient.close();
+ log.info("录制视频服务HTTP客户端已关闭");
+ }
+ } catch (IOException e) {
+ log.error("关闭HTTP客户端失败", e);
+ }
+ }
+
+ /**
+ * 销毁方法,用于Spring容器关闭时调用
+ */
+ public void destroy() {
+ close();
+ }
+}
diff --git a/bonus-common/src/main/java/com/bonus/common/domain/algorithm/dto/OperDeviceRequest.java b/bonus-common/src/main/java/com/bonus/common/domain/algorithm/dto/OperDeviceRequest.java
new file mode 100644
index 0000000..0575b81
--- /dev/null
+++ b/bonus-common/src/main/java/com/bonus/common/domain/algorithm/dto/OperDeviceRequest.java
@@ -0,0 +1,23 @@
+package com.bonus.common.domain.algorithm.dto;
+
+import lombok.Data;
+
+/**
+ * @className:OperDeviceRequest
+ * @author:cwchen
+ * @date:2026-01-19-9:29
+ * @version:1.0
+ * @description:设备操作请求实体
+ */
+@Data
+public class OperDeviceRequest {
+
+ /**
+ * 为1(工作模式)或者2(休眠模式)
+ */
+ private Long mode;
+ /**
+ * 为true(开启报警)或者false(关闭报警)
+ */
+ private boolean alarm;
+}
diff --git a/bonus-common/src/main/java/com/bonus/common/domain/algorithm/vo/DeviceDetailResponse.java b/bonus-common/src/main/java/com/bonus/common/domain/algorithm/vo/DeviceDetailResponse.java
new file mode 100644
index 0000000..23f183a
--- /dev/null
+++ b/bonus-common/src/main/java/com/bonus/common/domain/algorithm/vo/DeviceDetailResponse.java
@@ -0,0 +1,61 @@
+package com.bonus.common.domain.algorithm.vo;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import java.util.Objects;
+
+/**
+ * @className: DeviceDetailResponse
+ * @author: cwchen
+ * @date: 2026-01-08-9:35
+ * @version: 1.0
+ * @description: 设备详情响应-实体
+ */
+@Data
+public class DeviceDetailResponse {
+
+ @JsonProperty("code")
+ private Integer code; // 状态码
+
+ @JsonProperty("status")
+ private String status;
+
+ /**
+ * 对应 JSON 中的 "data" 对象
+ */
+ @JsonProperty("data")
+ private DeviceInfo data;
+
+ public boolean isSuccess() {
+ return Objects.equals(status, "success") && code != null && code == 200;
+ }
+
+ /**
+ * 内部类,用于映射 data 字段
+ * 使用静态内部类 (static class) 方便实例化
+ */
+ @Data
+ public static class DeviceInfo {
+
+ @JsonProperty("battery_cap")
+ private Integer batteryCap; // 电量百分比 (0-100)
+
+ @JsonProperty("time_to_full_min")
+ private Integer timeToFullMin; // 预计充满剩余分钟数
+
+ @JsonProperty("time_to_empty_min")
+ private Integer timeToEmptyMin; // 预计放空剩余分钟数
+
+ @JsonProperty("status_code")
+ private Integer statusCode; // 电池内部状态码
+
+ @JsonProperty("temperature_c")
+ private Double temperatureC; // 温度 (摄氏度),注意用 Double 接收小数
+
+ @JsonProperty("system_mode")
+ private Integer systemMode; // 当前模式 (1: WORK, 2: SLEEP)
+
+ @JsonProperty("alarm_flag")
+ private Integer alarmFlag; // 报警标志 (0: 无, 1: 报警)
+ }
+}
\ No newline at end of file
diff --git a/bonus-common/src/main/java/com/bonus/common/domain/algorithm/vo/DrawLinesResponse.java b/bonus-common/src/main/java/com/bonus/common/domain/algorithm/vo/DrawLinesResponse.java
index c618a1b..d0c8fa9 100644
--- a/bonus-common/src/main/java/com/bonus/common/domain/algorithm/vo/DrawLinesResponse.java
+++ b/bonus-common/src/main/java/com/bonus/common/domain/algorithm/vo/DrawLinesResponse.java
@@ -28,6 +28,6 @@ public class DrawLinesResponse {
private String status;
public boolean isSuccess() {
- return Objects.equals(status, "success") && code != null && code == 200;
+ return code == 200;
}
}
diff --git a/bonus-common/src/main/java/com/bonus/common/domain/data/dto/NetworkEthernetDto.java b/bonus-common/src/main/java/com/bonus/common/domain/data/dto/NetworkEthernetDto.java
index cc8b33b..cb8c794 100644
--- a/bonus-common/src/main/java/com/bonus/common/domain/data/dto/NetworkEthernetDto.java
+++ b/bonus-common/src/main/java/com/bonus/common/domain/data/dto/NetworkEthernetDto.java
@@ -48,8 +48,11 @@ public class NetworkEthernetDto {
*/
@NotBlank(message = "IP地址不能为空", groups = {NOENABLE.class})
@Length(max = 32, message = "IP地址字符长度不能超过32", groups = {NOENABLE.class})
- @Pattern(regexp = "^(?=.{1,255}$)(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$|^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$",
- message = "IP地址格式不正确(需为有效IP或域名)", groups = {NOENABLE.class})
+ @Pattern(
+ regexp = "^(?:(?=.{1,255}$)(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,63}))|(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))$",
+ message = "IP地址格式不正确(需为有效IPv4地址或域名)",
+ groups = {NOENABLE.class}
+ )
private String ipAddress;
/**
@@ -58,19 +61,18 @@ public class NetworkEthernetDto {
@NotBlank(message = "子网掩码不能为空", groups = {NOENABLE.class})
@Length(max = 15, message = "子网掩码长度不正确", groups = {NOENABLE.class})
@Pattern(
- regexp = "^(254|252|248|240|224|192|128|0)\\.0\\.0\\.0$|^(255\\.(254|252|248|240|224|192|128|0)\\.0\\.0)$|^(255\\.255\\.(254|252|248|240|224|192|128|0)\\.0)$|^(255\\.255\\.255\\.(255|254|252|248|240|224|192|128|0))$",
+ regexp = "^(?:(?:254|252|248|240|224|192|128|0)\\.0\\.0\\.0)|(?:255\\.(?:254|252|248|240|224|192|128|0)\\.0\\.0)|(?:255\\.255\\.(?:254|252|248|240|224|192|128|0)\\.0)|(?:255\\.255\\.255\\.(?:255|254|252|248|240|224|192|128|0))$",
message = "子网掩码格式不正确",
groups = {NOENABLE.class}
)
private String subnetMask;
/**
- * 默认网关
+ * 默认网关 (允许为空,有内容则校验格式)
*/
- @NotBlank(message = "默认网关不能为空", groups = {NOENABLE.class})
- @Length(max = 15, message = "默认网关长度不正确", groups = {NOENABLE.class})
@Pattern(
- regexp = "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$",
+ // 将原正则包裹在 (?:原正则)? 中,或者利用 @Pattern 默认不校验 null 的特性
+ regexp = "^$|^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$",
message = "默认网关格式不正确",
groups = {NOENABLE.class}
)
@@ -79,7 +81,6 @@ public class NetworkEthernetDto {
/**
* DNS
*/
- @NotBlank(message = "DNS不能为空", groups = {NOENABLE.class})
@Length(max = 512, message = "DNS字符长度不能超过512", groups = {NOENABLE.class})
private String dns;
diff --git a/bonus-common/src/main/java/com/bonus/common/domain/data/dto/ParamsDto.java b/bonus-common/src/main/java/com/bonus/common/domain/data/dto/ParamsDto.java
index d58d638..1fa867a 100644
--- a/bonus-common/src/main/java/com/bonus/common/domain/data/dto/ParamsDto.java
+++ b/bonus-common/src/main/java/com/bonus/common/domain/data/dto/ParamsDto.java
@@ -16,7 +16,9 @@ import java.util.Date;
@Data
public class ParamsDto {
- /**车辆类型 1.油车 2.新能源*/
+ /**
+ * 车辆类型 1.油车 2.新能源
+ */
private String carType;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@@ -27,16 +29,24 @@ public class ParamsDto {
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
- /**设备名称*/
+ /**
+ * 设备名称
+ */
private String equipmentName;
- /**设备ID*/
+ /**
+ * 设备ID
+ */
private Long systemId = 1L;
- /**告警状态*/
+ /**
+ * 告警状态
+ */
private String alarmStatus;
- /**系统设置ID*/
+ /**
+ * 系统设置ID
+ */
private Long systemSettingId;
/**
@@ -48,4 +58,17 @@ public class ParamsDto {
* SIM_ID
*/
private Long simId;
+
+ /**
+ * 为1(工作模式)或者2(休眠模式)
+ */
+ private String mode;
+ /**
+ * 为true(开启报警)或者false(关闭报警)
+ */
+ private boolean alarm;
+
+ /**录制状态 1.开始录制 2.结束录制*/
+ private String recordingType;
+
}
diff --git a/bonus-data/src/main/java/com/bonus/data/mapper/DISystemInfoMapper.java b/bonus-data/src/main/java/com/bonus/data/mapper/DISystemInfoMapper.java
index 3d02458..61c102f 100644
--- a/bonus-data/src/main/java/com/bonus/data/mapper/DISystemInfoMapper.java
+++ b/bonus-data/src/main/java/com/bonus/data/mapper/DISystemInfoMapper.java
@@ -1,5 +1,6 @@
package com.bonus.data.mapper;
+import com.bonus.common.domain.algorithm.vo.DeviceDetailResponse;
import com.bonus.common.domain.data.dto.ParamsDto;
import com.bonus.common.domain.data.vo.StorageVo;
import com.bonus.common.domain.data.vo.SystemInfoVo;
@@ -49,4 +50,13 @@ public interface DISystemInfoMapper {
* @date 2025/12/24 15:07
*/
void updateSystemStorage(StorageVo vo);
+
+ /**
+ * 更新设备详情
+ * @param data
+ * @return void
+ * @author cwchen
+ * @date 2026/1/19 13:48
+ */
+ void updateSystemInfo(DeviceDetailResponse.DeviceInfo data);
}
diff --git a/bonus-data/src/main/java/com/bonus/data/service/DISystemInfoService.java b/bonus-data/src/main/java/com/bonus/data/service/DISystemInfoService.java
index 0456f0a..3e3ea60 100644
--- a/bonus-data/src/main/java/com/bonus/data/service/DISystemInfoService.java
+++ b/bonus-data/src/main/java/com/bonus/data/service/DISystemInfoService.java
@@ -1,5 +1,6 @@
package com.bonus.data.service;
+import com.bonus.common.domain.algorithm.vo.DeviceDetailResponse;
import com.bonus.common.domain.data.dto.ParamsDto;
import com.bonus.common.domain.data.vo.StorageVo;
import com.bonus.common.domain.data.vo.SystemInfoVo;
@@ -47,4 +48,13 @@ public interface DISystemInfoService {
* @date 2025/12/24 15:06
*/
void updateSystemStorage(StorageVo vo);
+
+ /**
+ * 更新设备详情
+ * @param data
+ * @return void
+ * @author cwchen
+ * @date 2026/1/19 13:48
+ */
+ void updateSystemInfo(DeviceDetailResponse.DeviceInfo data);
}
diff --git a/bonus-data/src/main/java/com/bonus/data/service/impl/DSystemInfoServiceImpl.java b/bonus-data/src/main/java/com/bonus/data/service/impl/DSystemInfoServiceImpl.java
index 86b0540..d935ee7 100644
--- a/bonus-data/src/main/java/com/bonus/data/service/impl/DSystemInfoServiceImpl.java
+++ b/bonus-data/src/main/java/com/bonus/data/service/impl/DSystemInfoServiceImpl.java
@@ -1,5 +1,6 @@
package com.bonus.data.service.impl;
+import com.bonus.common.domain.algorithm.vo.DeviceDetailResponse;
import com.bonus.common.domain.data.dto.ParamsDto;
import com.bonus.common.domain.data.vo.StorageVo;
import com.bonus.common.domain.data.vo.SystemInfoVo;
@@ -41,4 +42,9 @@ public class DSystemInfoServiceImpl implements DISystemInfoService {
public void updateSystemStorage(StorageVo vo) {
diSystemInfoMapper.updateSystemStorage(vo);
}
+
+ @Override
+ public void updateSystemInfo(DeviceDetailResponse.DeviceInfo data) {
+ diSystemInfoMapper.updateSystemInfo(data);
+ }
}
diff --git a/bonus-data/src/main/resources/mapper/DSystemInfoMapper.xml b/bonus-data/src/main/resources/mapper/DSystemInfoMapper.xml
index 1cd8251..035bac8 100644
--- a/bonus-data/src/main/resources/mapper/DSystemInfoMapper.xml
+++ b/bonus-data/src/main/resources/mapper/DSystemInfoMapper.xml
@@ -42,4 +42,14 @@
UPDATE tb_system_info SET tf_storage = #{capacity} WHERE system_id = #{systemId}
+
+
+ UPDATE tb_system_info
+ SET
+ equipment_status = #{systemMode},
+ equipment_operating_temperature = #{temperatureC},
+ alarm_status = #{alarmFlag},
+ battery_power = #{batteryCap}
+ WHERE system_id = 1
+
diff --git a/bonus-quartz/pom.xml b/bonus-quartz/pom.xml
index 46ef1c4..6672484 100644
--- a/bonus-quartz/pom.xml
+++ b/bonus-quartz/pom.xml
@@ -34,7 +34,16 @@
com.bonus
bonus-common
-
+
+ com.bonus
+ bonus-algorithm
+ 3.9.0
+ compile
+
+
+ com.bonus
+ bonus-data
+
diff --git a/bonus-quartz/src/main/java/com/bonus/quartz/task/DeviceDetailTask.java b/bonus-quartz/src/main/java/com/bonus/quartz/task/DeviceDetailTask.java
new file mode 100644
index 0000000..2570ffe
--- /dev/null
+++ b/bonus-quartz/src/main/java/com/bonus/quartz/task/DeviceDetailTask.java
@@ -0,0 +1,59 @@
+package com.bonus.quartz.task;
+import com.bonus.algorithm.service.DeviceDetailService;
+import com.bonus.common.domain.algorithm.vo.DeviceDetailResponse;
+import com.bonus.data.service.DISystemInfoService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Objects;
+
+/**
+ * @className:DeviceDetailTask
+ * @author:cwchen
+ * @date:2025-12-30-17:07
+ * @version:1.0
+ * @description:设备详情任务类
+ */
+@Slf4j
+@Component(value = "DeviceDetailTask")
+public class DeviceDetailTask {
+
+ @Resource(name = "DeviceDetailService")
+ private DeviceDetailService detailService;
+
+ @Resource(name = "DISystemInfoService")
+ private DISystemInfoService diSystemInfoService;
+
+
+ /**
+ * 每天十分钟执行一次清理任务
+ * cron 表达式: 秒 分 时 日 月 周
+ */
+ public void getDeviceDetail() {
+ try {
+ DeviceDetailResponse deviceDetailResponse = detailService.callDeviceDetailService();
+ if (Objects.nonNull(deviceDetailResponse)) {
+ if(deviceDetailResponse.isSuccess()){
+ log.info("设备详情:{}",deviceDetailResponse);
+ DeviceDetailResponse.DeviceInfo data = deviceDetailResponse.getData();
+ // 处理温度
+ BigDecimal bd = new BigDecimal(Double.toString(data.getTemperatureC()));
+ bd = bd.setScale(2, RoundingMode.HALF_UP);
+ double result = bd.doubleValue();
+ data.setTemperatureC(result);
+ // 处理设备状态
+ if(Objects.equals(data.getSystemMode(),"2")){
+ data.setSystemMode(0);
+ }
+ diSystemInfoService.updateSystemInfo(data);
+ }
+ }
+ } catch (IOException e) {
+ log.error("设备详情更新失败",e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index baef741..e6b390b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
bonus
http://www.bonus.vip
- 智能投标系统
+ 车辆道路计数仪
3.9.0