package com.qianwen.mdc.collect.service;
|
|
import java.time.Instant;
|
import java.time.LocalDate;
|
import java.time.ZoneOffset;
|
import java.util.Collections;
|
import java.util.Map;
|
import java.util.Set;
|
|
import cn.hutool.core.date.DatePattern;
|
import cn.hutool.core.date.DateUtil;
|
import com.google.common.collect.Sets;
|
import com.qianwen.mdc.collect.cache.TimeSliceCache;
|
import com.qianwen.mdc.collect.constants.CommonConstant;
|
import com.qianwen.mdc.collect.dto.CacheBuildDTO;
|
import com.qianwen.mdc.collect.dto.CalendarShiftTimeSlicesDTO;
|
import com.qianwen.mdc.collect.mapper.iotdb.DeviceStateMapper;
|
import com.qianwen.mdc.collect.utils.LocalDateTimeUtils;
|
import com.xxl.job.core.log.XxlJobLogger;
|
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.Service;
|
|
import com.qianwen.mdc.collect.cache.WorkstationCache;
|
import com.qianwen.mdc.collect.dto.WorkstationDTO;
|
import com.qianwen.mdc.collect.entity.iotdb.DeviceState;
|
import com.qianwen.mdc.collect.entity.iotdb.ProcessParam;
|
import com.qianwen.mdc.collect.mapper.iotdb.ProcessParamMapper;
|
|
import cn.hutool.core.util.ObjectUtil;
|
/**
|
* 设备离线处理服务,超过一定时间无采集数据判定为离线,插入离线状态数据
|
*/
|
@Service
|
public class DeviceOfflineCheckService{
|
private static final Logger log = LoggerFactory.getLogger(DeviceOfflineCheckService.class);
|
/**
|
* 离线判定时长,默认5分钟
|
*/
|
@Value("${offlineConfigDuration:300000}")
|
private long offlineConfigDuration;
|
public static final String OFFLINE_VALUE = "4";//离线状态值
|
@Autowired
|
private ProcessParamService paramService;
|
|
@Autowired
|
private WorkstationCache workstationCache;
|
@Autowired
|
private ProcessParamMapper processParamMapper;
|
|
@Autowired
|
private DeviceStateService deviceStateService;
|
@Autowired
|
private TimeSliceCache timeSliceCache;
|
@Autowired
|
private DeviceStateMapper deviceStateMapper;
|
/**
|
* 保存状态固定点数据(state_{workstationId})
|
*/
|
public void checkOffline() {
|
//将数据按照工位id分组
|
Map<String, WorkstationDTO> workstationsMap = workstationCache.getWorkstations();
|
if (ObjectUtil.isEmpty(workstationsMap)) {
|
log.info("缓存无设备数据,退出");
|
return;
|
}
|
|
Set<String> workstationIds = workstationsMap.keySet();
|
|
log.info("离线检查工位总数:{}",workstationsMap.size());
|
|
for(String workstationId :workstationIds) {
|
log.info("开始检查工位{}的离线状态",workstationId);
|
Long wid = Long.parseLong(workstationId);
|
handleWorkstationOffline(wid);
|
}
|
|
}
|
/**
|
* 检查一个工位是否离线,离线则填充离线状态数据
|
* @param workstationId 工位id
|
*/
|
public void handleWorkstationOffline(long workstationId) {
|
long nowMills = System.currentTimeMillis();
|
long lastOnlineTime = nowMills - offlineConfigDuration;
|
/*
|
ProcessParam lastParam = processParamMapper.lastParamByWorkstationId(workstationId);
|
|
if(lastParam != null && lastParam.getTime()> onlineRange) {
|
//有数据,且在判定时间内-》在线
|
return;
|
}*/
|
DeviceState lastState = deviceStateMapper.lastNoFixedState(workstationId);
|
if(lastState != null && lastState.getTime() > lastOnlineTime) {
|
//有数据,且在判定时间内-》在线
|
return;
|
}
|
//TODO 这里一直离线是什么数据
|
|
XxlJobLogger.log("离线"+workstationId);
|
//时间段内无参数,说明设备没采集数据判定为离线,插入状态,然后发送realTime消息给mdc
|
|
//作为实时数据发送
|
ProcessParam statusParam = new ProcessParam();
|
statusParam.setTime(nowMills);
|
statusParam.setN("DeviceStatus");
|
statusParam.setV(OFFLINE_VALUE);
|
statusParam.setWorkstationId(workstationId);
|
|
//if(lastState == null || !lastParam.getN().equals("DeviceStatus")) {
|
if(lastState == null || lastState.getTime() <= lastOnlineTime) {
|
//之前无任何采集的数据(或者上一条不是状态数据),新加一条离线状态数据
|
//paramService.insertProcessParam(statusParam);
|
|
//插入状态表
|
DeviceState offLineState = new DeviceState();
|
offLineState.setTime(nowMills);
|
|
String calendarCode = workstationCache.getWorkstationCalendarCodeForDate(workstationId, DateUtil.formatDate(DateUtil.date(nowMills)));
|
offLineState.setCalendarCode(calendarCode);//111
|
this.fillCalendar(offLineState);
|
|
offLineState.setValueCollect(Integer.parseInt(OFFLINE_VALUE));
|
offLineState.setWcs(offLineState.getValueCollect());
|
offLineState.setWorkstationId(workstationId);
|
offLineState.setIsFixPoint(false);
|
offLineState.setIsDeleted(false);
|
offLineState.setIsSync(false);
|
|
|
deviceStateService.saveDeviceStates(Collections.singletonList(offLineState));
|
XxlJobLogger.log("保存离线状态"+workstationId);
|
}
|
|
//通知mdc更新实时状态
|
paramService.sendRealtimeDataMsg(statusParam);
|
|
}
|
|
/**
|
* 填充数据日历
|
* @param state 状态对象
|
*/
|
void fillCalendar(DeviceState state){
|
if (ObjectUtil.isEmpty(state.getCalendarCode())) {
|
state.setCalendarCode(CommonConstant.DEFAULT_CODE);
|
}
|
|
java.util.Date collectTime = new java.util.Date(state.getTime());
|
|
boolean isDefaultCalendar = true;
|
if (!CommonConstant.DEFAULT_CODE.equals(state.getCalendarCode())) {
|
CalendarShiftTimeSlicesDTO calendarShiftTimeSlicesDTO = timeSliceCache.getTimeSliceShift(state.getCalendarCode(), collectTime);//从redis中获得日历的时间切片
|
if (ObjectUtil.isEmpty(calendarShiftTimeSlicesDTO)) {
|
LocalDate targetDate = Instant.ofEpochMilli(state.getTime()).atZone(ZoneOffset.systemDefault()).toLocalDate();
|
CacheBuildDTO cacheBuildDTO = CacheBuildDTO.builder().tenantIds(Sets.newHashSet(new String[]{"000000"})).calendarCode(state.getCalendarCode()).targetDate(targetDate).build();
|
timeSliceCache.build(cacheBuildDTO);
|
calendarShiftTimeSlicesDTO = timeSliceCache.getTimeSliceShift(state.getCalendarCode(), collectTime);
|
}
|
|
if (ObjectUtil.isNotEmpty(calendarShiftTimeSlicesDTO)) {
|
state.setShiftIndex(calendarShiftTimeSlicesDTO.getShiftIndex());
|
state.setShiftTimeType(Integer.valueOf(calendarShiftTimeSlicesDTO.getShiftTimeType()));
|
state.setFactoryDate(Integer.valueOf(calendarShiftTimeSlicesDTO.getFactoryDate().replaceAll("-", "")));
|
state.setFactoryWeek(calendarShiftTimeSlicesDTO.getFactoryWeek());
|
state.setFactoryMonth(calendarShiftTimeSlicesDTO.getFactoryMonth());
|
state.setFactoryYear(calendarShiftTimeSlicesDTO.getFactoryYear());
|
isDefaultCalendar = false;
|
}
|
}
|
|
//无日历切片,使用采集时间填充factoryYear,month,date,week几个属性
|
if (isDefaultCalendar) {
|
log.info("离线检查无日历切片");
|
LocalDate localDate = Instant.ofEpochMilli(state.getTime()).atZone(ZoneOffset.systemDefault()).toLocalDate();
|
state.setFactoryDate(Integer.valueOf(DatePattern.PURE_DATE_FORMAT.format(collectTime)));
|
state.setFactoryYear(DateUtil.year(collectTime));
|
state.setFactoryWeek(LocalDateTimeUtils.getWeek(localDate));
|
state.setFactoryMonth(DateUtil.month(collectTime) + 1);
|
state.setShiftIndex(CommonConstant.DEFAULT_SHIFT_INDEX);
|
state.setShiftTimeType(CommonConstant.DEFAULT_SHIFT_TYPE);
|
}
|
}
|
|
|
}
|