tplink切片任务

This commit is contained in:
1378012178@qq.com 2026-05-13 10:18:05 +08:00
parent 9aff21e979
commit 8e56d6fc1d
41 changed files with 1149 additions and 965 deletions

View File

@ -50,7 +50,7 @@ public class ServiceOrderApi {
@ApiOperation(value = "服务指令工单-开始服务", notes = "服务指令工单-开始服务")
@AutoLog(value = "服务指令工单-开始服务", clientType = "app", operateType = 2)
@PostMapping(value = "/startOrder")
@PostMapping(value = "/startorder")
public Result<?> startOrder(@RequestBody DirectiveOrderEntity directiveOrderEntity) {
Map<String, Object> result = directiveOrderApi.startOrder(directiveOrderEntity);
return Result.OK(result);

View File

@ -0,0 +1,17 @@
package com.nu.dto;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @Description: tplink任务mq
* @Author: jeecg-boot
* @Date: 2026-05-09
* @Version: V1.0
*/
@Data
public class TplinkMQDto implements Serializable {
private List<TplinkUploadLogMQDto> taskList;
}

View File

@ -0,0 +1,92 @@
package com.nu.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: tplink切片上传日志
* @Author: jeecg-boot
* @Date: 2026-05-09
* @Version: V1.0
*/
@Data
public class TplinkUploadLogMQDto implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private String id;
/**
* 设备标识
*/
private String sn;
/**
* 开始时间
*/
private Date startTime;
/**
* 结束时间
*/
private Date endTime;
/**
* tplink网络地址
*/
private String tplinkPath;
/**
* tplink视频大小
*/
private String mp4Len;
/**
* tplink切片crc64
*/
private String tplinkCrc64;
/**
* tplink监控视频上传任务ID
*/
private String tplinkTaskId;
/**
* tplink上传入参
*/
private String tplinkParams;
/**
* tplink切片处理次数次数到达乏值 - 系统参数 且没有 order_end_time 代表彻底失败
*/
private Integer tplinkDownCount;
/**
* tplink录像机切片任务状态 0处理中 1失败 2成功
*/
private String tplinkTaskStatus;
/**
* tplink录像机切片任务失败原因
*/
private String tplinkTaskErrorMsg;
/**
* 切片完成后通过ftp上传的状态 0上传中 1失败 2成功
*/
private String uploadStatus;
/**
* 切片完成后通过ftp上传失败原因
*/
private String uploadErrorMsg;
/**
* 创建日期
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 更新日期
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/**
* 机构编码
*/
private String orgCode;
}

View File

@ -244,33 +244,6 @@ public class DirectiveOrderEntity implements Serializable {
* 工单执行状态0待执行1服务中2正常完成3超时完成 4未执行
*/
private String orderStatus;
/**
* tplink网络地址多个逗号分隔
*/
private String tplinkPath;
/**
* tplink监控视频上传任务ID
*/
private String tplinkTaskId;
/**
* tplink监控视频上传进度(千分制
*/
private String tplinkrocess;
/**
* tplink切片crc64
*/
private String tplinkCrc64;
/**
* tplink切片下载次数次数到达乏值 - 系统参数 且没有 order_end_time 代表彻底失败
*/
private String tplinkDownCount;
/**
* COS上传状态 null未上传过 1上传中 2成功 3失败
*/
private String cosStatus;
private String tplinkLen;
private String cosLen;
private String tplinkParams;
/**
* 接单上限

View File

@ -119,8 +119,6 @@ public class DirectiveOrderInfoEntity implements Serializable {
private Date updateTime;
/**是否删除 0未删除 1删除*/
private String delFlag;
/**tplink下载地址*/
private String tplinkPath;
/**手动拍照*/
private String manuallyPicPath;
/**手动录制*/

View File

@ -120,8 +120,6 @@ public class EmployeesSalaryInfoEntity implements Serializable {
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/**tplink下载地址*/
private String tplinkPath;
/**手动拍照*/
private String manuallyPicPath;
/**手动录制*/

View File

@ -0,0 +1,93 @@
package com.nu.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: tplink切片上传日志
* @Author: jeecg-boot
* @Date: 2026-05-09
* @Version: V1.0
*/
@Data
public class TplinkUploadLogEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private String id;
/**
* 设备标识
*/
private String sn;
/**
* 开始时间
*/
private Date startTime;
/**
* 结束时间
*/
private Date endTime;
/**
* tplink网络地址
*/
private String tplinkPath;
/**
* tplink视频大小
*/
private String mp4Len;
/**
* tplink切片crc64
*/
private String tplinkCrc64;
/**
* tplink监控视频上传任务ID
*/
private String tplinkTaskId;
/**
* tplink上传入参
*/
private String tplinkParams;
/**
* tplink切片处理次数次数到达乏值 - 系统参数 且没有 order_end_time 代表彻底失败
*/
private Integer tplinkDownCount;
/**
* tplink录像机切片任务状态 0处理中 1失败 2成功
*/
private String tplinkTaskStatus;
/**
* tplink录像机切片任务失败原因
*/
private String tplinkTaskErrorMsg;
/**
* 切片完成后通过ftp上传的状态 0上传中 1失败 2成功
*/
private String uploadStatus;
/**
* 切片完成后通过ftp上传失败原因
*/
private String uploadErrorMsg;
/**
* 创建日期
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private java.util.Date createTime;
/**
* 更新日期
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private java.util.Date updateTime;
/**
* 机构编码
*/
private String orgCode;
}

View File

@ -1,220 +0,0 @@
package com.nu.utils;
import com.nu.entity.CosFileInfoEntity;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.model.ObjectMetadata;
import com.tencentcloudapi.cdn.v20180606.CdnClient;
import com.tencentcloudapi.cdn.v20180606.models.PushUrlsCacheRequest;
import com.tencentcloudapi.cdn.v20180606.models.PushUrlsCacheResponse;
import com.tencentcloudapi.common.Credential;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* COS文件操作工具类
* 功能查询文件上传状态获取MD5获取文件信息
*/
@Component
public class CosFileUtil {
private static final Logger log = LoggerFactory.getLogger(CosFileUtil.class);
@Autowired
private COSClient cosClient;
@Value("${tencent.cos.bucketName}")
private String bucketName;
@Value("${tencent.cdn.secretId}")
private String cdnSecretId;
@Value("${tencent.cdn.secretKey}")
private String cdnSecretKey;
@Value("${tencent.cdn.domain}")
private String cdnDomain;
/**
* 查询文件上传状态和MD5
* <p>
* 返回值说明
* - success: true=查询COS接口成功false=查询失败网络/权限/系统问题
* - exists: true=文件已存在已上传完成false=文件不存在未上传或上传中
* <p>
* 使用示例
* CosFileInfoEntity result = cosFileUtil.checkFileStatus("video/2024/01/15/10.mp4");
* if (result.isSuccess() && result.isExists()) {
* // 文件已上传完成
* System.out.println("上传成功MD5" + result.getMd5());
* } else if (result.isSuccess() && !result.isExists()) {
* // 查询成功但文件不存在还没传完或没开始传
* System.out.println("文件未就绪");
* } else {
* // 查询COS接口失败
* System.out.println("查询失败:" + result.getErrorMsg());
* }
*
* @param fileKey 文件路径video/2024/01/15/10.mp4
* @return 文件信息实体
*/
public CosFileInfoEntity checkFileStatus(String fileKey) {
CosFileInfoEntity entity = new CosFileInfoEntity();
entity.setFileKey(fileKey);
try {
// 获取文件元数据HEAD请求不下载内容
ObjectMetadata metadata = cosClient.getObjectMetadata(bucketName, fileKey);
// 文件存在已上传完成
entity.setExists(true);
entity.setSuccess(true);
entity.setFileSize(metadata.getContentLength());
entity.setLastModified(metadata.getLastModified());
entity.setCrc64(metadata.getCrc64Ecma());//crc64 跟md5一样作用
log.info("查询文件成功fileKey={}, exists=true, crc64={}, size={}",
fileKey, entity.getCrc64(), entity.getFileSize());
} catch (CosServiceException e) {
if (e.getStatusCode() == 404) {
// 文件不存在还未上传完成
entity.setExists(false);
entity.setSuccess(true);
log.info("文件不存在fileKey={}", fileKey);
} else {
// 其他COS错误
entity.setSuccess(false);
entity.setExists(false);
entity.setErrorMsg("COS错误码" + e.getErrorCode() + ",错误信息:" + e.getErrorMessage());
log.error("查询文件状态COS异常fileKey={}, errorCode={}, errorMsg={}",
fileKey, e.getErrorCode(), e.getErrorMessage());
}
} catch (CosClientException e) {
// 客户端异常网络超时等
entity.setSuccess(false);
entity.setExists(false);
entity.setErrorMsg("客户端异常:" + e.getMessage());
log.error("查询文件状态客户端异常fileKey={}, msg={}", fileKey, e.getMessage());
} catch (Exception e) {
entity.setSuccess(false);
entity.setExists(false);
entity.setErrorMsg("系统异常:" + e.getMessage());
log.error("查询文件状态系统异常fileKey={}", fileKey, e);
}
return entity;
}
/**
* 只获取Crc64
*
* @param fileKey 文件路径
* @return MD5值文件不存在或获取失败返回null
*/
public String getCrc64(String fileKey) {
CosFileInfoEntity entity = checkFileStatus(fileKey);
if (entity.isSuccess() && entity.isExists() && entity.getCrc64() != null) {
return entity.getCrc64();
}
return null;
}
/**
* 判断文件是否已上传完成
*
* @param fileKey 文件路径
* @return true=已上传false=未上传或查询失败
*/
public boolean isUploadSuccess(String fileKey) {
CosFileInfoEntity entity = checkFileStatus(fileKey);
return entity.isSuccess() && entity.isExists();
}
/**
* 批量预热CDN
*
* @param fileKeys 文件路径列表
*/
public void batchPreloadCdn(List<String> fileKeys) {
if (fileKeys == null || fileKeys.isEmpty()) {
log.info("文件列表为空跳过CDN预热");
return;
}
// 1. 转成完整URL
List<String> urls = new ArrayList<>();
for (String key : fileKeys) {
urls.add(cdnDomain + key);
}
// 2. 分批每批最多500条
int batchSize = 500;
int totalBatches = (urls.size() + batchSize - 1) / batchSize;
for (int i = 0; i < urls.size(); i += batchSize) {
int end = Math.min(i + batchSize, urls.size());
List<String> batch = urls.subList(i, end);
int batchNum = i / batchSize + 1;
try {
// 3. 调用CDN预热API
Credential cred = new Credential(cdnSecretId, cdnSecretKey);
CdnClient client = new CdnClient(cred, "");
PushUrlsCacheRequest req = new PushUrlsCacheRequest();
req.setUrls(batch.toArray(new String[0]));
req.setUrlEncode(true);//解决中文路径问题
PushUrlsCacheResponse resp = client.PushUrlsCache(req);
log.info("CDN预热批次 {}/{} 成功,数量={}, taskId={}",
batchNum, totalBatches, batch.size(), resp.getTaskId());
} catch (Exception e) {
log.error("CDN预热批次 {}/{} 失败,数量={}", batchNum, totalBatches, batch.size(), e);
}
// 4. 批次间隔100ms除了最后一批
if (end < urls.size()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.warn("CDN预热被中断");
break;
}
}
}
}
/**
* 删除文件支持单个或多个
*
* @param files 文件路径列表
*/
public void deleteFiles(List<String> files) {
if (files == null || files.isEmpty()) {
return;
}
for (String fileKey : files) {
if (fileKey == null || fileKey.trim().isEmpty()) {
continue;
}
try {
cosClient.deleteObject(bucketName, fileKey);
log.info("文件删除成功:{}", fileKey);
} catch (Exception e) {
log.error("文件删除失败:{}", fileKey, e);
}
}
}
}

View File

@ -8,7 +8,9 @@
</update>
<select id="findById" resultType="com.nu.modules.employeesInfo.entity.BizEmployeesInfo">
select *
select *,
CONCAT(height, '') as height,
CONCAT(weight, '') as weight
from nu_biz_employees_info
where id = #{id}
</select>

View File

@ -215,10 +215,6 @@ public class EmployeesSalaryInfo implements Serializable {
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新日期")
private java.util.Date updateTime;
/**tplink下载地址*/
@Excel(name = "tplink下载地址", width = 15)
@ApiModelProperty(value = "tplink下载地址")
private java.lang.String tplinkPath;
/**手动拍照*/
@Excel(name = "手动拍照", width = 15)
@ApiModelProperty(value = "手动拍照")

View File

@ -9,4 +9,6 @@ import java.util.List;
public interface ICameraInfoApi {
public List<CameraInfoEntity> getCameraInfoList(CameraInfoEntity cameraInfoEntity);
CameraInfoEntity getSnByNuID(String nuId);
}

View File

@ -0,0 +1,13 @@
package com.nu.modules.uploadlog;
import com.nu.entity.TplinkUploadLogEntity;
import java.util.List;
public interface ITplinkUploadLogApi {
int saveData(TplinkUploadLogEntity tplinkUploadLogEntity);
List<TplinkUploadLogEntity> queryProcessingTask();
int updateDataById(TplinkUploadLogEntity task);
}

View File

@ -2,6 +2,7 @@ package com.nu.modules.tplink.camera.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nu.entity.CameraInfoEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import com.nu.modules.tplink.camera.entity.CameraInfo;
@ -24,4 +25,6 @@ public interface CameraInfoMapper extends BaseMapper<CameraInfo> {
CameraInfo getByDeviceId(CameraInfo cameraInfo);
void updateDeviceStatusByDevId(CameraInfo cameraInfo);
IPage<CameraInfo> previewList(Page<CameraInfo> page, @Param("params") CameraInfo cameraInfo);
CameraInfoEntity getSnByNuID(@Param("nuId") String nuId);
}

View File

@ -2,7 +2,8 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nu.modules.tplink.camera.mapper.CameraInfoMapper">
<select id="findPage" parameterType="com.nu.modules.tplink.camera.entity.CameraInfo" resultType="com.nu.modules.tplink.camera.entity.CameraInfo">
<select id="findPage" parameterType="com.nu.modules.tplink.camera.entity.CameraInfo"
resultType="com.nu.modules.tplink.camera.entity.CameraInfo">
select a.id,
a.device_index as deviceIndex,
device_name as deviceName,
@ -54,7 +55,8 @@
</where>
</select>
<select id="findList" parameterType="com.nu.modules.tplink.camera.entity.CameraInfo" resultType="com.nu.modules.tplink.camera.entity.CameraInfo">
<select id="findList" parameterType="com.nu.modules.tplink.camera.entity.CameraInfo"
resultType="com.nu.modules.tplink.camera.entity.CameraInfo">
select a.id,
a.device_index as deviceIndex,
device_name as deviceName,
@ -89,31 +91,32 @@
</where>
</select>
<select id="findAllList" parameterType="com.nu.modules.tplink.camera.entity.CameraInfo" resultType="com.nu.modules.tplink.camera.entity.CameraInfo">
<select id="findAllList" parameterType="com.nu.modules.tplink.camera.entity.CameraInfo"
resultType="com.nu.modules.tplink.camera.entity.CameraInfo">
select a.id,
a.device_index as deviceIndex,
b.device_name as deviceName,
b.device_type as deviceType,
a.device_status as deviceStatus,
b.device_model as deviceModel,
a.ip as ip,
a.mac as mac,
a.region_id as regionId,
a.region_name as regionName,
a.parent_id as parentId,
a.parent_device_name as parentDeviceName,
a.project_id as projectId,
a.project_name as projectName,
a.firmware_ver as firmwareVer,
a.hardware_ver as hardwareVer,
a.manager_auth_type as managerAuthType,
a.msg_auth_type as msgAuthType,
a.sip_code as sipCode,
a.location_name as locationName,
a.system_type as systemType,
a.protocol as protocol,
b.nu_id as nuId,
a.channel
a.device_index as deviceIndex,
b.device_name as deviceName,
b.device_type as deviceType,
a.device_status as deviceStatus,
b.device_model as deviceModel,
a.ip as ip,
a.mac as mac,
a.region_id as regionId,
a.region_name as regionName,
a.parent_id as parentId,
a.parent_device_name as parentDeviceName,
a.project_id as projectId,
a.project_name as projectName,
a.firmware_ver as firmwareVer,
a.hardware_ver as hardwareVer,
a.manager_auth_type as managerAuthType,
a.msg_auth_type as msgAuthType,
a.sip_code as sipCode,
a.location_name as locationName,
a.system_type as systemType,
a.protocol as protocol,
b.nu_id as nuId,
a.channel
from nu_iot_tplink_camera a
inner join nu_iot_device_preview b on a.mac = b.sn
where b.device_status != '损坏'
@ -122,29 +125,30 @@
</if>
</select>
<select id="getByDeviceId" parameterType="com.nu.modules.tplink.camera.entity.CameraInfo" resultType="com.nu.modules.tplink.camera.entity.CameraInfo">
<select id="getByDeviceId" parameterType="com.nu.modules.tplink.camera.entity.CameraInfo"
resultType="com.nu.modules.tplink.camera.entity.CameraInfo">
select a.id,
device_index as deviceIndex,
device_name as deviceName,
device_type as deviceType,
device_status as deviceStatus,
device_model as deviceModel,
ip as ip,
mac as mac,
region_id as regionId,
region_name as regionName,
parent_id as parentId,
device_index as deviceIndex,
device_name as deviceName,
device_type as deviceType,
device_status as deviceStatus,
device_model as deviceModel,
ip as ip,
mac as mac,
region_id as regionId,
region_name as regionName,
parent_id as parentId,
parent_device_name as parentDeviceName,
project_id as projectId,
project_name as projectName,
firmware_ver as firmwareVer,
hardware_ver as hardwareVer,
manager_auth_type as managerAuthType,
msg_auth_type as msgAuthType,
sip_code as sipCode,
location_name as locationName,
system_type as systemType,
protocol as protocol,
project_id as projectId,
project_name as projectName,
firmware_ver as firmwareVer,
hardware_ver as hardwareVer,
manager_auth_type as managerAuthType,
msg_auth_type as msgAuthType,
sip_code as sipCode,
location_name as locationName,
system_type as systemType,
protocol as protocol,
a.channel
from nu_iot_tplink_camera a
where device_index = #{deviceIndex}
@ -159,43 +163,44 @@
where device_index = #{deviceIndex}
</update>
<select id="previewList" parameterType="com.nu.modules.tplink.camera.entity.CameraInfo" resultType="com.nu.modules.tplink.camera.entity.CameraInfo">
<select id="previewList" parameterType="com.nu.modules.tplink.camera.entity.CameraInfo"
resultType="com.nu.modules.tplink.camera.entity.CameraInfo">
select
a.id,
a.nu_id,
c.nu_name,
a.device_name,
a.device_type,
a.device_model,
a.factory,
a.sn,
a.create_time,
a.update_time,
a.remarks,
t.online_status as deviceStatus,
t.device_index
a.id,
a.nu_id,
c.nu_name,
a.device_name,
a.device_type,
a.device_model,
a.factory,
a.sn,
a.create_time,
a.update_time,
a.remarks,
t.online_status as deviceStatus,
t.device_index
from nu_iot_device_preview a
left join nu_base_info c on a.nu_id = c.nu_id
inner join (
select mac as sn,
( case device_status when '0' then '离线' when '1' then '在线' end ) as online_status,
device_index
from nu_iot_tplink_camera
union all
select sn,
( case relay_state when '0' then '离线' else '在线' end ) as online_status,
'' as device_index
from nu_iot_ds_electricity_meter
union all
select cid as sn,
( case relay_state when '0' then '离线' else '在线' end ) as online_status,
'' as device_index
from nu_iot_tq_water_meter
union all
select sn,
( case status when '0' then '在线' else '离线' end ) as online_status,
'' as device_index
from nu_iot_yiweilian_humid_device
select mac as sn,
( case device_status when '0' then '离线' when '1' then '在线' end ) as online_status,
device_index
from nu_iot_tplink_camera
union all
select sn,
( case relay_state when '0' then '离线' else '在线' end ) as online_status,
'' as device_index
from nu_iot_ds_electricity_meter
union all
select cid as sn,
( case relay_state when '0' then '离线' else '在线' end ) as online_status,
'' as device_index
from nu_iot_tq_water_meter
union all
select sn,
( case status when '0' then '在线' else '离线' end ) as online_status,
'' as device_index
from nu_iot_yiweilian_humid_device
) t on a.sn = t.sn
where a.sn is not null
and ifnull(a.device_status,'') != '损坏'
@ -213,6 +218,11 @@
</if>
order by a.device_type,a.device_model,a.sn
</select>
<select id="getSnByNuID" resultType="com.nu.entity.CameraInfoEntity">
select sn as mac
from nu_iot_device_preview
where nu_id = #{nuId}
</select>
</mapper>

View File

@ -22,13 +22,4 @@ public interface ICameraInfoJobService extends IService<CameraInfo> {
Map<String,Object> getUploadToServerProcess(String taskId);
Map<String,Object> getUploadToServerProcessAsync(String taskId);
/**
* 下载tplink自定义录像
*
* @return
*/
Map<String, Object> zdyTplinkVideo(DirectiveOrderEntity orderEntity, String orgCode);
}

View File

@ -1,32 +1,18 @@
package com.nu.modules.tplink.camera.service.impl;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.nu.entity.DirectiveOrderEntity;
import com.nu.modules.tplink.camera.entity.CameraInfo;
import com.nu.modules.tplink.camera.mapper.CameraInfoMapper;
import com.nu.modules.tplink.camera.service.ICameraInfoJobService;
import com.nu.modules.tplink.common.entity.ErrorCode;
import com.nu.modules.tplink.common.entity.TumsConfig;
import com.nu.modules.tplink.common.mapper.TumsConfigMapper;
import com.nu.modules.tplink.common.service.IErrorCodeService;
import com.nu.modules.tplink.utils.TumsApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.util.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
@ -43,12 +29,6 @@ public class CameraInfoJobServiceImpl extends ServiceImpl<CameraInfoMapper, Came
private TumsApi tumsApi;
@Autowired
private IErrorCodeService errorCodeService;
@Autowired
private TumsConfigMapper tumsConfigMapper;
@Value(value = "${jeecg.path.upload}")
private String uploadpath;
/**
* 获取转存MP4上传任务进度
@ -90,221 +70,4 @@ public class CameraInfoJobServiceImpl extends ServiceImpl<CameraInfoMapper, Came
}
}
@Override
@Async
public Map<String, Object> getUploadToServerProcessAsync(String taskId) {
Map<String, Object> resultMap = Maps.newHashMap();
StringBuffer sb = new StringBuffer();
sb.append("{");
sb.append("\"taskId\"").append(":").append("\"").append(taskId).append("\"");
sb.append("}");
String res = tumsApi.getUploadToServerProcess(sb.toString());
JSONObject jsonObject = new JSONObject(res);
String errorCode = jsonObject.getStr("error_code");
if (errorCode.equals("0")) {
JSONObject result = jsonObject.getJSONObject("result");
String process = result.getStr("process");
resultMap.put("result", "success");
resultMap.put("process", process);
resultMap.put("url", result.getStr("url"));
return resultMap;
} else {
String errMsg = jsonObject.getStr("msg");
if (errMsg == null || errMsg.equals("")) {
try {
ErrorCode errorVo = errorCodeService.getByCode(errorCode);
errMsg = errorVo.getErrorMsg();
} catch (Exception e) {
errMsg = errorCode;
}
}
log.info("getUploadToServerProcess:{}-{}", errorCode, errMsg);
resultMap.put("result", "error");
resultMap.put("errorCode", errorCode);
resultMap.put("errMsg", errMsg);
return resultMap;
}
}
/**
* 下载tplink自定义录像
*
* @return
*/
@Override
public Map<String, Object> zdyTplinkVideo(DirectiveOrderEntity orderEntity, String orgCode) {
String nuId = orderEntity.getNuId();
String startTime = DateUtils.formatDate(orderEntity.getEmpStartTime(), "yyyy-MM-dd HH:mm:ss");
String endTime = DateUtils.formatDate(orderEntity.getEmpEndTime(), "yyyy-MM-dd HH:mm:ss");
Map<String, Object> result = Maps.newHashMap();
QueryWrapper<CameraInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("nu_id", nuId);
List<CameraInfo> tplinkList = baseMapper.selectList(queryWrapper);
if (tplinkList.size() == 0) {
result.put("result", "error");
return result;
}
String fileName = nuId + "-" + DateUtils.formatDate(new Date(), "yyyyMMddHHmmss" + "-" + orderEntity.getId());
String year = DateUtils.formatDate(new Date(), "yyyy");
String month = DateUtils.formatDate(new Date(), "MM");
String day = DateUtils.formatDate(new Date(), "dd");
CameraInfo tplinkInfo = tplinkList.get(0);
CameraInfo cameraInfo = new CameraInfo();
cameraInfo.setDeviceIndex(tplinkInfo.getDeviceIndex());
cameraInfo.setParentId(tplinkInfo.getParentId());
cameraInfo.setFileName(fileName);
cameraInfo.setVideoType("1");
cameraInfo.setFtpUploadpath("/tplinkVideo/fwzl" + "/" + orgCode
+ "/" + year + "/" + month + "/" + day
+ "/" + orderEntity.getInstructionName() + "/" + orderEntity.getCategoryName()
+ "/" + orderEntity.getTypeName() + "/" + orderEntity.getDirectiveName());
cameraInfo.setStartTime(startTime);
cameraInfo.setEndTime(endTime);
try {
result = uploadToServerResult(cameraInfo);
// result.put("")
return result;
} catch (Exception e) {
e.printStackTrace();
result.put("result", "error");
return result;
}
}
/**
* 回放视频转mp4上传
*
* @param cameraInfo
* @return
*/
public Map<String, Object> uploadToServerResult(CameraInfo cameraInfo) throws ParseException {
String ftpUsername = "";
String ftpPassword = "";
String ftpUploadpath = "";
String ftpIp = "";
String ftpPort = "";
log.info("uploadToServerResult - cameraInfo:{}:", cameraInfo);
CameraInfo entity = baseMapper.getByDeviceId(cameraInfo);
if (entity.getFtpIp() != null && !entity.getFtpIp().equals("")) {
ftpIp = entity.getFtpIp();
ftpPort = entity.getFtpPort();
ftpUsername = entity.getFtpUsername();
ftpPassword = entity.getFtpPassword();
ftpUploadpath = entity.getFtpUploadpath();
} else {
TumsConfig tumsConfig = tumsConfigMapper.getByCode();
ftpIp = tumsConfig.getFtpIp();
ftpPort = tumsConfig.getFtpPort();
ftpUsername = tumsConfig.getFtpUsername();
ftpPassword = tumsConfig.getFtpPassword();
ftpUploadpath = tumsConfig.getFtpUploadpath();
}
if (StringUtils.isNotBlank(cameraInfo.getFtpUploadpath())) {
ftpUploadpath = cameraInfo.getFtpUploadpath();
}
//文件夹不存在就创建 上传到COS不需要管这个问题了
mkdirsFolder(ftpUploadpath);
String deviceIndex = cameraInfo.getDeviceIndex();
String parentId = cameraInfo.getParentId();
String fileName = cameraInfo.getFileName();
StringBuffer sb = new StringBuffer();
sb.append("{");
sb.append("\"videoDevId\"").append(":").append("\"").append(deviceIndex).append("\",");
if (parentId != null && !parentId.equals("") && !parentId.equals("0")) {
//存储设备ID
sb.append("\"storageDevId\"").append(":").append("\"").append(parentId).append("\",");
} else {
//SK卡取自身设备ID
sb.append("\"storageDevId\"").append(":").append("\"").append(deviceIndex).append("\",");
}
sb.append("\"videoType\"").append(":").append(cameraInfo.getVideoType()).append(",");
sb.append("\"storageType\"").append(":").append("0").append(",");
if (fileName != null && !fileName.equals("")) {
//存储设备ID
sb.append("\"fileName\"").append(":").append("\"").append(fileName).append("\",");
}
// 使用 SimpleDateFormat 解析
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(cameraInfo.getStartTime());
Date date2 = sdf.parse(cameraInfo.getEndTime());
long startTime = date.getTime() / 1000 - 1;
long endTime = date2.getTime() / 1000 + 1;
// long startTime = 1765993096;
// long endTime = 1765993156;
sb.append("\"startTime\"").append(":").append(startTime).append(",");
sb.append("\"endTime\"").append(":").append(endTime).append(",");
sb.append("\"downloadInfo\"").append(":{");
sb.append("\"username\"").append(":").append("\"").append(ftpUsername).append("\",");
sb.append("\"password\"").append(":").append("\"").append(ftpPassword).append("\",");
sb.append("\"path\"").append(":").append("\"").append(ftpUploadpath).append("\",");
sb.append("\"ftpIp\"").append(":").append("\"").append(ftpIp).append("\",");
sb.append("\"ftpPort\"").append(":").append(ftpPort);
sb.append("}");
sb.append("}");
System.out.println("------------------" + sb.toString());
String res = tumsApi.uploadToServer(sb.toString());
JSONObject jsonObject = new JSONObject(res);
String errorCode = jsonObject.getStr("error_code");
Map<String, Object> resultMap = Maps.newHashMap();
resultMap.put("tplinkParams", sb.toString());
if (errorCode.equals("0")) {
JSONObject result = jsonObject.getJSONObject("result");
String taskId = result.getStr("taskId");
cameraInfo.setTaskId(taskId);
// getUploadToServerProcess(cameraInfo);
resultMap.put("result", "success");
resultMap.put("taskId", taskId);
resultMap.put("fileName", ftpUploadpath + "/" + fileName + ".mp4");
return resultMap;
} else {
String errorMsg = "";
try {
ErrorCode errorVo = errorCodeService.getByCode(errorCode);
errorMsg = errorVo.getErrorMsg();
} catch (Exception e) {
errorMsg = errorCode;
}
log.info("uploadToServerResult:{}-{}", errorCode, errorMsg);
resultMap.put("result", "error");
resultMap.put("errorCode", errorCode);
resultMap.put("errorMsg", errorMsg);
return resultMap;
}
}
public String mkdirsFolder(String folderPath) {
// 创建File对象
File folder = new File(folderPath);
String ctxPath = uploadpath;
String fileName = null;
File file = new File(ctxPath + File.separator + File.separator);
if (!file.exists()) {
file.mkdirs();// 创建文件根目录
} // 判断文件夹是否存在
if (!folder.exists()) {
System.out.println("文件夹不存在,开始创建...");
// 创建文件夹包括所有不存在的父文件夹
boolean created = folder.mkdirs();
if (created) {
System.out.println("文件夹创建成功:" + folderPath);
} else {
System.out.println("文件夹创建失败:" + folderPath);
}
} else {
System.out.println("文件夹已存在:" + folderPath);
// 还可以判断是否是文件夹而不是文件
if (folder.isDirectory()) {
System.out.println("这是一个文件夹");
} else {
System.out.println("这不是一个文件夹,而是文件");
}
}
return "success";
}
}

View File

@ -439,6 +439,11 @@ public class CameraInfoServiceImpl extends ServiceImpl<CameraInfoMapper, CameraI
return listDto;
}
@Override
public CameraInfoEntity getSnByNuID(String nuId) {
return baseMapper.getSnByNuID(nuId);
}
@Override
public IPage<CameraInfo> previewList(Page<CameraInfo> page, CameraInfo cameraInfo) {
return baseMapper.previewList(page, cameraInfo);

View File

@ -0,0 +1,180 @@
package com.nu.modules.tplink.uploadlog.controller;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.query.QueryRuleEnum;
import org.jeecg.common.util.oConvertUtils;
import com.nu.modules.tplink.uploadlog.entity.TplinkUploadLog;
import com.nu.modules.tplink.uploadlog.service.ITplinkUploadLogService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.apache.shiro.authz.annotation.RequiresPermissions;
/**
* @Description: tplink切片上传日志
* @Author: jeecg-boot
* @Date: 2026-05-09
* @Version: V1.0
*/
@Api(tags="tplink切片上传日志")
@RestController
@RequestMapping("/tplink/uploadlog/tplinkUploadLog")
@Slf4j
public class TplinkUploadLogController extends JeecgController<TplinkUploadLog, ITplinkUploadLogService> {
@Autowired
private ITplinkUploadLogService tplinkUploadLogService;
/**
* 分页列表查询
*
* @param tplinkUploadLog
* @param pageNo
* @param pageSize
* @param req
* @return
*/
//@AutoLog(value = "tplink切片上传日志-分页列表查询")
@ApiOperation(value="tplink切片上传日志-分页列表查询", notes="tplink切片上传日志-分页列表查询")
@GetMapping(value = "/list")
public Result<IPage<TplinkUploadLog>> queryPageList(TplinkUploadLog tplinkUploadLog,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<TplinkUploadLog> queryWrapper = QueryGenerator.initQueryWrapper(tplinkUploadLog, req.getParameterMap());
Page<TplinkUploadLog> page = new Page<TplinkUploadLog>(pageNo, pageSize);
IPage<TplinkUploadLog> pageList = tplinkUploadLogService.page(page, queryWrapper);
return Result.OK(pageList);
}
/**
* 添加
*
* @param tplinkUploadLog
* @return
*/
@AutoLog(value = "tplink切片上传日志-添加")
@ApiOperation(value="tplink切片上传日志-添加", notes="tplink切片上传日志-添加")
@RequiresPermissions("tplink.uploadlog:nu_iot_tplink_upload_log:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody TplinkUploadLog tplinkUploadLog) {
tplinkUploadLogService.save(tplinkUploadLog);
return Result.OK("添加成功!");
}
/**
* 编辑
*
* @param tplinkUploadLog
* @return
*/
@AutoLog(value = "tplink切片上传日志-编辑")
@ApiOperation(value="tplink切片上传日志-编辑", notes="tplink切片上传日志-编辑")
@RequiresPermissions("tplink.uploadlog:nu_iot_tplink_upload_log:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<String> edit(@RequestBody TplinkUploadLog tplinkUploadLog) {
tplinkUploadLogService.updateById(tplinkUploadLog);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "tplink切片上传日志-通过id删除")
@ApiOperation(value="tplink切片上传日志-通过id删除", notes="tplink切片上传日志-通过id删除")
@RequiresPermissions("tplink.uploadlog:nu_iot_tplink_upload_log:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
tplinkUploadLogService.removeById(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
*
* @param ids
* @return
*/
@AutoLog(value = "tplink切片上传日志-批量删除")
@ApiOperation(value="tplink切片上传日志-批量删除", notes="tplink切片上传日志-批量删除")
@RequiresPermissions("tplink.uploadlog:nu_iot_tplink_upload_log:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.tplinkUploadLogService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 通过id查询
*
* @param id
* @return
*/
//@AutoLog(value = "tplink切片上传日志-通过id查询")
@ApiOperation(value="tplink切片上传日志-通过id查询", notes="tplink切片上传日志-通过id查询")
@GetMapping(value = "/queryById")
public Result<TplinkUploadLog> queryById(@RequestParam(name="id",required=true) String id) {
TplinkUploadLog tplinkUploadLog = tplinkUploadLogService.getById(id);
if(tplinkUploadLog==null) {
return Result.error("未找到对应数据");
}
return Result.OK(tplinkUploadLog);
}
/**
* 导出excel
*
* @param request
* @param tplinkUploadLog
*/
@RequiresPermissions("tplink.uploadlog:nu_iot_tplink_upload_log:exportXls")
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, TplinkUploadLog tplinkUploadLog) {
return super.exportXls(request, tplinkUploadLog, TplinkUploadLog.class, "tplink切片上传日志");
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequiresPermissions("tplink.uploadlog:nu_iot_tplink_upload_log:importExcel")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, TplinkUploadLog.class);
}
}

View File

@ -0,0 +1,141 @@
package com.nu.modules.tplink.uploadlog.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.Column;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: tplink切片上传日志
* @Author: jeecg-boot
* @Date: 2026-05-09
* @Version: V1.0
*/
@Data
@TableName("nu_iot_tplink_upload_log")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "nu_iot_tplink_upload_log对象", description = "tplink切片上传日志")
public class TplinkUploadLog implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "ID")
private java.lang.String id;
/**
* 设备标识
*/
@Excel(name = "设备标识", width = 15)
@ApiModelProperty(value = "设备标识")
private java.lang.String sn;
/**
* 开始时间
*/
@Excel(name = "开始日期", width = 20, format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "开始日期")
private Date startTime;
/**
* 结束时间
*/
@Excel(name = "结束日期", width = 20, format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "结束日期")
private Date endTime;
/**
* tplink网络地址
*/
@Excel(name = "tplink网络地址", width = 15)
@ApiModelProperty(value = "tplink网络地址")
private java.lang.String tplinkPath;
/**
* tplink视频大小
*/
@Excel(name = "tplink视频大小", width = 15)
@ApiModelProperty(value = "tplink视频大小")
private java.lang.String mp4Len;
/**
* tplink切片crc64
*/
@Excel(name = "tplink切片crc64", width = 15)
@ApiModelProperty(value = "tplink切片crc64")
private java.lang.String tplinkCrc64;
/**
* tplink监控视频上传任务ID
*/
@Excel(name = "tplink监控视频上传任务ID", width = 15)
@ApiModelProperty(value = "tplink监控视频上传任务ID")
@TableField(updateStrategy = FieldStrategy.IGNORED)
@Column(nullable = true, updatable = true)
private java.lang.String tplinkTaskId;
/**
* tplink上传入参
*/
@Excel(name = "tplink上传入参", width = 15)
@ApiModelProperty(value = "tplink上传入参")
private java.lang.String tplinkParams;
/**
* tplink切片下载次数次数到达乏值 - 系统参数 且没有 order_end_time 代表彻底失败
*/
@Excel(name = "tplink切片处理次数次数到达乏值 - 系统参数 且没有 order_end_time 代表彻底失败)", width = 15)
@ApiModelProperty(value = "tplink切片处理次数次数到达乏值 - 系统参数 且没有 order_end_time 代表彻底失败)")
private java.lang.Integer tplinkDownCount;
/**
* tplink录像机切片任务状态 0处理中 1失败 2成功
*/
@Excel(name = "tplink录像机切片任务状态 0处理中 1失败 2成功", width = 15)
@ApiModelProperty(value = "tplink录像机切片任务状态 0处理中 1失败 2成功")
private java.lang.String tplinkTaskStatus;
/**
* tplink录像机切片任务失败原因
*/
@Excel(name = "tplink录像机切片任务失败原因", width = 15)
@ApiModelProperty(value = "tplink录像机切片任务失败原因")
private java.lang.String tplinkTaskErrorMsg;
/**
* 切片完成后通过ftp上传的状态 0上传中 1失败 2成功
*/
@Excel(name = "切片完成后通过ftp上传的状态 0上传中 1失败 2成功", width = 15)
@ApiModelProperty(value = "切片完成后通过ftp上传的状态 0上传中 1失败 2成功")
private java.lang.String uploadStatus;
/**
* 切片完成后通过ftp上传失败原因
*/
@Excel(name = "切片完成后通过ftp上传失败原因", width = 15)
@ApiModelProperty(value = "切片完成后通过ftp上传失败原因")
private java.lang.String uploadErrorMsg;
/**
* 创建日期
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建日期")
private java.util.Date createTime;
/**
* 更新日期
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新日期")
private java.util.Date updateTime;
/**
* 机构编码
*/
@Excel(name = "机构编码", width = 15)
@ApiModelProperty(value = "机构编码")
private String orgCode;
}

