diff --git a/yudao-module-camera/yudao-module-camera-biz/pom.xml b/yudao-module-camera/yudao-module-camera-biz/pom.xml
index a45d24c..91368d9 100644
--- a/yudao-module-camera/yudao-module-camera-biz/pom.xml
+++ b/yudao-module-camera/yudao-module-camera-biz/pom.xml
@@ -30,11 +30,14 @@
- com.sun.jna
+ net.java.dev.jna
jna
- 1.0
- system
- ${project.basedir}/src/main/resources/libs/jna.jar
+ 5.13.0
+
+
+ net.java.dev.jna
+ jna-platform
+ 5.13.0
diff --git a/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/conf/MyInitializer.java b/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/conf/MyInitializer.java
index 00a3e60..6deb5b7 100644
--- a/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/conf/MyInitializer.java
+++ b/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/conf/MyInitializer.java
@@ -27,8 +27,8 @@ import java.util.Objects;
public class MyInitializer {
-
- private final OkHttpClient client = new OkHttpClient();
+ @Resource
+ private OkHttpClient client ;
@Resource
@@ -43,6 +43,8 @@ public class MyInitializer {
myInitializer.checkAndAddRtspProxies();
}
+
+
@Scheduled(fixedRate = 30000) // 每分钟执行一次
public void checkAndAddRtspProxies() {
diff --git a/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/cameraio/CameraIoController.java b/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/cameraio/CameraIoController.java
index 2299788..e69de29 100644
--- a/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/cameraio/CameraIoController.java
+++ b/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/cameraio/CameraIoController.java
@@ -1,144 +0,0 @@
-package cn.iocoder.yudao.module.camera.controller.admin.cameraio;
-
-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.camera.controller.admin.cameraio.vo.CameraIoPageReqVO;
-import cn.iocoder.yudao.module.camera.controller.admin.cameraio.vo.CameraIoRespVO;
-import cn.iocoder.yudao.module.camera.controller.admin.cameraio.vo.CameraIoSaveReqVO;
-import cn.iocoder.yudao.module.camera.dal.dataobject.camera.CameraDO;
-import cn.iocoder.yudao.module.camera.dal.dataobject.cameraio.CameraIoDO;
-import cn.iocoder.yudao.module.camera.lib.camera.CameraModFactory;
-import cn.iocoder.yudao.module.camera.service.camera.CameraService;
-import cn.iocoder.yudao.module.camera.service.cameraio.CameraIoService;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import jakarta.annotation.Resource;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.validation.Valid;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-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("/admin-api/camera/camera-io")
-@Validated
-public class CameraIoController {
-
- @Resource
- private CameraIoService cameraIoService;
-
- @Resource
- private CameraModFactory cameraModFactory;
-
-
- @Resource
- private CameraService cameraService;
-
- @PostMapping("/create")
- @Operation(summary = "创建相机预置点位")
- @PreAuthorize("@ss.hasPermission('camera:camera-io:create')")
- public CommonResult createCameraIo(@Valid @RequestBody CameraIoSaveReqVO createReqVO) {
- List list = cameraIoService.list(new QueryWrapper()
- .eq("camera_id", createReqVO.getCameraId()));
- Integer ptzId = list.stream().map(CameraIoDO::getPtzId).max(Integer::compareTo).orElse(0)+1;
- createReqVO.setPtzId(ptzId);
- int i= cameraIoService.createCameraIo(createReqVO);
- CameraDO cameraIoDO = cameraService.getById(createReqVO.getCameraId());
- cameraModFactory.get(cameraIoDO.getType()).ptz(createReqVO.getPtzId(),createReqVO.getName(),createReqVO.getCameraId());
-
- return success(i);
- }
-
- @PostMapping("/callPtz")
- @Operation(summary = "调用预置点位")
- @PreAuthorize("@ss.hasPermission('camera:camera-io:callPtz')")
- public CommonResult callPtz(@Valid @RequestBody CameraIoSaveReqVO createReqVO) {
-
- CameraDO cameraIoDO = cameraService.getById(createReqVO.getCameraId());
- cameraModFactory.get(cameraIoDO.getType()).toPtz(createReqVO.getPtzId(),createReqVO.getCameraId());
- return success(cameraIoService.createCameraIo(createReqVO));
- }
-
- /**
- * 创建或覆盖相机预置点位 必须穿ptzId
- * @param createReqVO
- * @return
- */
- @PostMapping("/overwritePtz")
- @Operation(summary = "创建或覆盖相机预置点位")
- @PreAuthorize("@ss.hasPermission('camera:camera-io:overwritePtz')")
- public CommonResult overwritePtz(@Valid @RequestBody CameraIoSaveReqVO createReqVO) {
- CameraDO cameraIoDO = cameraService.getById(createReqVO.getCameraId());
- cameraModFactory.get(cameraIoDO.getType()).ptz(createReqVO.getPtzId(),createReqVO.getName(),createReqVO.getCameraId());
- return success(cameraIoService.createCameraIo(createReqVO));
- }
-
- @GetMapping("/list")
- @Operation(summary = "获得相机预置点位分页")
- @PreAuthorize("@ss.hasPermission('camera:camera-io:query')")
- public CommonResult> list(@Valid CameraIoPageReqVO pageReqVO) {
- List pageResult = cameraIoService.list(new QueryWrapper().eq("camera_id", pageReqVO.getCameraId()).orderByAsc("id"));
- return success(BeanUtils.toBean(pageResult, CameraIoRespVO.class));
- }
-
- @DeleteMapping("/delete")
- @Operation(summary = "删除相机预置点位")
- @Parameter(name = "id", description = "编号", required = true)
- @PreAuthorize("@ss.hasPermission('camera:camera-io:delete')")
- public CommonResult deleteCameraIo(@RequestParam("id") Integer id) {
- cameraIoService.deleteCameraIo(id);
- return success(true);
- }
- @PutMapping("/update")
- @Operation(summary = "更新相机预置点位")
- @PreAuthorize("@ss.hasPermission('camera:camera-io:update')")
- public CommonResult updateCameraIo(@Valid @RequestBody CameraIoSaveReqVO updateReqVO) {
- cameraIoService.updateCameraIo(updateReqVO);
- return success(true);
- }
-
-
- @GetMapping("/get")
- @Operation(summary = "获得相机预置点位")
- @Parameter(name = "id", description = "编号", required = true, example = "1024")
- @PreAuthorize("@ss.hasPermission('camera:camera-io:query')")
- public CommonResult getCameraIo(@RequestParam("id") Integer id) {
- CameraIoDO cameraIo = cameraIoService.getCameraIo(id);
- return success(BeanUtils.toBean(cameraIo, CameraIoRespVO.class));
- }
-
- @GetMapping("/page")
- @Operation(summary = "获得相机预置点位分页")
- @PreAuthorize("@ss.hasPermission('camera:camera-io:query')")
- public CommonResult> getCameraIoPage(@Valid CameraIoPageReqVO pageReqVO) {
- PageResult pageResult = cameraIoService.getCameraIoPage(pageReqVO);
- return success(BeanUtils.toBean(pageResult, CameraIoRespVO.class));
- }
-
- @GetMapping("/export-excel")
- @Operation(summary = "导出相机预置点位 Excel")
- @PreAuthorize("@ss.hasPermission('camera:camera-io:export')")
- @ApiAccessLog(operateType = EXPORT)
- public void exportCameraIoExcel(@Valid CameraIoPageReqVO pageReqVO,
- HttpServletResponse response) throws IOException {
- pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
- List list = cameraIoService.getCameraIoPage(pageReqVO).getList();
- // 导出 Excel
- ExcelUtils.write(response, "相机预置点位.xls", "数据", CameraIoRespVO.class,
- BeanUtils.toBean(list, CameraIoRespVO.class));
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/lib/camera/CameraModFactory.java b/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/lib/camera/CameraModFactory.java
index 8ccbc35..9a80fca 100644
--- a/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/lib/camera/CameraModFactory.java
+++ b/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/lib/camera/CameraModFactory.java
@@ -24,6 +24,8 @@ public class CameraModFactory {
return hikControlModuleImpl; // 获取 HikControlModuleImpl 单例实例
} else if (type == 0) {
return dhControlModuleImpl; // 获取 DhControlModuleImpl 单例实例
+ }else if (type == 2) {
+ return dhControlModuleImpl; // 获取 DhControlModuleImpl 单例实例
}
// 默认返回 HikControlModuleImpl
return hikControlModuleImpl;
diff --git a/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/service/channel/CameraChannel.java b/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/service/channel/CameraChannel.java
index 7579dac..278f4b7 100644
--- a/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/service/channel/CameraChannel.java
+++ b/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/service/channel/CameraChannel.java
@@ -7,9 +7,9 @@ public class CameraChannel {
public static String generateHikvisionRTSPUrl(String ip, int port, String channel, String username, String password) {
return String.format("rtsp://%s:%s@%s:%d/Streaming/channels/%s", username, password, ip, port, channel);
}
-
+//默认主码流
public static String generateDahuaRTSPUrl(String ip, int port, String channel, String username, String password) {
- return String.format("rtsp://%s:%s@%s:%d/cam/realmonitor?channel=%s", username, password, ip, port, channel);
+ return String.format("rtsp://%s:%s@%s:%d/cam/realmonitor?channel=%s&subtype=0", username, password, ip, port, channel);
}
public static String getRtspUrl(String ip, int port, String channel, String username, String password, int type) {
String rtspUrl = "";
diff --git a/yudao-module-camera/yudao-module-camera-biz/src/test/java/cn/iocoder/yudao/module/camera/service/camera/CameraServiceImplTest.java b/yudao-module-camera/yudao-module-camera-biz/src/test/java/cn/iocoder/yudao/module/camera/service/camera/CameraServiceImplTest.java
index 2ce8164..e69de29 100644
--- a/yudao-module-camera/yudao-module-camera-biz/src/test/java/cn/iocoder/yudao/module/camera/service/camera/CameraServiceImplTest.java
+++ b/yudao-module-camera/yudao-module-camera-biz/src/test/java/cn/iocoder/yudao/module/camera/service/camera/CameraServiceImplTest.java
@@ -1,18 +0,0 @@
-package cn.iocoder.yudao.module.camera.service.camera;
-
-import cn.iocoder.yudao.module.camera.framework.netty.NettyClient;
-import org.junit.jupiter.api.Test;
-import org.springframework.context.annotation.Import;
-
-/**
- * {@link CameraServiceImpl} 的单元测试类
- *
- * @author 芋道源码
- */
-@Import(NettyClient.class)
-public class CameraServiceImplTest{
- @Test
- public void testCreateCamera_success() {
-
- }
-}
\ No newline at end of file
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/pom.xml b/yudao-module-logistics/yudao-module-logistics-biz/pom.xml
index 4fc80e3..4abe238 100644
--- a/yudao-module-logistics/yudao-module-logistics-biz/pom.xml
+++ b/yudao-module-logistics/yudao-module-logistics-biz/pom.xml
@@ -35,11 +35,14 @@
- com.sun.jna
+ net.java.dev.jna
jna
- 1.0
- system
- ${project.basedir}/src/main/resources/libs/jna.jar
+ 5.13.0
+
+
+ net.java.dev.jna
+ jna-platform
+ 5.13.0
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/config/OkHttpClientConfig.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/config/OkHttpClientConfig.java
new file mode 100644
index 0000000..e36112e
--- /dev/null
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/config/OkHttpClientConfig.java
@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.camera.config;
+
+import okhttp3.ConnectionPool;
+import okhttp3.OkHttpClient;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.concurrent.TimeUnit;
+
+@Configuration
+public class OkHttpClientConfig {
+
+ @Bean
+ public OkHttpClient okHttpClient() {
+ return new OkHttpClient.Builder()
+ .connectTimeout(30, TimeUnit.SECONDS)
+ .readTimeout(30, TimeUnit.SECONDS)
+ .writeTimeout(30, TimeUnit.SECONDS)
+ .connectionPool(new ConnectionPool(10, 3, TimeUnit.MINUTES))
+ // 可添加拦截器,如日志、Token 添加等
+// .addInterceptor(chain -> {
+// Request request = chain.request().newBuilder()
+// .addHeader("Authorization", "Bearer your_token")
+// .build();
+// return chain.proceed(request);
+// })
+ .build();
+ }
+}
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/Hik3D/Hik3DController.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/Hik3D/Hik3DController.java
new file mode 100644
index 0000000..a934031
--- /dev/null
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/Hik3D/Hik3DController.java
@@ -0,0 +1,70 @@
+package cn.iocoder.yudao.module.camera.controller.admin.Hik3D;
+
+import cn.iocoder.yudao.module.camera.dal.entity.HikPythonEntity;
+import cn.iocoder.yudao.module.camera.service.Hik3D.HikFlaskApiService;
+import cn.iocoder.yudao.module.camera.service.checklog.CheckLogService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.annotation.security.PermitAll;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+
+@Tag(name = "管理后台 - hik3D识别")
+@RestController
+@RequestMapping("/logistics/Hik3DController")
+@Validated
+public class Hik3DController {
+ @Resource
+ HikFlaskApiService hikFlaskApiService;
+
+ @Resource
+ private CheckLogService checkLogService;
+
+ @PostMapping("/updateConfig")
+ @Operation(summary = "updateConfig")
+ @ResponseBody
+ @PermitAll
+ public HikPythonEntity updateConfig(){
+ String baseUrl = "http://127.0.0.1:5000";
+ try {
+ return hikFlaskApiService.updateConfig(baseUrl);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+
+ @PostMapping("/addTemplate")
+ @Operation(summary = "updateConfig")
+ @ResponseBody
+ @PermitAll
+ public HikPythonEntity addTemplate(@RequestBody HikPythonEntity hikPythonEntity){
+ String baseUrl = "http://127.0.0.1:5000";
+ try {
+ return hikFlaskApiService.addTemplate(hikPythonEntity.getType(), hikPythonEntity,baseUrl);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @PostMapping("/picComputeAll")
+ @Operation(summary = "picComputeAll")
+ @ResponseBody
+ @PermitAll
+ public HikPythonEntity picComputeAll(@RequestBody HikPythonEntity hikPythonEntity){
+ String baseUrl = "http://127.0.0.1:5000";
+ try {
+ return hikFlaskApiService.picComputeAll(hikPythonEntity.getType(),baseUrl);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+
+
+}
\ No newline at end of file
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/cameraio/CameraIoController.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/cameraio/CameraIoController.java
index bfaf778..3130037 100644
--- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/cameraio/CameraIoController.java
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/cameraio/CameraIoController.java
@@ -69,7 +69,7 @@ public class CameraIoController {
CameraDO cameraIoDO = cameraService.getById(createReqVO.getCameraId());
cameraModFactory.get(cameraIoDO.getType()).toPtz(createReqVO.getPtzId(),createReqVO.getCameraId());
- return success(cameraIoService.createCameraIo(createReqVO));
+ return success(cameraIoDO.getPtzId());
}
/**
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/sensorgun/vo/SensorGunPageReqVO.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/sensorgun/vo/SensorGunPageReqVO.java
index 9142eb9..ac1dbb1 100644
--- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/sensorgun/vo/SensorGunPageReqVO.java
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/sensorgun/vo/SensorGunPageReqVO.java
@@ -19,6 +19,9 @@ public class SensorGunPageReqVO extends PageParam {
@Schema(description = "ip")
private String ip;
+ @Schema(description = "type")
+ private Integer type;
+
@Schema(description = "端口")
private Integer port;
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/sensorgun/vo/SensorGunSaveReqVO.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/sensorgun/vo/SensorGunSaveReqVO.java
index d7823ec..5f22cec 100644
--- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/sensorgun/vo/SensorGunSaveReqVO.java
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/sensorgun/vo/SensorGunSaveReqVO.java
@@ -19,6 +19,9 @@ public class SensorGunSaveReqVO {
@Schema(description = "ip")
private String ip;
+ @Schema(description = "type")
+ private Integer type;
+
@Schema(description = "端口")
private Integer port;
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/dataobject/street/SensorGunDO.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/dataobject/street/SensorGunDO.java
index 55dac76..a4fd435 100644
--- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/dataobject/street/SensorGunDO.java
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/dataobject/street/SensorGunDO.java
@@ -1,8 +1,11 @@
package cn.iocoder.yudao.module.camera.dal.dataobject.sensorgun;
-import lombok.*;
-import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+import org.glassfish.jaxb.core.v2.TODO;
/**
* 扫码枪 DO
@@ -17,7 +20,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
@Builder
@NoArgsConstructor
@AllArgsConstructor
-public class SensorGunDO extends BaseDO {
+public class SensorGunDO extends BaseDO {
/**
* id
@@ -28,6 +31,11 @@ public class SensorGunDO extends BaseDO {
* 巷道id
*/
private Integer streetId;
+
+ /**
+ * type
+ */
+ private Integer type;
/**
* 左右
*
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/HikPythonEntity.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/HikPythonEntity.java
new file mode 100644
index 0000000..7f1c2bd
--- /dev/null
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/HikPythonEntity.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.camera.dal.entity;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class HikPythonEntity {
+ private String type;
+ private String sn;
+ private Integer direction;
+ private String width;
+ private String length;
+ private Integer height;
+ private Integer min_area;
+ private Boolean lack;
+// 是否有缺
+ private Integer tolerance;
+ private String status;
+ private List colors;
+
+}
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/Hik3D/HikFlaskApiService.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/Hik3D/HikFlaskApiService.java
new file mode 100644
index 0000000..0cee629
--- /dev/null
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/Hik3D/HikFlaskApiService.java
@@ -0,0 +1,171 @@
+package cn.iocoder.yudao.module.camera.service.Hik3D;
+
+import cn.iocoder.yudao.module.camera.dal.dataobject.resources.URLResourcesDo;
+import cn.iocoder.yudao.module.camera.dal.dataobject.stock.StockDO;
+import cn.iocoder.yudao.module.camera.dal.dataobject.street.StreetDO;
+import cn.iocoder.yudao.module.camera.dal.entity.HikPythonEntity;
+import cn.iocoder.yudao.module.camera.dal.entity.ScanData;
+import cn.iocoder.yudao.module.camera.framework.netty.ksec.KsecDataInfo;
+import cn.iocoder.yudao.module.camera.service.resources.URLResourcesService;
+import cn.iocoder.yudao.module.camera.service.scan.ScanService;
+import cn.iocoder.yudao.module.system.service.dict.DictDataService;
+import com.google.gson.Gson;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.*;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.util.Objects;
+
+@Slf4j
+@Service("HikFlaskApiService")
+public class HikFlaskApiService implements ScanService {
+
+ private static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
+ @Resource
+ private OkHttpClient client;
+ private final Gson gson = new Gson();
+
+
+ @Resource
+ private DictDataService dictDataService;
+ // ================== /config/update ==================
+
+ /**
+ * 调用 /config/update 接口,触发配置更新
+ */
+ public HikPythonEntity updateConfig(String baseUrl) throws IOException {
+ Request request = new Request.Builder()
+ .url(baseUrl + "/config/update")
+ .get()
+ .build();
+
+ try (Response response = client.newCall(request).execute()) {
+ if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
+
+ String responseBody = Objects.requireNonNull(response.body()).string();
+ return gson.fromJson(responseBody, HikPythonEntity.class);
+ }
+ }
+
+ // ================== /api/addTemplate ==================
+
+ /**
+ * 调用 /api/addTemplate 接口,保存模板配置
+ *
+ * @param templateType 模板类型(type 字段)
+ * @param data 模板数据(JSON 格式 Map)
+ */
+ public HikPythonEntity addTemplate(String templateType, HikPythonEntity data,String baseUrl) throws IOException {
+
+ if (templateType == null || templateType.isEmpty()) {
+ throw new IllegalArgumentException("Missing 'type' field");
+ }
+
+ String json = gson.toJson(data);
+ RequestBody body = RequestBody.create(json, JSON);
+
+ Request request = new Request.Builder()
+ .url(baseUrl + "/api/addTemplate")
+ .post(body)
+ .build();
+
+ try (Response response = client.newCall(request).execute()) {
+ if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
+
+ String responseBody = Objects.requireNonNull(response.body()).string();
+ return gson.fromJson(responseBody, HikPythonEntity.class);
+ }
+ }
+
+ // ================== /api/picComputeAll ==================
+
+ /**
+ * 调用 /api/picComputeAll 接口,批量处理所有设备图片
+ */
+ public HikPythonEntity picComputeAll(String type,String baseUrl) throws IOException {
+ HikPythonEntity requestData = new HikPythonEntity();
+ requestData.setType(type);
+
+ String json = gson.toJson(requestData);
+ RequestBody body = RequestBody.create(json, JSON);
+
+ Request request = new Request.Builder()
+ .url(baseUrl + "/api/picComputeAll")
+ .post(body)
+ .build();
+
+ try (Response response = client.newCall(request).execute()) {
+ if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
+
+ String responseBody = Objects.requireNonNull(response.body()).string();
+ return gson.fromJson(responseBody, HikPythonEntity.class);
+ }
+ }
+
+ // ================== /api/picCompute ==================
+
+ /**
+ * 调用 /api/picCompute 接口,处理单个设备图片
+ */
+ public HikPythonEntity picCompute(String sn, String type,String baseUrl) throws IOException {
+ HikPythonEntity requestData =new HikPythonEntity();
+ requestData.setSn(sn);
+ requestData.setType(type);
+
+ String json = gson.toJson(requestData);
+ RequestBody body = RequestBody.create(json, JSON);
+
+ Request request = new Request.Builder()
+ .url(baseUrl + "/api/picCompute")
+ .post(body)
+ .build();
+
+ try (Response response = client.newCall(request).execute()) {
+ if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
+
+ String responseBody = Objects.requireNonNull(response.body()).string();
+ return gson.fromJson(responseBody, HikPythonEntity.class);
+ }
+ }
+
+ @Resource
+ URLResourcesService urlResourcesService;
+// 识别结果是正常或缺件
+ @Override
+ public ScanData scan(StreetDO streetDO, KsecDataInfo dataInfo, StockDO stockDO) {
+ ScanData scanData = new ScanData();
+
+
+ String urlPath ="http://"+streetDO.getPlcIp() + ":" + dictDataService.parseDictData("Hik3DApi", "port").getValue();
+ String picPath ="http://"+streetDO.getPlcIp() + ":" + dictDataService.parseDictData("Hik3DApi", "picPath").getValue();
+ try {
+
+ scanData.setCode("缺件");
+ HikPythonEntity hikPythonEntity = picComputeAll(dataInfo.getCategory(),urlPath);
+ if (hikPythonEntity != null){
+ if (hikPythonEntity.getLack()!= null && hikPythonEntity.getLack()) {
+ }else {
+ scanData.setCode("正常");
+ }
+ if (hikPythonEntity.getColors() != null && hikPythonEntity.getColors().size() > 0) {
+ for (String color:hikPythonEntity.getColors()){
+ if (color.startsWith(".")) {
+ color = color.substring(1);
+ }
+ color = picPath + color ;
+ urlResourcesService.save(URLResourcesDo.builder().url(color).uuid( stockDO.getCheckPic()).type("1").little("缺件拍照").build());
+ }
+ }
+ }
+ return scanData;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+// return null;
+ }
+
+ // ================== 测试方法 ==================
+
+}
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderService.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderService.java
index 3f8e096..c1f6f3c 100644
--- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderService.java
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderService.java
@@ -13,7 +13,6 @@ import jakarta.validation.Valid;
* @author 芋道源码
*/
public interface OrderService {
- void check(OrderDO orderDO);
/**
* 创建随行记录
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderServiceImpl.java
index eb7a47c..54efb5a 100644
--- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderServiceImpl.java
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderServiceImpl.java
@@ -2,22 +2,19 @@ package cn.iocoder.yudao.module.camera.service.order;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.camera.controller.admin.checklog.vo.CheckLogSaveReqVO;
import cn.iocoder.yudao.module.camera.controller.admin.order.vo.OrderPageReqVO;
import cn.iocoder.yudao.module.camera.controller.admin.order.vo.OrderSaveReqVO;
-import cn.iocoder.yudao.module.camera.controller.admin.stock.vo.StockSaveReqVO;
-import cn.iocoder.yudao.module.camera.dal.dataobject.checklog.CheckLogDO;
import cn.iocoder.yudao.module.camera.dal.dataobject.order.OrderDO;
-import cn.iocoder.yudao.module.camera.dal.dataobject.sensorgun.SensorGunDO;
-import cn.iocoder.yudao.module.camera.dal.dataobject.stock.StockDO;
import cn.iocoder.yudao.module.camera.dal.dataobject.street.StreetDO;
-import cn.iocoder.yudao.module.camera.dal.entity.echarts.*;
+import cn.iocoder.yudao.module.camera.dal.entity.echarts.Axis;
+import cn.iocoder.yudao.module.camera.dal.entity.echarts.EChartsOption;
+import cn.iocoder.yudao.module.camera.dal.entity.echarts.Legend;
+import cn.iocoder.yudao.module.camera.dal.entity.echarts.Series;
import cn.iocoder.yudao.module.camera.dal.mysql.order.OrderMapper;
import cn.iocoder.yudao.module.camera.dal.mysql.sensorgun.SensorGunMapper;
import cn.iocoder.yudao.module.camera.service.checklog.CheckLogService;
import cn.iocoder.yudao.module.camera.service.stock.StockService;
import cn.iocoder.yudao.module.camera.service.street.StreetService;
-import cn.iocoder.yudao.module.camera.service.threeInOneCode.ScanningGun;
import cn.iocoder.yudao.module.camera.service.threeInOneCode.SpecificationsAndOCR;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import de.danielbechler.util.Strings;
@@ -64,58 +61,6 @@ public class OrderServiceImpl implements OrderService {
StockService stockService;
- @Override
- public void check(OrderDO orderDO) {
- StreetDO streetDo = streetService.getStreetByPlcId(orderDO.getSrmNumber());
- if(streetDo==null){
- return;
- }
- CheckLogSaveReqVO checkLogSaveReqVO = new CheckLogSaveReqVO();
- List sensorGunDOS = sensorGunMapper.selectListByStreetId(streetDo.getId());
- //扫码枪校验
- String sensorGunCode = "";
- for (SensorGunDO sensorGunDO : sensorGunDOS){
- sensorGunCode = ScanningGun.readOCR(sensorGunDO.getIp(), sensorGunDO.getPort(),"start",3);
- }
-
- //灵闪校验
- Map readOCR = SpecificationsAndOCR.readOCR(streetDo.getPlcIp(), streetDo.getPlcPort());
- String code = readOCR.get("ORC");
- StockDO stockDoc =stockService.getOne(new QueryWrapper()
- .eq("street_id",streetDo.getId())
- .eq("side",orderDO.getFromSide())
- .eq("direction",orderDO.getFromDirection())
- .eq("`column`",orderDO.getFromColumn())
- .eq("`row`",orderDO.getFromRow())
- .eq("separation",orderDO.getFromSeparation())
- );
- if(stockDoc==null){
- stockDoc.setCode(sensorGunCode);
- stockDoc.setStorageCode(code);
- stockService.updateById(stockDoc);
- }else {
-
- //图片保存和记录
- StockSaveReqVO stockSaveReqVO = new StockSaveReqVO();
- stockSaveReqVO.setOrderNum(orderDO.getTaskId());
- stockSaveReqVO.setCode(sensorGunCode);
- stockSaveReqVO.setStreetId(streetDo.getId());
- stockSaveReqVO.setSide(orderDO.getFromSide());
- stockSaveReqVO.setDirection(orderDO.getFromDirection());
- stockSaveReqVO.setColumn(orderDO.getFromColumn());
- stockSaveReqVO.setRow(orderDO.getFromRow());
- stockSaveReqVO.setStorageCode(code);
- stockService.createStock(stockSaveReqVO);
- }
-
-
-
- CheckLogDO checkLogDoc = new CheckLogDO();
- checkLogService.save(checkLogDoc);
-
-
- }
-
@Override
public Long createOrder(OrderSaveReqVO createReqVO) {
// 插入
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/plc/PLCServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/plc/PLCServiceImpl.java
index c28aec4..0716b33 100644
--- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/plc/PLCServiceImpl.java
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/plc/PLCServiceImpl.java
@@ -26,6 +26,7 @@ import cn.iocoder.yudao.module.camera.service.checklog.CheckLogService;
import cn.iocoder.yudao.module.camera.service.resources.URLResourcesService;
import cn.iocoder.yudao.module.camera.service.scan.ScanServiceFactory;
import cn.iocoder.yudao.module.camera.service.stock.StockService;
+import cn.iocoder.yudao.module.camera.service.streamingMedia.ZLMediaKitService;
import cn.iocoder.yudao.module.camera.service.street.StreetService;
import cn.iocoder.yudao.module.camera.service.threeInOneCode.ScanningGun;
import cn.iocoder.yudao.module.camera.util.PathUtil;
@@ -502,7 +503,8 @@ public class PLCServiceImpl implements PLCService {
//OrderRealtime.startOrder(street.getId(), plcCmdInfo.getOrderNum());
}
}
-
+ @Resource
+ ZLMediaKitService zLMediaKitService;
public void orderStop(KsecDataInfo ksecDataInfo) {
Map dictDataList = dictDataService.getDictDataList("camera_conf");
LocalDateTime endTime = LocalDateTime.now();
@@ -535,7 +537,8 @@ public class PLCServiceImpl implements PLCService {
if (street.getCamera1Id() != null) {
String pathSrc = PathUtil.createFileName(ksecDataInfo, street, "B2-1", ".mp4");
- String path = cameraVideo(street.getCamera1Id(), pathSrc, order.getCreateTime(), endDownLoadTime, dictDataList);
+ String path = zLMediaKitService.startRecord("live", street.getCamera1Id().toString());
+// String path = cameraVideo(street.getCamera1Id(), pathSrc, order.getCreateTime(), endDownLoadTime, dictDataList);
update.setVideoPath1(path);
}
if (street.getCamera2Id() != null) {
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/ScanGunScanServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/ScanGunScanServiceImpl.java
index 1acd0d8..5d53e38 100644
--- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/ScanGunScanServiceImpl.java
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/ScanGunScanServiceImpl.java
@@ -5,7 +5,9 @@ import cn.iocoder.yudao.module.camera.dal.dataobject.stock.StockDO;
import cn.iocoder.yudao.module.camera.dal.dataobject.street.StreetDO;
import cn.iocoder.yudao.module.camera.dal.entity.ScanData;
import cn.iocoder.yudao.module.camera.framework.netty.ksec.KsecDataInfo;
+import cn.iocoder.yudao.module.camera.service.sensorgun.CognexSocket;
import cn.iocoder.yudao.module.camera.service.sensorgun.SensorGunService;
+import cn.iocoder.yudao.module.camera.service.sensorgun.SickSocket;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
@@ -87,7 +89,13 @@ public class ScanGunScanServiceImpl implements ScanService{
if (sensorGun == null) {
log.error("no sensor gun config in database ,street id:{},direction:{}", streetDO.getId(), dataInfo.getFromDirection());
} else {
- trayCode = readOCR(sensorGun.getIp(), sensorGun.getPort());
+// sick扫码
+ if (sensorGun.getType() == 1){
+ trayCode = SickSocket.readOCR(sensorGun.getIp(), sensorGun.getPort());
+ }else {
+// 康耐视扫码
+ trayCode = CognexSocket.readOCR(sensorGun.getIp(), sensorGun.getPort());
+ }
}
scanData.setCode(trayCode);
return scanData;
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/ScanServiceFactory.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/ScanServiceFactory.java
index 5e44166..b7e3e24 100644
--- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/ScanServiceFactory.java
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/ScanServiceFactory.java
@@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.camera.dal.dataobject.stock.StockDO;
import cn.iocoder.yudao.module.camera.dal.dataobject.street.StreetDO;
import cn.iocoder.yudao.module.camera.dal.entity.ScanData;
import cn.iocoder.yudao.module.camera.framework.netty.ksec.KsecDataInfo;
+import cn.iocoder.yudao.module.camera.service.Hik3D.HikFlaskApiService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -21,8 +22,13 @@ public class ScanServiceFactory {
private YoloServiceImpl yoloService;
@Resource
private OpencvServiceImpl opencvService;
+ @Resource
+ private HikFlaskApiService hikFlaskApiService;
+
+// 返回的ScanData的code会将作为扫描结果,如果和wms的一致,则记录为成功
+// 图片保存将在scan方法中实现
public ScanData scan(String type, StreetDO streetDO, KsecDataInfo dataInfo, StockDO stockDO) {
@@ -47,6 +53,9 @@ public class ScanServiceFactory {
case "5":
return opencvService.scan(streetDO, dataInfo, stockDO);
+ // hik3d识别扫码
+ case "6":
+ return hikFlaskApiService.scan(streetDO, dataInfo, stockDO);
// 默认情况处理
default:
return null;
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/sensorgun/CognexSocket.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/sensorgun/CognexSocket.java
new file mode 100644
index 0000000..b6e9290
--- /dev/null
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/sensorgun/CognexSocket.java
@@ -0,0 +1,81 @@
+package cn.iocoder.yudao.module.camera.service.sensorgun;
+
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.nio.charset.StandardCharsets;
+
+@Slf4j
+public class CognexSocket {
+
+ private static final Logger tcpLogger = LoggerFactory.getLogger("sick");
+ public static String readOCR(String ip,int port){
+ Socket socket = new Socket();
+ String code = "NOREAD";
+ OutputStream os = null;
+ InputStream is = null;
+ try {
+ socket.connect(new InetSocketAddress(ip,port),3000);
+ os = socket.getOutputStream();
+ is = socket.getInputStream();
+ int i = 0;
+ while ("NOREAD".equals(code) && i <= 4){
+ writeCmd(os);
+ code = read(is);
+ tcpLogger.info("count:{},ip:{},code:{}",i,ip,code);
+ if(code!= null){
+ code = code.replace("\\n","");
+ }
+ i++;
+ }
+ } catch (IOException e) {
+ tcpLogger.error("sick time out,ip:{},info:{}",ip,e);
+ log.error("sick time out,ip:{},info:{}",ip,e);
+ }finally {
+ if(os != null){
+ try {
+ os.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if(is != null){
+ try {
+ is.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ try {
+ socket.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ return code;
+ }
+ }
+
+ private static void writeCmd(OutputStream os) throws IOException {
+ String startCmd = "+";
+ byte[]bytes = startCmd.getBytes(StandardCharsets.UTF_8);
+ os.write(bytes);
+ try {
+ Thread.sleep(300);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ startCmd = "-";
+ bytes = startCmd.getBytes(StandardCharsets.UTF_8);
+ os.write(bytes);
+ }
+
+ private static String read(InputStream inStream) throws IOException {
+ BufferedReader bd = new BufferedReader(new InputStreamReader(inStream));
+ return bd.readLine();
+ }
+}
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/sensorgun/SensorGunService.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/sensorgun/SensorGunService.java
index c6e37e6..ecd8c89 100644
--- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/sensorgun/SensorGunService.java
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/sensorgun/SensorGunService.java
@@ -52,4 +52,5 @@ public interface SensorGunService extends IService {
*/
PageResult getSensorGunPage(SensorGunPageReqVO pageReqVO);
+ String scan(Integer id);
}
\ No newline at end of file
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/sensorgun/SensorGunServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/sensorgun/SensorGunServiceImpl.java
index ae611fb..7a6ac3d 100644
--- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/sensorgun/SensorGunServiceImpl.java
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/sensorgun/SensorGunServiceImpl.java
@@ -68,4 +68,20 @@ public class SensorGunServiceImpl extends ServiceImpl list);
+ void deleteRecordDirectory(String app, String stream, String period);
+}
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/streamingMedia/ZLMediaKitServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/streamingMedia/ZLMediaKitServiceImpl.java
new file mode 100644
index 0000000..6867dcc
--- /dev/null
+++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/streamingMedia/ZLMediaKitServiceImpl.java
@@ -0,0 +1,218 @@
+package cn.iocoder.yudao.module.camera.service.streamingMedia;
+
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import cn.iocoder.yudao.module.camera.dal.dataobject.camera.CameraDO;
+import cn.iocoder.yudao.module.camera.dal.zlm.RtspSessionResponse;
+import cn.iocoder.yudao.module.camera.service.channel.CameraChannel;
+import cn.iocoder.yudao.module.system.service.dict.DictDataService;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.HttpUrl;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@Service
+@Validated
+@Slf4j
+public class ZLMediaKitServiceImpl implements ZLMediaKitService{
+
+ @Resource
+ private OkHttpClient client ;
+ @Resource
+ private DictDataService dictDataService;
+
+ @Override
+ public String startRecord(String app, String cameraId) {
+
+ String zlmApiSecret = dictDataService.parseDictData("ZLMediaKit_conf", "secret").getValue();
+ Map addParams = new HashMap<>();
+ addParams.put("secret", zlmApiSecret);
+ addParams.put("type", "1");//0为hls,1为mp4
+ addParams.put("vhost", "__defaultVhost__");
+ addParams.put("app", "live");
+ addParams.put("stream","camera"+ cameraId);
+// addParams.put("url", CameraChannel.getRtspUrl(camera.getIp(), camera.getRtspPort(), camera.getChannel(), camera.getUser(), camera.getPassword(),camera.getType()));
+ sendHttp(addParams, "startRecord");
+ log.info("startRecord camera:"+cameraId);
+ String path = checkHiddenFilesInDirectory(app,cameraId);
+ ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
+
+ Runnable task = () -> {
+ stopRecord(app,cameraId);
+
+ };
+
+ // 延迟5分钟后执行停止任务,不会将录像文件录5分钟
+ long delay =5;
+ scheduler.schedule(task, delay, TimeUnit.MINUTES);
+ return path;
+ }
+
+ // 新增方法:检查指定文件夹下是否有以.为开头的文件
+ public String checkHiddenFilesInDirectory(String app, String cameraId) {
+
+ String mp4SavePath = dictDataService.parseDictData("ZLMediaKit_conf", "mp4SavePath").getValue();
+ // 获取当前日期
+ LocalDate currentDate = LocalDate.now();
+
+ // 定义日期格式
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+ // 格式化日期
+ String formattedDate = currentDate.format(formatter);
+
+ String directoryPath = mp4SavePath+"record/"+app+"/camera"+cameraId+"/"+formattedDate;
+
+
+ Path directory = Paths.get(directoryPath);
+ List hiddenFiles = new ArrayList<>();
+
+ try (Stream paths = Files.walk(directory, 1)) {
+ hiddenFiles= paths
+ .filter(Files::isRegularFile)
+ .map(Path::getFileName)
+ .map(Path::toString)
+ .filter(name -> name.startsWith("."))
+ .collect(Collectors.toList());
+ return hiddenFiles.isEmpty() ? "" : "record/"+app+"/camera"+cameraId+"/"+formattedDate+"/"+removeLeadingDot(hiddenFiles.get(0));
+ } catch (IOException e) {
+ e.printStackTrace();
+ hiddenFiles= List.of(); // 返回空列表
+ }
+ return "";
+ }
+
+ public static String removeLeadingDot(String input) {
+ if (input == null || input.isEmpty()) {
+ return input;
+ }
+ if (input.startsWith(".")) {
+ return input.substring(1);
+ }
+ return input;
+ }
+ @Override
+ public void stopRecord(String app, String stream) {
+
+ String zlmApiSecret = dictDataService.parseDictData("ZLMediaKit_conf", "secret").getValue();
+ Map addParams = new HashMap<>();
+ addParams.put("secret", zlmApiSecret);
+ addParams.put("type", "1");//0为hls,1为mp4
+ addParams.put("vhost", "__defaultVhost__");
+ addParams.put("app", "live");
+ addParams.put("stream","camera"+ stream);
+// addParams.put("url", CameraChannel.getRtspUrl(camera.getIp(), camera.getRtspPort(), camera.getChannel(), camera.getUser(), camera.getPassword(),camera.getType()));
+ sendHttp(addParams, "stopRecord");
+
+ }
+
+ @Override
+ public void zlmConf( List list) {
+
+ String zlmApiUrl = dictDataService.parseDictData("ZLMediaKit_conf", "Apiurl").getValue();
+ String zlmApiSecret = dictDataService.parseDictData("ZLMediaKit_conf", "secret").getValue();
+ try {
+ // 查询当前的RTSP拉流代理
+ Map queryParams = new HashMap<>();
+ queryParams.put("secret", zlmApiSecret);
+ String queryUrl = buildUrl(zlmApiUrl +"getMediaList",null , queryParams);
+ String response = get(queryUrl);
+ RtspSessionResponse rtspSessionResponse = JsonUtils.parseObject(response, RtspSessionResponse.class);
+ // 检查并添加缺失的RTSP代理
+ for (CameraDO entry : list) {
+ boolean isRtspProxyExists = false;
+ if (rtspSessionResponse != null && rtspSessionResponse.getData()!=null && rtspSessionResponse.getData().size()>0) {
+ for (RtspSessionResponse.RtspSession rtspSession : rtspSessionResponse.getData()){
+ if (rtspSession.getApp().equals("live")&&rtspSession.getStream().equals("camera"+entry.getId())){
+ isRtspProxyExists = true;
+ break;
+ }
+ }
+ }
+ //不存在则重新注入
+ if (!isRtspProxyExists){
+ try {
+
+ addRtspProxy(entry, zlmApiUrl, zlmApiSecret);
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ }
+
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public void addRtspProxy(CameraDO camera, String zlmApiUrl, String zlmApiSecret) {
+ Map addParams = new HashMap<>();
+ addParams.put("secret", zlmApiSecret);
+ addParams.put("vhost", "__defaultVhost__");
+ addParams.put("app", "live");
+ addParams.put("stream","camera"+ camera.getId());
+ addParams.put("url", CameraChannel.getRtspUrl(camera.getIp(), camera.getRtspPort(), camera.getChannel(), camera.getUser(), camera.getPassword(),camera.getType()));
+ String addUrl = buildUrl(zlmApiUrl+"addStreamProxy",null , addParams);
+ String response = null;
+ try {
+ response = get(addUrl);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ System.out.println("Add RTSP Proxy Response: " + response);
+ }
+ @Override
+ public void deleteRecordDirectory(String app, String stream, String period) {
+
+ }
+ public void sendHttp(Map queryParams ,String url){
+
+ String zlmApiUrl = dictDataService.parseDictData("ZLMediaKit_conf", "Apiurl").getValue();
+ try {
+ // 查询当前的RTSP拉流代理
+ String queryUrl = buildUrl(zlmApiUrl +url,null , queryParams);
+ String response = get(queryUrl);
+ RtspSessionResponse rtspSessionResponse = JsonUtils.parseObject(response, RtspSessionResponse.class);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private String buildUrl(String baseUrl, String action, Map params) {
+ HttpUrl.Builder urlBuilder = HttpUrl.parse(baseUrl).newBuilder();
+
+ for (Map.Entry entry : params.entrySet()) {
+ urlBuilder.addQueryParameter(entry.getKey(), entry.getValue().toString());
+ }
+ return urlBuilder.build().toString();
+ }
+
+ private String get(String url) throws IOException {
+ Request request = new Request.Builder()
+ .url(url)
+ .build();
+ try (Response response = client.newCall(request).execute()) {
+ return response.body().string();
+ }
+ }
+}
diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/util/RedisUtil.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/util/RedisUtil.java
deleted file mode 100644
index 93a6030..0000000
--- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/util/RedisUtil.java
+++ /dev/null
@@ -1,747 +0,0 @@
-package cn.iocoder.yudao.module.camera.util;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.stereotype.Component;
-import org.springframework.util.CollectionUtils;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
-/**
- *
- * @author 王赛超 基于spring和redis的redisTemplate工具类 针对所有的hash 都是以h开头的方法 针对所有的Set 都是以s开头的方法 不含通用方法 针对所有的List 都是以l开头的方法
- */
-@Component
-@Slf4j
-public class RedisUtil {
- @Autowired
- private RedisTemplate redisTemplate;
-
- // =============================common============================
- /**
- * 指定缓存失效时间
- *
- * @param key
- * 键
- * @param time
- * 时间(秒)
- * @return
- */
- public boolean expire(String key, long time) {
- try {
- if (time > 0) {
- redisTemplate.expire(key, time, TimeUnit.SECONDS);
- }
- return true;
- } catch (Exception e) {
- log.error(key, e);
- return false;
- }
- }
-
- /**
- * 根据key 获取过期时间
- *
- * @param key
- * 键 不能为null
- * @return 时间(秒) 返回0代表为永久有效
- */
- public long getExpire(String key) {
- return redisTemplate.getExpire(key, TimeUnit.SECONDS);
- }
-
- /**
- * 判断key是否存在
- *
- * @param key
- * 键
- * @return true 存在 false不存在
- */
- public boolean hasKey(String key) {
- try {
- return redisTemplate.hasKey(key);
- } catch (Exception e) {
- log.error(key, e);
- return false;
- }
- }
-
- /**
- * 删除缓存
- *
- * @param key
- * 可以传一个值 或多个
- */
- @SuppressWarnings("unchecked")
- public void del(String... key) {
- if (key != null && key.length > 0) {
- if (key.length == 1) {
- redisTemplate.delete(key[0]);
- } else {
- redisTemplate.delete((Collection) CollectionUtils.arrayToList(key));
- }
- }
- }
-
- // ============================String=============================
- /**
- * 普通缓存获取
- *
- * @param key
- * 键
- * @return 值
- */
- public Object get(String key) {
- return key == null ? null : redisTemplate.opsForValue().get(key);
- }
-
- /**
- * 普通缓存放入
- *
- * @param key
- * 键
- * @param value
- * 值
- * @return true成功 false失败
- */
- public boolean set(String key, Object value) {
- try {
- redisTemplate.opsForValue().set(key, value);
- return true;
- } catch (Exception e) {
- log.error(key, e);
- return false;
- }
-
- }
-
- /**
- * 普通缓存放入并设置时间
- *
- * @param key
- * 键
- * @param value
- * 值
- * @param time
- * 时间(秒) time要大于0 如果time小于等于0 将设置无限期
- * @return true成功 false 失败
- */
- public boolean set(String key, Object value, long time) {
- try {
- if (time > 0) {
- redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
- } else {
- set(key, value);
- }
- return true;
- } catch (Exception e) {
- log.error(key, e);
- return false;
- }
- }
-
- /**
- * 递增 适用场景: https://blog.csdn.net/y_y_y_k_k_k_k/article/details/79218254 高并发生成订单号,秒杀类的业务逻辑等。。
- *
- * @param key
- * 键
- * 要增加几(大于0)
- * @return
- */
- public long incr(String key, long delta) {
- if (delta < 0) {
- throw new RuntimeException("递增因子必须大于0");
- }
- return redisTemplate.opsForValue().increment(key, delta);
- }
-
- /**
- * 递减
- *
- * @param key
- * 键
- * 要减少几(小于0)
- * @return
- */
- public long decr(String key, long delta) {
- if (delta < 0) {
- throw new RuntimeException("递减因子必须大于0");
- }
- return redisTemplate.opsForValue().increment(key, -delta);
- }
-
- // ================================Map=================================
- /**
- * HashGet
- *
- * @param key
- * 键 不能为null
- * @param item
- * 项 不能为null
- * @return 值
- */
- public Object hget(String key, String item) {
- return redisTemplate.opsForHash().get(key, item);
- }
-
- /**
- * 获取hashKey对应的所有键值
- *
- * @param key
- * 键
- * @return 对应的多个键值
- */
- public Map