摄像头设置是否开启全天录像接口
This commit is contained in:
@ -1,9 +1,11 @@
|
||||
package org.dromara.job.ys7;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.manager.ys7manager.Ys7Manager;
|
||||
import org.dromara.manager.ys7manager.vo.Ys7QueryDeviceResponseVo;
|
||||
import org.dromara.other.domain.OthYs7Device;
|
||||
import org.dromara.other.service.IOthYs7DeviceService;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
@ -41,4 +43,19 @@ public class IncSyncYs7DeviceData {
|
||||
}
|
||||
}
|
||||
|
||||
//同步摄像头全天录像开关状态
|
||||
// 每 1 分钟执行一次
|
||||
@Scheduled(cron = "1 0 0 * * ?")
|
||||
// @Scheduled(cron = "0 */10 * * * ?")
|
||||
public void getEnable() {
|
||||
log.info("定时同步摄像头设备数据");
|
||||
List<OthYs7Device> ys7DeviceList = ys7DeviceService.getBaseMapper().selectList(new LambdaQueryWrapper<OthYs7Device>().orderByDesc(OthYs7Device::getCreateTime));
|
||||
Boolean result = ys7DeviceService.saveOrUpdateEnableByDeviceList(ys7DeviceList);
|
||||
if (result) {
|
||||
log.info("定时同步摄像头设备数据成功");
|
||||
} else {
|
||||
log.info("没有需要定时同步的设备");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -71,4 +71,13 @@ public interface Ys7Constant {
|
||||
*/
|
||||
String getDeviceLappVideoUrlByPost = "https://open.ys7.com/api/lapp/v2/live/address/get";
|
||||
|
||||
/**
|
||||
* 设置全天录像开关 POST
|
||||
*/
|
||||
String UPDATEONEKEYSWITCH = "https://open.ys7.com/api/lapp/device/fullday/record/switch/set";
|
||||
/**
|
||||
* 获取全天录像开关状态 POST
|
||||
*/
|
||||
String GETONEKEYSWITCHSTATUS = "https://open.ys7.com/api/lapp/device/fullday/record/switch/status";
|
||||
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.core.utils.TimestampUtils;
|
||||
import org.dromara.manager.ys7manager.dto.DeviceLocalVideoRequstDto;
|
||||
import org.dromara.manager.ys7manager.dto.DeviceOneKeySwitchRequstDto;
|
||||
import org.dromara.manager.ys7manager.dto.DevicePlayBackUrlRequstDto;
|
||||
import org.dromara.manager.ys7manager.vo.*;
|
||||
|
||||
@ -448,4 +449,75 @@ public class Ys7RequestUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置全天录像开关
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
public static Boolean putDeviceOneKeySwitch(DeviceOneKeySwitchRequstDto dto) {
|
||||
if (StringUtils.isAnyBlank(dto.getAccessToken(), dto.getDeviceSerial())) {
|
||||
throw new ServiceException("设置全天录像开关参数为空", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
if (dto.getEnable() == null){
|
||||
throw new ServiceException("请选择开关状态", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
HashMap<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("accessToken", dto.getAccessToken());
|
||||
paramMap.put("deviceSerial", dto.getDeviceSerial());
|
||||
paramMap.put("enable", dto.getEnable());
|
||||
if (dto.getChannelNo() != null) {
|
||||
paramMap.put("channelNo", dto.getChannelNo());
|
||||
}
|
||||
|
||||
String errorMsg = "设置全天录像开关请求失败";
|
||||
try (HttpResponse response = HttpRequest.post(Ys7Constant.UPDATEONEKEYSWITCH)
|
||||
.form(paramMap)
|
||||
.execute()) {
|
||||
if (!response.isOk()) {
|
||||
log.error("{}:{}", errorMsg, response.getStatus());
|
||||
throw new ServiceException(errorMsg + response.getStatus());
|
||||
}
|
||||
String body = response.body();
|
||||
log.info("设置全天录像开关body{}",body);
|
||||
Ys7ResponseVo responseVo = JSONUtil.toBean(body, Ys7ResponseVo.class);
|
||||
if (!responseVo.getCode().equals("200")) {
|
||||
log.error("{},状态码:{},{}", errorMsg, responseVo.getCode(), responseVo.getMsg());
|
||||
throw new ServiceException("序列号:"+dto.getDeviceSerial()+errorMsg + responseVo.getMsg());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取全天录像开关状态
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
public static Integer getDeviceSwitchStatus(DeviceOneKeySwitchRequstDto dto) {
|
||||
if (StringUtils.isAnyBlank(dto.getAccessToken(), dto.getDeviceSerial())) {
|
||||
throw new ServiceException("获取全天录像开关状态参数为空", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
HashMap<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("accessToken", dto.getAccessToken());
|
||||
paramMap.put("deviceSerial", dto.getDeviceSerial());
|
||||
|
||||
String errorMsg = "获取全天录像开关状态请求失败";
|
||||
try (HttpResponse response = HttpRequest.post(Ys7Constant.GETONEKEYSWITCHSTATUS)
|
||||
.form(paramMap)
|
||||
.execute()) {
|
||||
if (!response.isOk()) {
|
||||
log.error("{}:{}", errorMsg, response.getStatus());
|
||||
throw new ServiceException(errorMsg + response.getStatus());
|
||||
}
|
||||
String body = response.body();
|
||||
log.info("获取全天录像开关状态body{}",body);
|
||||
Ys7ResponseVo responseVo = JSONUtil.toBean(body, Ys7ResponseVo.class);
|
||||
if (!responseVo.getCode().equals("200")) {
|
||||
log.error("{},状态码:{},{}", errorMsg, responseVo.getCode(), responseVo.getMsg());
|
||||
throw new ServiceException("序列号:"+dto.getDeviceSerial()+errorMsg + responseVo.getMsg());
|
||||
}
|
||||
String data = responseVo.getData();
|
||||
return JSONUtil.parseObj(data).getInt("enable");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
package org.dromara.manager.ys7manager.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class DeviceOneKeySwitchRequstDto implements Serializable {
|
||||
private String accessToken; //toke
|
||||
private String deviceSerial; //设备序列号
|
||||
private Integer channelNo; // 通道号,默认1
|
||||
private Integer enable; // 状态:0-关闭,1-开启
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package org.dromara.other.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
|
||||
@Configuration
|
||||
public class ThreadPoolConfig {
|
||||
|
||||
/**
|
||||
* 摄像头全天录像开关操作专用线程池
|
||||
*/
|
||||
@Bean("deviceSwitchExecutor")
|
||||
public ThreadPoolTaskExecutor deviceSwitchExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(5); // 核心线程数
|
||||
executor.setMaxPoolSize(10); // 最大线程数
|
||||
executor.setKeepAliveSeconds(60); // 空闲线程存活时间(秒)
|
||||
executor.setQueueCapacity(100); // 任务队列容量
|
||||
executor.setThreadNamePrefix("device-switch-task-"); // 线程名前缀(替代自定义ThreadFactory)
|
||||
// 拒绝策略:队列满时由调用线程执行
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
// 初始化线程池
|
||||
executor.initialize();
|
||||
// 应用关闭时优雅关闭
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(executor::shutdown));
|
||||
return executor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取摄像头全天录像开关状态操作专用线程池
|
||||
*/
|
||||
@Bean("getDeviceSwitchExecutor")
|
||||
public ThreadPoolTaskExecutor getDeviceSwitchExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(5); // 核心线程数
|
||||
executor.setMaxPoolSize(10); // 最大线程数
|
||||
executor.setKeepAliveSeconds(60); // 空闲线程存活时间(秒)
|
||||
executor.setQueueCapacity(100); // 任务队列容量
|
||||
executor.setThreadNamePrefix("get-device-switch-task-"); // 线程名前缀(替代自定义ThreadFactory)
|
||||
// 拒绝策略:队列满时由调用线程执行
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
// 初始化线程池
|
||||
executor.initialize();
|
||||
// 应用关闭时优雅关闭
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(executor::shutdown));
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
@ -282,4 +282,20 @@ public class OthYs7DeviceController extends BaseController {
|
||||
return R.ok(othYs7DeviceService.getDateAndDeviceLocalVideo(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 一键开关萤石摄像头全天录像开关
|
||||
* @return
|
||||
*/
|
||||
@SaCheckPermission("other:ys7Device:edit")
|
||||
@PostMapping("/updateOneKeySwitch")
|
||||
public R<String> updateOneKeySwitch(@RequestBody OthYs7DeviceOneKeySwitchReq req){
|
||||
if (req.getDeviceSerial() == null){
|
||||
throw new ServiceException("设备序列号不能为空!!!");
|
||||
}
|
||||
if (req.getEnable() == null){
|
||||
throw new ServiceException("状态不能为空!!!");
|
||||
}
|
||||
int i = othYs7DeviceService.updateOneKeySwitch(req);
|
||||
return R.ok(i>0?"正在处理中,请稍后刷新页面查看":"操作失败");
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,6 +53,11 @@ public class OthYs7Device implements Serializable {
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 状态:0-关闭,1-开启
|
||||
*/
|
||||
private Integer enable;
|
||||
|
||||
/**
|
||||
* 布撤防状态
|
||||
*/
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
package org.dromara.other.domain.dto.ys7device;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lilemy
|
||||
* @date 2025/6/13 10:19
|
||||
*/
|
||||
@Data
|
||||
public class OthYs7DeviceOneKeySwitchReq implements Serializable {
|
||||
|
||||
/**
|
||||
* 设备序列号
|
||||
*/
|
||||
private List<String> deviceSerial;
|
||||
|
||||
/**
|
||||
* 状态:0-关闭,1-开启
|
||||
*/
|
||||
private Integer enable;
|
||||
}
|
||||
@ -69,6 +69,11 @@ public class OthYs7DeviceVo implements Serializable {
|
||||
@ExcelProperty(value = "设备在线状态(0离线 1在线)")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 状态:0-关闭,1-开启
|
||||
*/
|
||||
private Integer enable;
|
||||
|
||||
/**
|
||||
* 固件版本号
|
||||
*/
|
||||
|
||||
@ -165,4 +165,19 @@ public interface IOthYs7DeviceService extends IService<OthYs7Device> {
|
||||
* @return
|
||||
*/
|
||||
DateAndDeviceLocalVideoVo getDateAndDeviceLocalVideo(OthYs7DevicePlayBackUrlReq req);
|
||||
|
||||
/**
|
||||
* 一键开关
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
int updateOneKeySwitch(OthYs7DeviceOneKeySwitchReq req);
|
||||
|
||||
/**
|
||||
* 保存或更新萤石摄像开关状态对象列表
|
||||
*
|
||||
* @param ys7DeviceList 萤石摄像对象列表
|
||||
* @return 是否有值发生更改
|
||||
*/
|
||||
Boolean saveOrUpdateEnableByDeviceList(List<OthYs7Device> ys7DeviceList);
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
@ -19,6 +20,7 @@ import org.dromara.manager.ys7manager.Ys7Constant;
|
||||
import org.dromara.manager.ys7manager.Ys7Manager;
|
||||
import org.dromara.manager.ys7manager.Ys7RequestUtils;
|
||||
import org.dromara.manager.ys7manager.dto.DeviceLocalVideoRequstDto;
|
||||
import org.dromara.manager.ys7manager.dto.DeviceOneKeySwitchRequstDto;
|
||||
import org.dromara.manager.ys7manager.dto.DevicePlayBackUrlRequstDto;
|
||||
import org.dromara.manager.ys7manager.enums.DeviceOnOffLineEnum;
|
||||
import org.dromara.manager.ys7manager.vo.DeviceLocalVideoRecordsVo;
|
||||
@ -35,10 +37,12 @@ import org.dromara.other.utils.DateRangeUtils;
|
||||
import org.dromara.project.domain.BusProject;
|
||||
import org.dromara.project.service.IBusProjectService;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -59,6 +63,11 @@ public class OthYs7DeviceServiceImpl extends ServiceImpl<OthYs7DeviceMapper, Oth
|
||||
@Resource
|
||||
private Ys7Manager ys7Manager;
|
||||
|
||||
@Resource
|
||||
private ThreadPoolTaskExecutor deviceSwitchExecutor; // 摄像头全天录像开关操作专用线程池
|
||||
@Resource
|
||||
private ThreadPoolTaskExecutor getDeviceSwitchExecutor; // 注入获取摄像头全天录像开关状态线程池
|
||||
|
||||
/**
|
||||
* 查询萤石摄像头
|
||||
*
|
||||
@ -487,6 +496,101 @@ public class OthYs7DeviceServiceImpl extends ServiceImpl<OthYs7DeviceMapper, Oth
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateOneKeySwitch(OthYs7DeviceOneKeySwitchReq req) {
|
||||
String token = ys7Manager.getToken();
|
||||
|
||||
if (token == null || token.isEmpty()) {
|
||||
log.error("updateOneKeySwitch获取token失败,无法执行设备开关操作");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 3. 遍历设备序列号,提交异步任务
|
||||
List<String> deviceSerials = req.getDeviceSerial();
|
||||
Integer enable = req.getEnable();
|
||||
for (String deviceSerial : deviceSerials) {
|
||||
// lambda内变量需为final/有效final,重新赋值
|
||||
String finalDeviceSerial = deviceSerial;
|
||||
Integer finalEnable = enable;
|
||||
String finalToken = token;
|
||||
|
||||
// 4. 异步执行单个设备的开关操作
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
// 构建请求DTO
|
||||
DeviceOneKeySwitchRequstDto dto = new DeviceOneKeySwitchRequstDto();
|
||||
dto.setAccessToken(finalToken);
|
||||
dto.setDeviceSerial(finalDeviceSerial);
|
||||
dto.setEnable(finalEnable);
|
||||
|
||||
// 调用第三方接口(可能抛出异常,已被try-catch捕获)
|
||||
Boolean b = Ys7RequestUtils.putDeviceOneKeySwitch(dto);
|
||||
if (b != null && b) {
|
||||
// 接口调用成功,更新数据库
|
||||
int updateRows = baseMapper.update(new LambdaUpdateWrapper<OthYs7Device>()
|
||||
.set(OthYs7Device::getEnable, finalEnable)
|
||||
.eq(OthYs7Device::getDeviceSerial, finalDeviceSerial));
|
||||
log.info("设备{}一键开关更新成功,开关状态:{},影响行数:{}",
|
||||
finalDeviceSerial, finalEnable, updateRows);
|
||||
} else {
|
||||
log.warn("设备{}一键开关接口返回false,未更新数据库,开关状态:{}",
|
||||
finalDeviceSerial, finalEnable);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 捕获所有异常,确保单个设备失败不影响其他设备
|
||||
log.error("设备{}一键开关处理失败,开关状态:{}", finalDeviceSerial, finalEnable, e);
|
||||
}
|
||||
}, deviceSwitchExecutor); // 指定自定义线程池
|
||||
}
|
||||
|
||||
// 5. 主线程快速返回(异步任务后台执行)
|
||||
log.info("已提交{}个设备的一键开关异步任务,开关状态:{}", deviceSerials.size(), enable);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean saveOrUpdateEnableByDeviceList(List<OthYs7Device> ys7DeviceList) {
|
||||
if (CollectionUtils.isEmpty(ys7DeviceList)) {
|
||||
return false;
|
||||
}
|
||||
String token = ys7Manager.getToken();
|
||||
|
||||
if (token == null || token.isEmpty()) {
|
||||
log.error("updateOneKeySwitch获取token失败,无法执行设备开关操作");
|
||||
return false;
|
||||
}
|
||||
for (OthYs7Device ys7Device : ys7DeviceList) {
|
||||
// lambda内变量需为final/有效final,重新赋值
|
||||
String finalDeviceSerial = ys7Device.getDeviceSerial();
|
||||
String finalToken = token;
|
||||
|
||||
// 4. 异步执行单个设备的开关操作
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
// 构建请求DTO
|
||||
DeviceOneKeySwitchRequstDto dto = new DeviceOneKeySwitchRequstDto();
|
||||
dto.setAccessToken(finalToken);
|
||||
dto.setDeviceSerial(finalDeviceSerial);
|
||||
|
||||
// 调用第三方接口(可能抛出异常,已被try-catch捕获)
|
||||
Integer b = Ys7RequestUtils.getDeviceSwitchStatus(dto);
|
||||
if (b != null) {
|
||||
// 接口调用成功,更新数据库
|
||||
int updateRows = baseMapper.update(new LambdaUpdateWrapper<OthYs7Device>()
|
||||
.set(OthYs7Device::getEnable, b)
|
||||
.eq(OthYs7Device::getDeviceSerial, finalDeviceSerial));
|
||||
log.info("设备{}全天录像开关状态更新成功,开关状态:{},影响行数:{}",
|
||||
finalDeviceSerial, b, updateRows);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 捕获所有异常,确保单个设备失败不影响其他设备
|
||||
log.error("设备{}全天录像开关状态获取失败", finalDeviceSerial, e);
|
||||
}
|
||||
}, getDeviceSwitchExecutor); // 指定自定义线程池
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证萤石摄像对象是否发生更改
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user