View File

@ -0,0 +1,17 @@
package com.nu.modules.tplink.uploadlog.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.nu.modules.tplink.uploadlog.entity.TplinkUploadLog;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @Description: tplink切片上传日志
* @Author: jeecg-boot
* @Date: 2026-05-09
* @Version: V1.0
*/
public interface TplinkUploadLogMapper extends BaseMapper<TplinkUploadLog> {
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nu.modules.tplink.uploadlog.mapper.TplinkUploadLogMapper">
</mapper>

View File

@ -0,0 +1,14 @@
package com.nu.modules.tplink.uploadlog.service;
import com.nu.modules.tplink.uploadlog.entity.TplinkUploadLog;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @Description: tplink切片上传日志
* @Author: jeecg-boot
* @Date: 2026-05-09
* @Version: V1.0
*/
public interface ITplinkUploadLogService extends IService<TplinkUploadLog> {
}

View File

@ -0,0 +1,61 @@
package com.nu.modules.tplink.uploadlog.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.nu.entity.TplinkUploadLogEntity;
import com.nu.modules.sysconfig.ISysConfigApi;
import com.nu.modules.tplink.uploadlog.entity.TplinkUploadLog;
import com.nu.modules.tplink.uploadlog.mapper.TplinkUploadLogMapper;
import com.nu.modules.tplink.uploadlog.service.ITplinkUploadLogService;
import com.nu.modules.uploadlog.ITplinkUploadLogApi;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.util.List;
/**
* @Description: tplink切片上传日志
* @Author: jeecg-boot
* @Date: 2026-05-09
* @Version: V1.0
*/
@Service
public class TplinkUploadLogServiceImpl extends ServiceImpl<TplinkUploadLogMapper, TplinkUploadLog> implements ITplinkUploadLogService, ITplinkUploadLogApi {
@Autowired
private ISysConfigApi sysConfigApi;
@Override
public int saveData(TplinkUploadLogEntity tplinkUploadLogEntity) {
TplinkUploadLog saveData = new TplinkUploadLog();
BeanUtils.copyProperties(tplinkUploadLogEntity, saveData);
return baseMapper.insert(saveData);
}
@Override
public List<TplinkUploadLogEntity> queryProcessingTask() {
//如果未配置最多重试3次
Integer tplinkMaxRetries = 3;
JSONObject opeOpenUrl = sysConfigApi.getByKey("tplink_max_retries");
try {
tplinkMaxRetries = opeOpenUrl.getInteger("configValue");
} catch (Exception e) {
e.printStackTrace();
}
QueryWrapper<TplinkUploadLog> qw = new QueryWrapper<>();
qw.isNotNull("tplink_task_id");
return BeanUtil.copyToList(baseMapper.selectList(qw), TplinkUploadLogEntity.class);
}
@Override
public int updateDataById(TplinkUploadLogEntity task) {
TplinkUploadLog updateData = new TplinkUploadLog();
BeanUtils.copyProperties(task, updateData);
return baseMapper.updateById(updateData);
}
}

View File

@ -40,9 +40,9 @@ public class TumsApi {
* @return
*/
public TumsClient createTumsClient(){
// if(this.tumsClient==null){
if(this.tumsClient==null){
login();
// }
}
return this.tumsClient;
}

View File

@ -0,0 +1,28 @@
package com.nu.mq.tplinkupload.exceptionhandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpRejectAndDontRequeueException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.listener.api.RabbitListenerErrorHandler;
import org.springframework.amqp.rabbit.support.ListenerExecutionFailedException;
import org.springframework.stereotype.Component;
@Slf4j
@Component("tplinkUploadMQErrorHandler")
public class TplinkUploadMQExceptionHandler implements RabbitListenerErrorHandler {
@Override
public Object handleError(Message message, org.springframework.messaging.Message<?> message1, ListenerExecutionFailedException e) {
log.error("MQ消息处理失败 | 消息体: {} | 异常原因: {}", new String(message.getBody()), e.getCause().getMessage());
// 根据异常类型选择处理策略
// if (isRetryable(e)) {
// // 可重试异常抛出异常触发重试
// throw e;
// } else {
// 不可恢复异常拒绝消息且不重新入队
throw new AmqpRejectAndDontRequeueException("消息处理失败且禁止重试", e);
// }
}
}

View File

@ -0,0 +1,29 @@
package com.nu.mq.tplinkupload.listener;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("tplinkUploadAsyncDQNP")
public class DynamicQueueNameProvider {
@Autowired
private ISysBaseAPI sysBaseAPI;
public String getTplinkUploadProcessQueueName() {
JSONObject deptInfo = sysBaseAPI.getDeptInfo();
String orgCode = deptInfo.getString("code");
if (StringUtils.isNotBlank(orgCode)) {
return orgCode + ".tplink.uploadtask.result";
} else {
return "";
}
}
public String getTplinkUploadProcessKeyName() {
return getTplinkUploadProcessQueueName();
}
}

View File

@ -0,0 +1,40 @@
package com.nu.mq.tplinkupload.listener;
import cn.hutool.core.bean.BeanUtil;
import com.nu.dto.IotHumidDeviceMQDto;
import com.nu.dto.TplinkMQDto;
import com.nu.modules.tplink.uploadlog.entity.TplinkUploadLog;
import com.nu.modules.tplink.uploadlog.service.ITplinkUploadLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Slf4j
@Component
public class TplinkUploadMQListener {
@Autowired
private ITplinkUploadLogService tplinkUploadLogService;
@RabbitListener(
bindings = @QueueBinding(
value = @Queue(name = "#{tplinkUploadAsyncDQNP.getTplinkUploadProcessQueueName()}"),
exchange = @Exchange(name = "hldy.mediaserv.tplink.uploadtask", type = ExchangeTypes.DIRECT),
key = "#{tplinkUploadAsyncDQNP.getTplinkUploadProcessKeyName()}"
),
errorHandler = "tplinkUploadMQErrorHandler"
)
public void handleMessage_unify(TplinkMQDto dto) {
List<TplinkUploadLog> updateList = BeanUtil.copyToList(dto.getTaskList(), TplinkUploadLog.class);
tplinkUploadLogService.updateBatchById(updateList);
}
}

View File

@ -198,10 +198,6 @@ public class DirectiveAppraisal implements Serializable {
* 是否多个 Y是指令集 N否
*/
private String izMulti;
/**
* tplink网络地址多个逗号分隔
*/
private String tplinkPath;
/**
* 手动拍照网络地址多个逗号分隔
*/
@ -210,25 +206,6 @@ public class DirectiveAppraisal implements Serializable {
* 手动录制网络地址多个逗号分隔
*/
private String manuallyMp4Path;
/**
* tplink监控视频上传任务ID
*/
private String tplinkTaskId;
/**
* tplink切片crc64
*/
private String tplinkCrc64;
/**
* tplink切片下载次数次数到达乏值 - 系统参数 且没有 order_end_time 代表彻底失败
*/
private String tplinkDownCount;
/**
* COS上传状态 null未上传过 1上传中 2成功 3失败
*/
private String cosStatus;
private String tplinkLen;
private String cosLen;
private String tplinkParams;
/**
* 指令类型ID

View File

@ -195,10 +195,6 @@ public class DirectiveOrder implements Serializable {
* 是否多个 Y是指令集 N否
*/
private String izMulti;
/**
* tplink网络地址多个逗号分隔
*/
private String tplinkPath;
/**
* 手动拍照网络地址多个逗号分隔
*/
@ -208,26 +204,9 @@ public class DirectiveOrder implements Serializable {
*/
private String manuallyMp4Path;
/**
* tplink监控视频上传任务ID
* 设备标识
*/
@TableField(updateStrategy = FieldStrategy.IGNORED)
@Column(nullable = true, updatable = true)
private String tplinkTaskId;
/**
* tplink切片crc64
*/
private String tplinkCrc64;
/**
* tplink切片下载次数次数到达乏值 - 系统参数 且没有 order_end_time 代表彻底失败
*/
private String tplinkDownCount;
/**
* COS上传状态 null未上传过 1上传中 2成功 3失败
*/
private String cosStatus;
private String tplinkLen;
private String cosLen;
private String tplinkParams;
private String tplinkSn;
/**
* 指令类型ID

View File

@ -1,189 +0,0 @@
package com.nu.modules.biz.order.job;
import com.alibaba.fastjson.JSONObject;
import com.nu.entity.DirectiveOrderEntity;
import com.nu.modules.biz.order.entity.DirectiveOrder;
import com.nu.modules.biz.order.service.IDirectiveOrderJobService;
import com.nu.modules.sysconfig.ISysConfigApi;
import com.nu.modules.tplink.camera.service.ICameraInfoJobService;
import com.nu.utils.CosFileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.util.DateUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 指令工单结束后tplink上传相关处理
*/
@Slf4j
public class DirectiveOrderEndTplinkJob implements Job {
@Autowired
private IDirectiveOrderJobService directiveOrderService;
@Autowired
private ICameraInfoJobService tplinkService;
@Autowired
private ISysConfigApi sysConfigApi;
@Autowired
private ISysBaseAPI sysBaseAPI;
@Autowired
private CosFileUtil cosFileUtil;
/**
* COS上传进度查询 + tplink上传任务
* <p>
* tplink上传任务 需要依赖 COS进度查询结果 所以先执行查询任务 再执行 上传任务
*
* @param jobExecutionContext
* @throws JobExecutionException
*/
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info("OrdersJob:{}-{}", DateUtils.now(), "服务指令结束工单tplink处理定时任务");
JSONObject obj = sysConfigApi.getByKey("enabled_cdn");
String cdnEnabledStr = obj.getString("configValue");
boolean cdnEnabled = "Y".equals(cdnEnabledStr);
//机构编码
JSONObject deptInfo = sysBaseAPI.getDeptInfo();
String orgCode = deptInfo.getString("code");
//任务一根据taskId查询tplink进度
{
List<DirectiveOrder> directiveOrderList = directiveOrderService.getUploadingTplink();
directiveOrderList.forEach(order -> {
try {
Map<String, Object> result = tplinkService.getUploadToServerProcess(order.getTplinkTaskId());
System.out.println("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
System.out.println(result.toString());
System.out.println("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
if("success".equals(result.get("result")) ){
if("1000".equals(result.get("process"))){
order.setTplinkParams("成功");
order.setOrderEndTime(new Date());
order.setTplinkTaskId(null);
directiveOrderService.updateById(order);
}
}else{
order.setTplinkParams(result.toString());
order.setOrderEndTime(new Date());
order.setTplinkTaskId(null);
directiveOrderService.updateById(order);
}
} catch (Exception e) {
e.printStackTrace();
}
});
}
// //任务一COS上传进度查询
// {
// //已完成的视频
// List<String> finishPathList = Lists.newArrayList();
// //查询上传中的进度 cos_status = 1的
// List<DirectiveOrder> directiveOrderList = directiveOrderService.getUploadingTplink();
// directiveOrderList.forEach(order -> {
// try {
// CosFileInfoEntity cosResult = cosFileUtil.checkFileStatus(order.getTplinkPath());
// if (cosResult.isExists()) {
// //上传完了
// order.setCosStatus("2");//上传成功
// order.setOrderEndTime(new Date());//工单结束时间
// order.setTplinkCrc64(cosResult.getCrc64());//视频切片crc64
// order.setCosLen(cosResult.getFileSize() + "");
// //记录需要进行CDN预热的文件
// finishPathList.add(order.getTplinkPath());
// } else if (cosResult.isSuccess()) {
// //传输中
// order.setCosStatus("1");//上传中
// } else {
// //失败了
// order.setCosStatus("3");//上传失败
// }
// //更新工单数据
// directiveOrderService.updateById(order);
// } catch (Exception e) {
// e.printStackTrace();
// }
// });
// //本轮所有文件都查询完结果之后
// try {
// if (cdnEnabled && !CollectionUtils.isEmpty(finishPathList)) {
// //CDN预热
// cosFileUtil.batchPreloadCdn(finishPathList);
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
//任务二处理tplink上传
{
//如果未配置最多重试3次
Integer tplinkMaxRetries = 3;
JSONObject opeOpenUrl = sysConfigApi.getByKey("tplink_max_retries");
try {
tplinkMaxRetries = opeOpenUrl.getInteger("configValue");
} catch (Exception e) {
e.printStackTrace();
}
//获取需要处理的工单数据 员工已结束服务 但工单未结束
List<DirectiveOrder> directiveOrderList = directiveOrderService.getNeedProcessTpLinkList(tplinkMaxRetries);
for (DirectiveOrder directiveOrder : directiveOrderList) {
try {
String nuId = directiveOrder.getNuId();
String startTime = DateUtils.formatDate(directiveOrder.getEmpStartTime(), "yyyy-MM-dd HH:mm:ss");
String endTime = DateUtils.formatDate(directiveOrder.getEmpEndTime(), "yyyy-MM-dd HH:mm:ss");
log.info("nuId:{}", nuId);
log.info("startTime:{}", startTime);
log.info("endTime:{}", endTime);
DirectiveOrderEntity orderEntity = new DirectiveOrderEntity();
BeanUtils.copyProperties(directiveOrder, orderEntity);
Map<String, Object> resultTplink = tplinkService.zdyTplinkVideo(orderEntity, orgCode);
directiveOrder.setTplinkParams((String) resultTplink.get("tplinkParams"));
String tplinkDownCount = directiveOrder.getTplinkDownCount();
//设置处理次数
if (StringUtils.isBlank(tplinkDownCount)) {
directiveOrder.setTplinkDownCount("1");
} else {
directiveOrder.setTplinkDownCount((Integer.parseInt(tplinkDownCount) + 1) + "");
}
if (!StringUtils.equals("error", (String) resultTplink.get("result"))) {
//成功调用tplink API 开始上传tplink切片 目标服务器
String taskId = (String) resultTplink.get("taskId");
String fileName = (String) resultTplink.get("fileName");
directiveOrder.setTplinkTaskId(taskId);
directiveOrder.setTplinkPath(fileName);//cos路径
directiveOrder.setCosStatus("1");//上传中
} else {
System.out.println("===============================================");
System.out.println((String) resultTplink.get("errorCode"));
System.out.println((String) resultTplink.get("errorMsg"));
System.out.println("===============================================");
}
directiveOrderService.updateById(directiveOrder);
if (directiveOrderList.indexOf(directiveOrder) < directiveOrderList.size() - 1) {
Thread.sleep(10000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}

View File

@ -0,0 +1,167 @@
package com.nu.modules.biz.order.job;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.nu.entity.TplinkUploadLogEntity;
import com.nu.modules.biz.order.mapper.DirectiveOrderMapper;
import com.nu.modules.tplink.camera.entity.CameraInfo;
import com.nu.modules.tplink.common.entity.ErrorCode;
import com.nu.modules.tplink.common.service.IErrorCodeService;
import com.nu.modules.tplink.utils.TumsApi;
import com.nu.modules.uploadlog.ITplinkUploadLogApi;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.util.DateUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.List;
/**
* tplink切片上传定时任务
*/
@Slf4j
public class TplinkUploadJob implements Job {
@Autowired
private DirectiveOrderMapper directiveOrderMapper;
@Autowired
private ITplinkUploadLogApi tplinkUploadLogApi;
@Autowired
private ISysBaseAPI sysBaseAPI;
@Autowired
private TumsApi tumsApi;
@Autowired
private IErrorCodeService errorCodeService;
/**
* 处理前一小时的切片并上传
*
* @param jobExecutionContext
* @throws JobExecutionException
*/
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info("tplink切片上传定时任务执行时间{}", DateUtils.now());
//拿到前一小时的开始和结束时间
// LocalDateTime lastHour = LocalDateTime.now().minusHours(1);
//todo 把这里改一下
LocalDateTime lastHour = LocalDateTime.now().minusDays(2);
//开始时间
ZonedDateTime startTimeZone = lastHour.withMinute(0).withSecond(0).withNano(0)
.atZone(ZoneId.of("Asia/Shanghai"));
Date startTime = Date.from(startTimeZone.toInstant());
long startMillis = startTimeZone.toInstant().toEpochMilli();
//结束时间
//todo 把这里改一下
ZonedDateTime endTimeZone = lastHour.withMinute(1).withSecond(59).withNano(0)
.atZone(ZoneId.of("Asia/Shanghai"));
Date endTime = Date.from(endTimeZone.toInstant());
long endMillis = endTimeZone.toInstant().toEpochMilli();
//获取机构信息
JSONObject deptInfo = sysBaseAPI.getDeptInfo();
String orgCode = deptInfo.getString("code");
//查询需要处理任务的摄像头
List<CameraInfo> tplinkList = directiveOrderMapper.getTplinkInfo();
for (int i = 0; i < tplinkList.size(); i++) {
String id = IdUtil.simpleUUID();
CameraInfo cameraInfo = tplinkList.get(i);
TplinkUploadLogEntity tplinkUploadLogEntity = new TplinkUploadLogEntity();
tplinkUploadLogEntity.setId(id);
tplinkUploadLogEntity.setOrgCode(orgCode);
tplinkUploadLogEntity.setSn(cameraInfo.getMac());
tplinkUploadLogEntity.setStartTime(startTime);
tplinkUploadLogEntity.setEndTime(endTime);
tplinkUploadLogEntity.setTplinkDownCount(1);
try {
String year = DateUtils.formatDate(new Date(), "yyyy");
String month = DateUtils.formatDate(new Date(), "MM");
String day = DateUtils.formatDate(new Date(), "dd");
String fileName = orgCode
+ "_" + DateUtils.formatDate(new Date(), "yyyyMMdd")
+ "_" + (cameraInfo.getNuId() != null ? cameraInfo.getNuId() + "_" : "")
+ cameraInfo.getMac() + "_" + DateUtils.formatDate(new Date(), "HHmmss");
String deviceIndex = cameraInfo.getDeviceIndex();
String parentId = cameraInfo.getParentId();
String ftpIp = cameraInfo.getFtpIp();
String ftpPort = cameraInfo.getFtpPort();
String ftpUsername = cameraInfo.getFtpUsername();
String ftpPassword = cameraInfo.getFtpPassword();
String ftpUploadpath = "/" + orgCode + "/" + year + "/" + month + "/" + day
+ "/" + (cameraInfo.getNuId() != null ? cameraInfo.getNuId() + "/" : "")
+ cameraInfo.getMac();
StringBuffer sb = new StringBuffer();
//拼接tplink需要的入参
{
sb.append("{");
sb.append("\"videoDevId\"").append(":").append("\"").append(deviceIndex).append("\",");
if (parentId != null && !parentId.equals("") && !parentId.equals("0")) {
//存储设备ID
sb.append("\"storageDevId\"").append(":").append("\"").append(parentId).append("\",");
} else {
//SK卡取自身设备ID
sb.append("\"storageDevId\"").append(":").append("\"").append(deviceIndex).append("\",");
}
sb.append("\"videoType\"").append(":").append("1").append(",");
sb.append("\"storageType\"").append(":").append("0").append(",");
sb.append("\"fileName\"").append(":").append("\"").append(fileName).append("\",");
sb.append("\"startTime\"").append(":").append(startMillis / 1000).append(",");
sb.append("\"endTime\"").append(":").append(endMillis / 1000).append(",");
sb.append("\"downloadInfo\"").append(":{");
sb.append("\"username\"").append(":").append("\"").append(ftpUsername).append("\",");
sb.append("\"password\"").append(":").append("\"").append(ftpPassword).append("\",");
sb.append("\"path\"").append(":").append("\"").append(ftpUploadpath).append("\",");
sb.append("\"ftpIp\"").append(":").append("\"").append(ftpIp).append("\",");
sb.append("\"ftpPort\"").append(":").append(ftpPort);
sb.append("}");
sb.append("}");
System.out.println("------------------" + sb);
}
tplinkUploadLogEntity.setTplinkParams(sb.toString());
//调用tplink上传api 并记录调用结果
{
String res = tumsApi.uploadToServer(sb.toString());
cn.hutool.json.JSONObject jsonObject = new cn.hutool.json.JSONObject(res);
String errorCode = jsonObject.getStr("error_code");
if (errorCode.equals("0")) {
cn.hutool.json.JSONObject result = jsonObject.getJSONObject("result");
tplinkUploadLogEntity.setTplinkTaskStatus("0");
tplinkUploadLogEntity.setTplinkTaskId(result.getStr("taskId"));
tplinkUploadLogEntity.setTplinkPath(ftpUploadpath + "/" + fileName);
} else {
String errorMsg = "";
try {
ErrorCode errorVo = errorCodeService.getByCode(errorCode);
errorMsg = errorVo.getErrorMsg();
} catch (Exception e) {
errorMsg = errorCode;
}
tplinkUploadLogEntity.setTplinkTaskStatus("1");
tplinkUploadLogEntity.setTplinkTaskErrorMsg("【第一次失败原因调用tplink上传任务失败 - " + errorMsg + "");
}
}
} catch (Exception e) {
e.printStackTrace();
//记录一次上传失败
tplinkUploadLogEntity.setTplinkTaskStatus("1");
tplinkUploadLogEntity.setTplinkTaskErrorMsg("【第一次失败原因:上传定时任务执行代码逻辑报错 - " + e.getMessage() + "");
}
tplinkUploadLogApi.saveData(tplinkUploadLogEntity);
}
}
}

View File

@ -0,0 +1,108 @@
package com.nu.modules.biz.order.job;
import cn.hutool.core.bean.BeanUtil;
import com.nu.dto.TplinkMQDto;
import com.nu.dto.TplinkUploadLogMQDto;
import com.nu.entity.TplinkUploadLogEntity;
import com.nu.modules.tplink.camera.service.ICameraInfoJobService;
import com.nu.modules.uploadlog.ITplinkUploadLogApi;
import com.nu.utils.RabbitMQUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang.StringUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;
/**
* tplink上传任务进度查询
*/
@Slf4j
public class TplinkUploadProcessQueryJob implements Job {
@Autowired
private ICameraInfoJobService tplinkService;
@Autowired
private ITplinkUploadLogApi tplinkUploadLogApi;
@Autowired
private RabbitMQUtil rabbitMQUtil;
/**
* tplink上传任务进度查询
*
* @param jobExecutionContext
* @throws JobExecutionException
*/
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
List<TplinkUploadLogEntity> list = tplinkUploadLogApi.queryProcessingTask();
//tplink已经处理完成的集合
List<TplinkUploadLogEntity> finishList = Lists.newArrayList();
if (!CollectionUtils.isEmpty(list)) {
for (int i = 0; i < list.size(); i++) {
TplinkUploadLogEntity task = list.get(i);
Map<String, Object> result = tplinkService.getUploadToServerProcess(task.getTplinkTaskId());
System.out.println("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");
System.out.println(result.toString());
System.out.println("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
if ("success".equals(result.get("result"))) {
if ("1000".equals(result.get("process"))) {
String url_ = (String) result.get("url");
try {
URL url = new URL(url_);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36");
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
int code = conn.getResponseCode();
if (code == 200) {
long length = conn.getContentLengthLong();
if (length != -1) {
task.setMp4Len(length + "");
}
}
conn.disconnect();
} catch (IOException e) {
log.info("tplink上传任务{}成功后通过url获取文件大小失败报错{}", task.getTplinkTaskId(), e.getMessage());
}
task.setTplinkTaskId(null);
task.setTplinkTaskStatus("2");
tplinkUploadLogApi.updateDataById(task);
//通知资源服务器中服务 查询资源文件上传状态
finishList.add(task);
}
} else {
task.setTplinkTaskId(null);
task.setTplinkTaskStatus("1");
if (StringUtils.isNotBlank(task.getTplinkTaskErrorMsg())) {
task.setTplinkTaskErrorMsg(task.getTplinkTaskErrorMsg() + "【第" + task.getTplinkDownCount() + "次失败原因tplink任务查询返回失败错误码 - " + result.get("errMsg") + "");
} else {
task.setTplinkTaskErrorMsg("【第" + task.getTplinkDownCount() + "次失败原因tplink任务查询返回失败错误码 - " + result.get("errMsg") + "");
}
tplinkUploadLogApi.updateDataById(task);
}
}
}
//向资源服务器发送任务
if (!CollectionUtils.isEmpty(finishList)) {
TplinkMQDto mqDto = new TplinkMQDto();
mqDto.setTaskList(BeanUtil.copyToList(finishList, TplinkUploadLogMQDto.class));
rabbitMQUtil.sendToExchange("hldy.mediaserv.tplink", "hldy.mediaserv.tplink.uploadtask", mqDto);
}
}
}

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.nu.entity.CareDirectiveEntity;
import com.nu.entity.DirectiveOrderEntity;
import com.nu.modules.biz.order.entity.DirectiveOrder;
import com.nu.modules.tplink.camera.entity.CameraInfo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@ -32,18 +33,9 @@ public interface DirectiveOrderMapper extends BaseMapper<DirectiveOrder> {
DirectiveOrderEntity queryOrderNeedBaseInfo(@Param("dto") DirectiveOrderEntity entity);
List<DirectiveOrder> getNeedProcessTpLinkList(@Param("tplinkMaxRetries") Integer tplinkMaxRetries);
List<DirectiveOrder> getUploadingTplink();
List<DirectiveOrder> getTplinkProcessing();
int taskSuccess(@Param("dto") DirectiveOrder order);
int taskFaild(@Param("tplinkTaskId") String tplinkTaskId);
int updateEmpEndTimeByJob();
List<DirectiveOrderEntity> queryOrderInfoList(@Param("dto") DirectiveOrderEntity queryWrapper);
List<CameraInfo> getTplinkInfo();
}

View File

@ -96,33 +96,20 @@
<result column="sub_update_by" property="updateBy"/>
<result column="sub_update_time" property="updateTime"/>
<result column="sub_del_flag" property="delFlag"/>
<result column="sub_tplink_path" property="tplinkPath"/>
<result column="sub_manually_pic_path" property="manuallyPicPath"/>
<result column="sub_manually_mp4_path" property="manuallyMp4Path"/>
</collection>
</resultMap>
<update id="taskSuccess">
update nu_biz_directive_order
set tplink_task_id = null,
tplink_len = #{dto.tplinkLen}
where tplink_task_id = #{dto.tplinkTaskId}
</update>
<update id="taskFaild">
update nu_biz_directive_order
set tplink_task_id = null,
cos_status = '3',
tplink_path = null
where tplink_task_id = #{tplinkTaskId}
</update>
<update id="updateEmpEndTimeByJob">
UPDATE nu_biz_directive_order
SET emp_end_time = DATE_FORMAT(emp_start_time, '%Y-%m-%d 23:59:59'),
order_end_time = DATE_FORMAT(emp_start_time, '%Y-%m-%d 23:59:59'),
order_status = '3'
WHERE emp_start_time IS NOT NULL
AND emp_end_time IS NULL
AND DATE(emp_start_time) = CURDATE()
AND DATE (emp_start_time) = CURDATE()
</update>
@ -189,7 +176,7 @@
o.iz_timeout,
o.opt_ids,
o.opt_names,
mainStatus.item_text as optTypeName
mainStatus.item_text as optTypeName
FROM nu_biz_directive_order o
LEFT JOIN sys_dict dict ON dict.dict_code = 'directive_order_opt_type'
LEFT JOIN sys_dict_item mainStatus
@ -294,12 +281,8 @@
t.update_time,
t.del_flag,
t.iz_multi,
t.tplink_path,
t.manually_pic_path,
t.manually_mp4_path,
t.tplink_task_id,
t.tplink_crc64,
t.tplink_down_count,
CASE WHEN t.emp_start_time IS NULL THEN 'N' ELSE 'Y' END AS iz_start,
CASE WHEN t.emp_end_time IS NULL THEN 'N' ELSE 'Y' END AS iz_finish,
dire.preview_file,
@ -380,12 +363,8 @@
t.update_time,
t.del_flag,
t.iz_multi,
t.tplink_path,
t.manually_pic_path,
t.manually_mp4_path,
t.tplink_task_id,
t.tplink_crc64,
t.tplink_down_count,
dire.preview_file,
dire.service_content,
dire.mp3_file,
@ -453,31 +432,6 @@
LEFT JOIN nu_biz_elder_info elder ON elder.id = base.elder_id
WHERE base.nu_id = #{dto.nuId}
</select>
<select id="getNeedProcessTpLinkList" resultType="com.nu.modules.biz.order.entity.DirectiveOrder">
select ord.*
from nu_biz_directive_order ord
where ord.emp_end_time is not null
and ord.order_end_time is null
and (
(ord.cos_status is null or ord.cos_status = '3')
or (
ord.cos_status = '2'
and (ord.cos_len != ord.tplink_len or ord.cos_len = '-1' or ord.tplink_len = '0')
)
)
and (ord.tplink_down_count is null or ord.tplink_down_count <![CDATA[ <= ]]> #{tplinkMaxRetries})
</select>
<select id="getUploadingTplink" resultType="com.nu.modules.biz.order.entity.DirectiveOrder">
select ord.*
from nu_biz_directive_order ord
where ord.tplink_task_id is not null and order_end_time is null
</select>
<select id="getTplinkProcessing" resultType="com.nu.modules.biz.order.entity.DirectiveOrder">
select ord.*
from nu_biz_directive_order ord
where ord.tplink_task_id is not null
</select>
<select id="queryOrderInfoList" resultType="com.nu.entity.DirectiveOrderEntity">
select a.*, b.immediate_file, b.immediate_file_focus
@ -487,4 +441,11 @@
and a.instruction_id = #{dto.instructionTagId}
and a.serv_start_time = #{dto.servStartTime}
</select>
<select id="getTplinkInfo" resultType="com.nu.modules.tplink.camera.entity.CameraInfo">
select cam.*,pre.nu_id
from nu_iot_tplink_camera cam
inner join nu_iot_device_preview pre on pre.sn = cam.mac
where pre.device_type = 'SURVEILLANCECAMERA' and pre.device_status = '已绑定'
</select>
</mapper>

View File

@ -1,24 +0,0 @@
package com.nu.modules.biz.order.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.nu.modules.biz.order.entity.DirectiveOrder;
import org.apache.ibatis.annotations.Param;
import org.jeecg.common.api.vo.Result;
import java.util.List;
import java.util.Map;
/**
* @Description: 服务指令工单主表
* @Author: caolei
* @Date: 2025-11-18
* @Version: V1.0
*/
public interface IDirectiveOrderJobService extends IService<DirectiveOrder> {
List<DirectiveOrder> getNeedProcessTpLinkList(Integer tplinkMaxRetries);
List<DirectiveOrder> getUploadingTplink();
}

View File

@ -17,4 +17,6 @@ public interface IDirectiveOrderService extends IService<DirectiveOrder> {
String getEmployeeName(String employeeId);
void updateEmpEndTimeByJob();
void upOrderSn(DirectiveOrder directiveOrder);
}

View File

@ -1,32 +0,0 @@
package com.nu.modules.biz.order.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nu.modules.biz.order.entity.DirectiveOrder;
import com.nu.modules.biz.order.mapper.DirectiveOrderMapper;
import com.nu.modules.biz.order.service.IDirectiveOrderJobService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description: 服务指令工单主表
* @Author: caolei
* @Date: 2025-11-18
* @Version: V1.0
*/
@Service
@Slf4j
public class DirectiveOrderJobServiceImpl extends ServiceImpl<DirectiveOrderMapper, DirectiveOrder> implements IDirectiveOrderJobService {
@Override
public List<DirectiveOrder> getNeedProcessTpLinkList(Integer tplinkMaxRetries) {
return baseMapper.getNeedProcessTpLinkList(tplinkMaxRetries);
}
@Override
public List<DirectiveOrder> getUploadingTplink() {
return baseMapper.getUploadingTplink();
}
}

View File

@ -249,6 +249,9 @@ public class DirectiveOrderPadServiceImpl extends ServiceImpl<DirectiveOrderMapp
}
baseMapper.update(upData, uw);
//存储本次工单使用的哪个摄像头
directiveOrderService.upOrderSn(directiveOrder);
return map;
}
@ -268,6 +271,7 @@ public class DirectiveOrderPadServiceImpl extends ServiceImpl<DirectiveOrderMapp
boolean izCs = new Date().after(directiveOrder.getServEndTime());
directiveOrder.setOrderStatus(izCs ? "3" : "2");
}
directiveOrder.setOrderEndTime(new Date());
baseMapper.updateById(directiveOrder);
map.put("success", true);

View File

@ -1,10 +1,14 @@
package com.nu.modules.biz.order.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nu.entity.CameraInfoEntity;
import com.nu.modules.biz.order.entity.DirectiveOrder;
import com.nu.modules.biz.order.mapper.DirectiveOrderMapper;
import com.nu.modules.biz.order.service.IDirectiveOrderService;
import com.nu.modules.camerainfo.api.ICameraInfoApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
/**
@ -17,6 +21,8 @@ import org.springframework.stereotype.Service;
@Slf4j
public class DirectiveOrderServiceImpl extends ServiceImpl<DirectiveOrderMapper, DirectiveOrder> implements IDirectiveOrderService {
@Autowired
private ICameraInfoApi cameraInfoApi;
/**
* 获取员工姓名
@ -40,4 +46,14 @@ public class DirectiveOrderServiceImpl extends ServiceImpl<DirectiveOrderMapper,
baseMapper.updateEmpEndTimeByJob();
}
@Async
@Override
public void upOrderSn(DirectiveOrder directiveOrder) {
CameraInfoEntity cameraInfo = cameraInfoApi.getSnByNuID(directiveOrder.getNuId());
DirectiveOrder upData = new DirectiveOrder();
upData.setId(directiveOrder.getId());
upData.setTplinkSn(cameraInfo.getMac());
baseMapper.updateById(upData);
}
}

View File

@ -1,7 +1,5 @@
package com.nu.modules.biz.plan.care.job;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.nu.modules.biz.order.entity.DirectiveOrder;
import com.nu.modules.biz.order.service.IDirectiveOrderService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
@ -9,14 +7,8 @@ import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
/**
* 结束工单定时 每天23:59:50把当天已开始未结束的 结束时间设置为23:59:59
* 结束工单定时 每天23:59:30把当天已开始未结束的 结束时间设置为23:59:59
*/
@Slf4j
public class DirectiveEndOrderJob implements Job {
@ -25,25 +17,6 @@ public class DirectiveEndOrderJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
// DirectiveOrder upData = new DirectiveOrder();
// //设置为当天23:59:59
// Calendar calendar = Calendar.getInstance();
// upData.setEmpEndTime(new Date(calendar.get(Calendar.YEAR) - 1900,
// calendar.get(Calendar.MONTH),
// calendar.get(Calendar.DAY_OF_MONTH),
// 23, 59, 59));
//
// //当天任务且已开始的
// UpdateWrapper<DirectiveOrder> uw = new UpdateWrapper<>();
// uw.apply("DATE(serv_start_time) = CURDATE()");
// uw.isNotNull("emp_start_time");
// uw.isNull("emp_end_time");
// directiveOrderService.update(upData,uw);
//条件是工单已开始未结束 员工开始时间是今天 存在问题
// 1任务设置在每天23:59:50 如果当天由于系统原因比如重启后才补发定时任务 则缺少了一天的定时任务
// 2如果员工在23:59:50~23:59:59 点击开始 则结束时间无法被定时任务执行到
// 3解决办法条件只要已开始未结束那以后就不能有让历史工单的结束时间需要保持空的需求了 - 定时会自动赋值 一旦出错这种数据因为没有日志就只能用数据库备份比对解决
directiveOrderService.updateEmpEndTimeByJob();
}

View File

@ -112,7 +112,6 @@
<result column="sub_update_by" property="updateBy"/>
<result column="sub_update_time" property="updateTime"/>
<result column="sub_del_flag" property="delFlag"/>
<result column="sub_tplink_path" property="tplinkPath"/>
<result column="sub_manually_pic_path" property="manuallyPicPath"/>
<result column="sub_manually_mp4_path" property="manuallyMp4Path"/>
</collection>