环境:idea
语言:java
框架:springboot
难点:Component调用另外的service和client
思路:
创建定时任务,这里默认是3秒钟
遍历每一个设备的最新数据
根据设备的数据时间,结合设备配置的允许离线时间阈值,判断设备是否离线
设备已经处理离线状态,则不更新状态
设备未达到允许离线时间阈值,则不更新状态
设备数据时间达到允许离线时间阈值,则更新状态
部分代码参考:
new BackService().start();
package com.lhiot.lh02f000.service.job;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
//取消部分内部引用
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* **@ClassName BackService
* **@Description
* **@Date 2023/2/2 9:24
* **@Created by tangbao
**/
@Slf4j
@Component
public class BackService {
private Integer delaySecond = 3;// 延迟时间
private static final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
private static DeviceClient deviceClient;
private static DeviceTypeClient deviceTypeClient;
private static DeviceCfgService deviceCfgService;
private static DeviceStateService deviceStateService;
private static PointValueClient pointValueClient;
private static DeviceCoordinateService deviceCoordinateService;
@Resource
public void setDeviceClient(DeviceClient deviceClient) {
this.deviceClient = deviceClient;
}
@Resource
public void setDeviceTypeClient(DeviceTypeClient deviceTypeClient) {
this.deviceTypeClient = deviceTypeClient;
}
@Resource
public void setDeviceCfgService(DeviceCfgService deviceCfgService){
this.deviceCfgService = deviceCfgService;
}
@Resource
public void setDeviceStateService(DeviceStateService deviceStateService){
this.deviceStateService = deviceStateService;
}
@Resource
public void setPointValueClient(PointValueClient pointValueClient) {
this.pointValueClient = pointValueClient;
}
@Resource
public void setDeviceCoordinateService(DeviceCoordinateService deviceCoordinateService){
this.deviceCoordinateService = deviceCoordinateService;
}
public BackService() {
}
public void run() throws Exception {
scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
try {
//实时数据对比
selectRealDeviceTable();
} catch (Exception e) {
log.error(JSON.toJSONString(e));
}
}
}, 1, delaySecond, TimeUnit.SECONDS);
}
public void start() {
try {
//load spring frame work
// SpringContextHolder.loadApplicationContextXml("classpath*:applicationContext.xml");
this.run();
log.info("(♥◠‿◠)ノ゙ GPS测温设备定时任务启动成功 ლ(´ڡ`ლ)゙ \n");
// System.out.println("(♥◠‿◠)ノ゙ GPS测温设备定时任务启动成功 ლ(´ڡ`ლ)゙ \n");
} catch (Exception e) {
log.error("BackServer-BackService failed to start due to {}", JSON.toJSONString(e));
}
}
/**
* 获取设备的实时数据
* @throws Exception
*/
public void selectRealDeviceTable() throws Exception {
DeviceType deviceType = new DeviceType();
deviceType.setTypeCode("02F000");
List<DeviceType> deviceTypeList = deviceTypeClient.list(deviceType).getData().getRecords();
if (null == deviceTypeList || deviceTypeList.size() < 1) {
log.error("未查询到指定的设备类型");
return;
}
DeviceType deviceType1 = deviceTypeList.get(0);
Device device = new Device();
device.setTypeId(deviceType1.getId());
List<Device> deviceList = deviceClient.list(device).getData().getRecords();
Map<String, String> deviceStatusMap = deviceClient.deviceStatus(device).getData();
for (int i = 0; i < deviceList.size(); i++) {
Device device1 = deviceList.get(i);
String statusWeb = deviceStatusMap.get(device1.getId());
DeviceCfg deviceCfg = deviceCfgService.selectByDevId(device1.getId());
DeviceState deviceState = deviceStateService.selectByDevId(device1.getId());
if (null == deviceCfg || (deviceCfg.getOfflineMinute() == 0)) {
if (statusWeb.equals(Common.Device.Status.OFFLINE)) {
//因为没有配置,这里就直接插入设备离线状态
this.dealDevState(device1, deviceCfg, deviceState);
}
} else {
if (deviceCfg.isOfflineEn()) {
this.dealDevState(device1, deviceCfg, deviceState);
}
}
}
}
/**
* 判断设备的状态,这里只判断离线状态
* @param device 设备对象
* @param deviceCfg 设备配置对象
* @param deviceState 设备状态对象
*/
private void dealDevState(Device device, DeviceCfg deviceCfg, DeviceState deviceState) {
if (null == deviceState) {
//设备还没有插入状态,则不做任何处理
return;
} else {
//设备已经插入了状态,则需要处理
if (deviceState.getState() == 0) {
//已经处于离线状态,就不需要再更新状态,直接返回
return;
}
Map<Integer, Object> pointValueMap = this.getPointValueMap(device.getId(), "60");
if (null == pointValueMap) {
return;
}
long offlineMinute = 2; //如果设备没有配置离线时间,则默认为2分钟离线
Date date = this.getDate(pointValueMap);
long disTime = DateUtil.between(date, new Date(), DateUnit.MINUTE);
if ((null != deviceCfg) && (deviceCfg.getOfflineMinute() > 0)) {
//如果设备有配置,则判断离线
offlineMinute = deviceCfg.getOfflineMinute();
}
if(disTime > offlineMinute) {
log.info("设备离线判断执行");
DeviceCoordinate deviceCoordinate = deviceCoordinateService.selectByDevId(device.getId());
deviceState.setEndTime(new Date());
deviceStateService.update(deviceState);
DeviceState deviceState1 = new DeviceState();
deviceState1.setDeviceId(device.getId());
deviceState1.setState(0);
deviceState1.setStartTime(date); //离线开始时间用最新信号的时间
deviceState1.formatDeviceInfo(pointValueMap);
deviceState1.formatDevAddr(pointValueMap, deviceCoordinate);
deviceState1.setAlarmCode("00000");
deviceState1.setAlarmInfo("设备离线");
deviceStateService.add(deviceState1);
}
}
}
/**
* 获取实时数据的信号量和信号值
*
* @param deviceId 设备ID
* @param funCode 功能码
* @return
*/
private Map<Integer, Object> getPointValueMap(String deviceId, String funCode) {
PointValue pointValue = pointValueClient.realtime(deviceId, funCode).getData();
pointValue = Optional.ofNullable(pointValue).orElseGet(
() -> (Optional.ofNullable(pointValueClient.latest(deviceId, funCode).getData()).orElseGet(() -> new PointValue())
));
List<PointValue> pointValues = Optional.ofNullable(pointValue.getChildren()).orElseGet(() -> new ArrayList<>());
if (pointValues.size() == 0) {
return null;
}
//将list转换map
Map<Integer, Object> pointValueMap = pointValues.stream().collect(Collectors.toMap(PointValue::getPointOrderNum, Function.identity(), (n1, n2) -> n1, TreeMap::new));
if (null != pointValue.getOriginTime()) {
((PointValue) pointValueMap.get(0)).setOriginTime(pointValue.getOriginTime());
}
return pointValueMap;
}
private Date getDate(Map<Integer, Object> pointValueMap){
Date date = ((PointValue) pointValueMap.get(0)).getCreateTime();
if(null == date){
date = ((PointValue) pointValueMap.get(0)).getOriginTime();
}
return date;
}
}