|
@@ -1,5 +1,6 @@
|
|
|
package org.dromara.server.hik.service.impl;
|
|
package org.dromara.server.hik.service.impl;
|
|
|
|
|
|
|
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
import cn.hutool.core.collection.CollectionUtil;
|
|
import cn.hutool.core.collection.CollectionUtil;
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
@@ -23,6 +24,7 @@ import org.dromara.common.core.enums.CardStatusEnum;
|
|
|
import org.dromara.common.core.enums.DeviceBrandEnum;
|
|
import org.dromara.common.core.enums.DeviceBrandEnum;
|
|
|
import org.dromara.common.core.enums.UserAccountStatusEnum;
|
|
import org.dromara.common.core.enums.UserAccountStatusEnum;
|
|
|
import org.dromara.common.core.exception.ServiceException;
|
|
import org.dromara.common.core.exception.ServiceException;
|
|
|
|
|
+import org.dromara.common.core.utils.MapstructUtils;
|
|
|
import org.dromara.common.core.utils.StringUtils;
|
|
import org.dromara.common.core.utils.StringUtils;
|
|
|
import org.dromara.common.core.utils.ValidatorUtils;
|
|
import org.dromara.common.core.utils.ValidatorUtils;
|
|
|
import org.dromara.common.redis.utils.RedisUtils;
|
|
import org.dromara.common.redis.utils.RedisUtils;
|
|
@@ -48,7 +50,13 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.validation.annotation.Validated;
|
|
import org.springframework.validation.annotation.Validated;
|
|
|
|
|
|
|
|
|
|
+import java.text.DateFormat;
|
|
|
import java.text.MessageFormat;
|
|
import java.text.MessageFormat;
|
|
|
|
|
+import java.text.ParseException;
|
|
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
|
|
+import java.time.LocalDate;
|
|
|
|
|
+import java.time.ZoneId;
|
|
|
|
|
+import java.time.ZoneOffset;
|
|
|
import java.time.ZonedDateTime;
|
|
import java.time.ZonedDateTime;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.time.format.DateTimeFormatter;
|
|
|
import java.util.*;
|
|
import java.util.*;
|
|
@@ -563,6 +571,37 @@ public class SendDeviceServiceImpl implements ISendDeviceService {
|
|
|
return this.setHttpHostByDto(dto);
|
|
return this.setHttpHostByDto(dto);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 设置数据下发数据的时间
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 该方法用于将员工信息传输到所有设备,基于提供的员工信息数据传输对象。
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param termNo
|
|
|
|
|
+ * @param time
|
|
|
|
|
+ * @return 响应信息主体,表示上传操作的结果状态及可能的附加信息
|
|
|
|
|
+ */
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void setSendTime(Long termNo, String time) {
|
|
|
|
|
+ // time的日期格式必须是yyyy-MM-dd,否则抛出异常
|
|
|
|
|
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
|
|
|
|
+ Date date;
|
|
|
|
|
+ try {
|
|
|
|
|
+ date = dateFormat.parse(time);
|
|
|
|
|
+ } catch (ParseException e) {
|
|
|
|
|
+ throw new ServiceException("时间格式错误,请输入yyyy-MM-dd格式的时间");
|
|
|
|
|
+ }
|
|
|
|
|
+ XfTermVo byTermNo = xfTermService.getByTermNo(termNo);
|
|
|
|
|
+ if (byTermNo == null) {
|
|
|
|
|
+ throw new ServiceException("设备不存在" + termNo);
|
|
|
|
|
+ }
|
|
|
|
|
+ String termMac = byTermNo.getTermMac();
|
|
|
|
|
+ if (StringUtils.isBlank(termMac)) {
|
|
|
|
|
+ throw new ServiceException("设备的mac为空," + termNo);
|
|
|
|
|
+ }
|
|
|
|
|
+ String newTermMac = termMac.replaceAll(":", "-");
|
|
|
|
|
+ RedisUtils.setCacheObject(CacheNames.XF_MAC_DOWN_SEND_TIME + newTermMac, date.getTime());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
@Override
|
|
@Override
|
|
|
public R<Void> setHttpHostAll() {
|
|
public R<Void> setHttpHostAll() {
|
|
|
List<RemoteXfTermVo> termList = remotePtXfTermService.queryListByBrand("hk");
|
|
List<RemoteXfTermVo> termList = remotePtXfTermService.queryListByBrand("hk");
|
|
@@ -1200,6 +1239,145 @@ public class SendDeviceServiceImpl implements ISendDeviceService {
|
|
|
RedisUtils.setCacheObject(CacheNames.XF_MAC_DOWN_SEND_TIME + newTermMac, System.currentTimeMillis());
|
|
RedisUtils.setCacheObject(CacheNames.XF_MAC_DOWN_SEND_TIME + newTermMac, System.currentTimeMillis());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 设置设备删除过期账户时间缓存
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param date 缓存值
|
|
|
|
|
+ * @param termNo 机号
|
|
|
|
|
+ */
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void setDeleteTimeCache(Date date, Long termNo) {
|
|
|
|
|
+ XfTermVo byTermNo = xfTermService.getByTermNo(termNo);
|
|
|
|
|
+ if (byTermNo == null) {
|
|
|
|
|
+ throw new ServiceException("设备不存在" + termNo);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(!StringUtils.equals(byTermNo.getBrand(), DeviceBrandEnum.HK.getCode())){
|
|
|
|
|
+ throw new ServiceException("设备不是海康设备: " + termNo);
|
|
|
|
|
+ }
|
|
|
|
|
+ String termMac = byTermNo.getTermMac();
|
|
|
|
|
+ if (StringUtils.isBlank(termMac)) {
|
|
|
|
|
+ throw new ServiceException("设备的mac为空," + termNo);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(date != null){
|
|
|
|
|
+ RedisUtils.setCacheMapValue(CacheNames.LAST_TIME_DELETE_LIST, termMac, date.getTime());
|
|
|
|
|
+ }else{
|
|
|
|
|
+ LocalDate localDate = LocalDate.now();
|
|
|
|
|
+ // localDate 转Date
|
|
|
|
|
+ Date now = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
|
|
|
|
+// Date now1 = Date.from(localDate.atStartOfDay(ZoneOffset.ofHours(8)).toInstant());
|
|
|
|
|
+ RedisUtils.setCacheMapValue(CacheNames.LAST_TIME_DELETE_LIST, termMac, now.getTime());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 删除设备过期账户
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param termNo 设备编号
|
|
|
|
|
+ */
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void deleteExpireAccountSend(Long termNo) {
|
|
|
|
|
+ XfTermVo byTermNo = xfTermService.getByTermNo(termNo);
|
|
|
|
|
+ if (byTermNo == null) {
|
|
|
|
|
+ throw new ServiceException("设备不存在" + termNo);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(!StringUtils.equals(byTermNo.getBrand(), DeviceBrandEnum.HK.getCode())){
|
|
|
|
|
+ throw new ServiceException("设备不是海康设备: " + termNo);
|
|
|
|
|
+ }
|
|
|
|
|
+ RemoteXfTermVo remoteXfTermVo = BeanUtil.copyProperties(byTermNo, RemoteXfTermVo.class);
|
|
|
|
|
+ removeExpireAccountForTerm(remoteXfTermVo);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 删除所有设备过期账户
|
|
|
|
|
+ */
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void deleteExpireAccountSendAllDevice() {
|
|
|
|
|
+ List<RemoteXfTermVo> termList = remotePtXfTermService.queryListByBrand(DeviceBrandEnum.HK.getCode());
|
|
|
|
|
+ if (CollectionUtil.isEmpty(termList)) {
|
|
|
|
|
+ throw new ServiceException("未查询到海康的设备");
|
|
|
|
|
+ }
|
|
|
|
|
+ List<Long> onlineDeviceList = getOnlineDeviceList();
|
|
|
|
|
+ //只给在线设备下发数据
|
|
|
|
|
+ List<RemoteXfTermVo> list = termList.stream().filter(p -> onlineDeviceList.contains(p.getTermNo())).toList();
|
|
|
|
|
+ list.forEach(p -> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ removeExpireAccountForTerm(p);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("删除设备过期账户异常:{}, 错误信息:{}", p.getTermNo(),e.getMessage(), e);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void removeExpireAccountForTerm(RemoteXfTermVo p) {
|
|
|
|
|
+ String termMac = p.getTermMac();
|
|
|
|
|
+ Long termNo = p.getTermNo();
|
|
|
|
|
+ if (StringUtils.isBlank(termMac)) {
|
|
|
|
|
+ throw new ServiceException("设备的mac为空," + termNo);
|
|
|
|
|
+ }
|
|
|
|
|
+ Long lastTime = RedisUtils.getCacheMapValue(CacheNames.LAST_TIME_DELETE_LIST, termMac);
|
|
|
|
|
+ if (lastTime == null) {
|
|
|
|
|
+ log.warn("设备未设置删除时间缓存,设置为当天0点:{}", termNo);
|
|
|
|
|
+ LocalDate localDate = LocalDate.now();
|
|
|
|
|
+ // localDate 转Date
|
|
|
|
|
+ Date now = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
|
|
|
|
+ RedisUtils.setCacheMapValue(CacheNames.LAST_TIME_DELETE_LIST, termMac, now.getTime());
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ Date last = new Date(lastTime);
|
|
|
|
|
+ Date now = new Date();
|
|
|
|
|
+ List<RemoteUserAccountVo> expireAccount = remoteUserAccountService.getExpireAccount(last, now);
|
|
|
|
|
+ if (expireAccount.isEmpty()) {
|
|
|
|
|
+ log.info("未查询到过期账户,设备:{}", termNo);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ DeviceDto device = getDeviceDto(p);
|
|
|
|
|
+
|
|
|
|
|
+ // 下发数据
|
|
|
|
|
+ int consecutiveTimeouts = 0; // 连续超时计数器
|
|
|
|
|
+
|
|
|
|
|
+ for (RemoteUserAccountVo account : expireAccount) {
|
|
|
|
|
+ // 调用第三方接口前重置超时标志
|
|
|
|
|
+ boolean isTimeout = false;
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 删除账户
|
|
|
|
|
+ EmpInfoDto empInfo = getEmpInfoDto(account, Boolean.TRUE, Boolean.TRUE,
|
|
|
|
|
+ Boolean.TRUE, Boolean.TRUE, Boolean.TRUE, Boolean.FALSE);
|
|
|
|
|
+ R<Void> result = createOperatorEmpInfo(device, empInfo);
|
|
|
|
|
+ log.info("删除账户,rs: {}",result.getMsg());
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ String message = e.getMessage();
|
|
|
|
|
+ log.error("删除账户异常:{},异常信息:{}", account.getRealName(), message, e);
|
|
|
|
|
+ // 判断是否为超时异常
|
|
|
|
|
+ String lowerCase = message.toLowerCase().replaceAll(" ", "");
|
|
|
|
|
+ // Connection timed out: connect
|
|
|
|
|
+ if (lowerCase.contains("timeout") || lowerCase.contains("timedout") || lowerCase.contains("connecttimedout")) {
|
|
|
|
|
+ isTimeout = true;
|
|
|
|
|
+ consecutiveTimeouts++;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 其他异常重置计数器
|
|
|
|
|
+ consecutiveTimeouts = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果不是超时异常,重置计数器
|
|
|
|
|
+ if (!isTimeout) {
|
|
|
|
|
+ consecutiveTimeouts = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果连续三次超时,抛出异常或处理
|
|
|
|
|
+ if (consecutiveTimeouts >= 3) {
|
|
|
|
|
+ log.warn("连续3次调用超时,停止处理,设备网络断开,避免一直超时等待而暂用系统资源,设备:{}", termNo);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(consecutiveTimeouts < 3){
|
|
|
|
|
+ RedisUtils.setCacheMapValue(CacheNames.LAST_TIME_DELETE_LIST, termMac, now.getTime());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 获取在线设备列表
|
|
* 获取在线设备列表
|
|
|
*
|
|
*
|