package com.zhgd.xmgl.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.zhgd.redis.lock.RedisRepository; import com.zhgd.xmgl.enums.ParamEnum; import com.zhgd.xmgl.modules.environment.entity.RainAlarm; import com.zhgd.xmgl.modules.environment.entity.RainDev; import com.zhgd.xmgl.modules.environment.entity.RainRecord; import com.zhgd.xmgl.modules.environment.mapper.RainDevMapper; import com.zhgd.xmgl.modules.environment.service.IRainAlarmService; import com.zhgd.xmgl.modules.environment.service.IRainDevService; import com.zhgd.xmgl.modules.environment.service.IRainRecordService; import com.zhgd.xmgl.modules.project.entity.Project; import com.zhgd.xmgl.modules.project.mapper.ProjectMapper; import com.zhgd.xmgl.util.RenZhiUtil; import lombok.extern.slf4j.Slf4j; import net.javacrumbs.shedlock.core.SchedulerLock; import org.jetbrains.annotations.Nullable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @Slf4j @RestController @RequestMapping("xmgl/task") public class RainTask { public static final String REDIS_RAIN_ALARM_TASK_START_TIME = "getRainAlarmTaskStartTime"; public static final String DATA_VALUE = "dataValue"; public static final String RECORD_TIME = "recordTime"; @Resource @Lazy private IRainRecordService rainRecordService; @Resource @Lazy private IRainAlarmService rainAlarmService; @Resource @Lazy private IRainDevService rainDevService; @Lazy @Autowired private ProjectMapper projectMapper; @Lazy @Autowired private RedisRepository redisRepository; @Lazy @Autowired private RainDevMapper rainDevMapper; /** * 获取实时数据 */ @Scheduled(cron = "0 */2 * * * ?") @SchedulerLock(name = "getRainRecordTask", lockAtMostFor = 1000 * 60, lockAtLeastFor = 1000 * 60) @RequestMapping("getRainRecordTask") public void getRainRecordTask() { List projectList = projectMapper.selectList(new LambdaQueryWrapper() .ne(Project::getJnrzckAccount, "") .ne(Project::getJnrzckPw, "") ); for (Project project : projectList) { try { saveAllRecord(project); } catch (Exception e) { log.error("", e); } } } private void saveAllRecord(Project project) { List devs = rainDevService.list(new LambdaQueryWrapper().eq(RainDev::getProjectSn, project.getProjectSn())); if (CollUtil.isEmpty(devs)) { return; } Map devSnMap = devs.stream().collect(Collectors.toMap(RainDev::getDevSn, Function.identity())); JSONArray datas = RenZhiUtil.getRealTimeDataByDeviceAddr(StrUtil.join(",", devs.stream().map(RainDev::getDevSn).collect(Collectors.toList())), project.getJnrzckAccount(), project.getJnrzckPw()); if (CollUtil.isEmpty(datas)) { log.info("获取实时数据为空,项目名称:{}", project.getProjectName()); return; } List records = new ArrayList<>(); for (int i = 0; i < datas.size(); i++) { JSONObject dataJo = datas.getJSONObject(i); JSONArray dataItemJa = dataJo.getJSONArray("dataItem"); String deviceAddr = dataJo.getString("deviceAddr"); //normal:正常 //alarming:报警 //preAlarming:预警 //offline:离线 String deviceStatus = dataJo.getString("deviceStatus"); RainRecord record = new RainRecord(); RainDev dev = devSnMap.get(deviceAddr); if (CollUtil.isNotEmpty(dataItemJa)) { for (int j = 0; j < dataItemJa.size(); j++) { JSONObject itemJo = dataItemJa.getJSONObject(j); Integer nodeId = itemJo.getInteger("nodeId"); JSONArray registerItemJa = itemJo.getJSONArray("registerItem"); if (nodeId == 1) { //风力、风速 record.setWindForce(getDouble(registerItemJa, 0)); record.setWindSpeed(getDouble(registerItemJa, 1)); } else if (nodeId == 2) { record.setWindDirection(getString(registerItemJa, 0)); } else if (nodeId == 20) { record.setAccumulatedRainfall(getDouble(registerItemJa, 0)); } else if (nodeId == 21) { record.setInstantaneousRainfall(getDouble(registerItemJa, 0)); record.setCurrentRainfall(getDouble(registerItemJa, 1)); } else if (nodeId == 22) { record.setDailyRainfall(getDouble(registerItemJa, 0)); } else if (nodeId == 11) { record.setAirTemperature(getDouble(registerItemJa, 0)); record.setAirHumidity(getDouble(registerItemJa, 1)); } else if (nodeId == 14) { record.setAtmosphericPressure(getDouble(registerItemJa, 0)); } } record.setRecordTime(new Date(dataJo.getLong("timeStamp"))); record.setDevSn(deviceAddr); record.setProjectSn(dev.getProjectSn()); records.add(record); } //更新在线离线 String offline = "offline"; if (offline.equals(deviceStatus)) { if (dev != null) { if (dev.getLastUploadTime() != null && DateUtil.compare(dev.getLastUploadTime(), DateUtil.offsetMinute(new Date(), -30)) >= 0) { dev.setLastUploadTime(DateUtil.offsetMinute(new Date(), -60)); rainDevMapper.updateById(dev); } } } else { if (dev != null) { if (dev.getLastUploadTime() == null || DateUtil.compare(dev.getLastUploadTime(), DateUtil.offsetMinute(new Date(), -20)) < 0) { dev.setLastUploadTime(new Date()); rainDevMapper.updateById(dev); } } } } rainRecordService.saveBatch(records); } private String getString(JSONArray registerItemJa, int index) { return Optional.ofNullable(registerItemJa.getJSONObject(index)).map(o -> o.getString("data")).orElse(null); } @Nullable private Double getDouble(JSONArray registerItemJa, int index) { return Optional.ofNullable(registerItemJa.getJSONObject(index)).map(o -> o.getDouble("data")).orElse(null); } /** * 获取报警数据 */ @Scheduled(cron = "0 */6 * * * ?") @SchedulerLock(name = "getRainAlarmTask", lockAtMostFor = 1000 * 60 * 5, lockAtLeastFor = 1000 * 60 * 3) @RequestMapping("getRainAlarmTask") public void getRainAlarmTask() { List projectList = projectMapper.selectList(new LambdaQueryWrapper() .ne(Project::getJnrzckAccount, "") .ne(Project::getJnrzckPw, "") ); String start; Object o = redisRepository.get(REDIS_RAIN_ALARM_TASK_START_TIME); if (o != null) { start = o.toString(); } else { start = DateUtil.format(DateUtil.offsetMinute(new Date(), -5), "yyyy-MM-dd HH:mm"); } String end = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm"); redisRepository.set(REDIS_RAIN_ALARM_TASK_START_TIME, end); for (Project project : projectList) { try { saveAllAlarm(project, start, end); } catch (Exception e) { log.error("", e); } } } private void saveAllAlarm(Project project, String start, String end) { List devs = rainDevService.list(new LambdaQueryWrapper().eq(RainDev::getProjectSn, project.getProjectSn())); if (CollUtil.isEmpty(devs)) { return; } ArrayList alarms = new ArrayList<>(); String token = RenZhiUtil.getToken(project.getJnrzckAccount(), project.getJnrzckPw()); for (RainDev dev : devs) { JSONArray dataJa = RenZhiUtil.getAlarmRecordList(dev.getDevSn(), token, -1, start, end); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } if (CollUtil.isEmpty(dataJa)) { continue; } for (int j = 0; j < dataJa.size(); j++) { JSONObject jo = dataJa.getJSONObject(j); RainAlarm alarm = new RainAlarm(); alarm.setAlarmContent(getAlarmContent(jo)); alarm.setAlarmVal(jo.getDouble(DATA_VALUE)); alarm.setProjectSn(dev.getProjectSn()); alarm.setAlarmTime(new Date(jo.getLong(RECORD_TIME))); alarm.setAlarmType(getAlarmType(jo)); alarms.add(alarm); } } rainAlarmService.saveBatch(alarms); } private Integer getAlarmType(JSONObject jo) { String factorName = jo.getString("factorName"); if (StrUtil.isNotBlank(factorName)) { if (factorName.contains(ParamEnum.RainAlarmTypeEnum.WIND_FORCE.getDesc())) { return ParamEnum.RainAlarmTypeEnum.WIND_FORCE.getValue(); } else if (factorName.contains(ParamEnum.RainAlarmTypeEnum.WIND_SPEED.getDesc())) { return ParamEnum.RainAlarmTypeEnum.WIND_SPEED.getValue(); } else if (factorName.contains(ParamEnum.RainAlarmTypeEnum.WIND_DIRECTION.getDesc())) { return ParamEnum.RainAlarmTypeEnum.WIND_DIRECTION.getValue(); } else if (factorName.contains(ParamEnum.RainAlarmTypeEnum.ACCUMULATED_RAINFALL.getDesc())) { return ParamEnum.RainAlarmTypeEnum.ACCUMULATED_RAINFALL.getValue(); } else if (factorName.contains(ParamEnum.RainAlarmTypeEnum.INSTANTANEOUS_RAINFALL.getDesc())) { return ParamEnum.RainAlarmTypeEnum.INSTANTANEOUS_RAINFALL.getValue(); } else if (factorName.contains(ParamEnum.RainAlarmTypeEnum.CURRENT_RAINFALL.getDesc())) { return ParamEnum.RainAlarmTypeEnum.CURRENT_RAINFALL.getValue(); } else if (factorName.contains(ParamEnum.RainAlarmTypeEnum.DAILY_RAINFALL.getDesc())) { return ParamEnum.RainAlarmTypeEnum.DAILY_RAINFALL.getValue(); } else if (factorName.contains(ParamEnum.RainAlarmTypeEnum.AIR_TEMPERATURE.getDesc())) { return ParamEnum.RainAlarmTypeEnum.AIR_TEMPERATURE.getValue(); } else if (factorName.contains(ParamEnum.RainAlarmTypeEnum.AIR_HUMIDITY.getDesc())) { return ParamEnum.RainAlarmTypeEnum.AIR_HUMIDITY.getValue(); } else if (factorName.contains(ParamEnum.RainAlarmTypeEnum.ATMOSPHERIC_PRESSURE.getDesc())) { return ParamEnum.RainAlarmTypeEnum.ATMOSPHERIC_PRESSURE.getValue(); } } return null; } private String getAlarmContent(JSONObject jo) { /* alarmLevel int 报警级别: 25 1: 报警(超报警上限) 2: 预警(超预警上限) 3: 预警(超预警下限) 4:报警(超报警下限) -1: 离线报警 -2:遥调(开关量)报警 dataValue Double 报警值 alarmRange String 报警限值 */ String factorName = jo.getString("factorName"); Integer alarmLevel = jo.getInteger("alarmLevel"); if (Objects.equals(alarmLevel, 1) || Objects.equals(alarmLevel, 2) || Objects.equals(alarmLevel, 3) || Objects.equals(alarmLevel, 4)) { return StrUtil.format("{} {},报警值:{},报警限值:{}", factorName, getAlarmLevelStr(alarmLevel), jo.getDouble(DATA_VALUE), jo.getString("alarmRange")); } else { return StrUtil.format("{} {},报警值:{}", factorName, getAlarmLevelStr(alarmLevel), jo.getString(DATA_VALUE)); } } private String getAlarmLevelStr(Integer alarmLevel) { String s = ""; switch (alarmLevel) { case 1: s = "报警(超报警上限)"; break; case 2: s = "预警(超预警上限)"; break; case 3: s = "预警(超预警下限)"; break; case 4: s = "报警(超报警下限)"; break; case -1: s = "离线报警"; break; case -2: s = "遥调(开关量)报警"; break; default: } return s; } }