package com.moral.service.impl; import static com.moral.common.bean.Constants.NULL_VALUE; import static org.springframework.util.ObjectUtils.isEmpty; import java.math.BigDecimal; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.temporal.TemporalAdjusters; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.Callable; import java.util.concurrent.CompletionService; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.stream.Collectors; import javax.annotation.Resource; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.time.DateUtils; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; import com.moral.common.util.CalculateUtils; import com.moral.common.util.ParameterUtils; import com.moral.common.util.ReportTimeFormat; import com.moral.common.util.ResourceUtil; import com.moral.common.util.ValidateUtil; import com.moral.entity.Sensor; import com.moral.entity.charts.DataCondition; import com.moral.entity.charts.LineChartCriteria; import com.moral.entity.charts.TimePeriod; import com.moral.mapper.AlarmDailyMapper; import com.moral.mapper.DeviceMapper; import com.moral.mapper.HistoryMapper; import com.moral.mapper.HistoryMinutelyMapper; import com.moral.mapper.SensorMapper; import com.moral.service.HistoryMinutelyService; @Service @SuppressWarnings({"unchecked", "unused", "rawtypes"}) public class HistoryMinutelyServiceImpl implements HistoryMinutelyService { @Resource private HistoryMinutelyMapper historyMinutelyMapper; @Resource private HistoryMapper historyMapper; @Resource private DeviceMapper deviceMapper; @Resource private SensorMapper sensorMapper; @Resource private AlarmDailyMapper alarmDailyMapper; @Override public Map getDayAQIByDevice(Map parameters) { //ValidateUtil.notNull(parameters.get("mac"), "param.is.null"); LocalDate localDate = LocalDate.now(); // 昨日00:00:00 parameters.put("start", localDate.minusDays(1)); // 今日00:00:00 parameters.put("end", localDate); parameters.put("sensorKeys", Arrays.asList("e1", "e2", "e10", "e11", "e15", "e16")); Map average = historyMinutelyMapper.getSersionAvgByDevice(parameters); return getAQIByDataMap(average); } @Override public Map getHourAQIByDevice(Map parameters) { //ValidateUtil.notNull(parameters.get("mac"), "param.is.null"); LocalDate localDate = LocalDate.now(); System.out.println("localDate:" + localDate); // 昨日00:00:00 //parameters.put("start", localDate.minusDays(1)); Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.set(Calendar.HOUR, calendar.get(Calendar.HOUR) - 1); System.out.println("++++++" + calendar); int hour = calendar.get(Calendar.HOUR) - 1; System.out.println("当前小时减一" + hour); // 今日00:00:00 parameters.put("end", localDate); parameters.put("sensorKeys", Arrays.asList("e1", "e2", "e10", "e11", "e15", "e16")); Map average = historyMinutelyMapper.getSersionAvgByDevice(parameters); return getAQIByDataMap(average); } private Map getAQIByDataMap(Map average) { Map resultMap = new HashMap(); if (isEmpty(average)) { resultMap.put("AQI", "N/V"); } else { String[] IAQIValues = ResourceUtil.getArrValue("IAQI"); Set IAQIs = new HashSet(); for (Map.Entry entry : average.entrySet()) { double minMacKey = 0, maxMacKey = 0, minIAQI = 0, maxIAQI = 0; String[] macKeyValues = ResourceUtil.getArrValue(entry.getKey()); Double avg = entry.getValue(); if (isEmpty(avg)) { IAQIs.add(null); } else { int index = -1; for (int i = 0; i < macKeyValues.length; i++) { if (avg <= Double.valueOf(macKeyValues[i])) { if (i == 0) { index = i; } else { index = i - 1; } break; } } if (index == -1) { IAQIs.add(Double.MAX_VALUE); } else { minMacKey = Double.valueOf(macKeyValues[index]); maxMacKey = Double.valueOf(macKeyValues[index + 1]); minIAQI = Double.valueOf(IAQIValues[index]); maxIAQI = Double.valueOf(IAQIValues[index + 1]); Double result = CalculateUtils.calculateIAQI(maxIAQI, minIAQI, maxMacKey, minMacKey, avg); IAQIs.add(result); } } } IAQIs.remove(null); if (isEmpty(IAQIs)) { resultMap.put("AQI", "N/V"); } else { Double AQI = Collections.max(IAQIs); if (AQI == Double.MAX_VALUE) { resultMap.put("AQI", IAQIValues[IAQIValues.length - 1]); } else { resultMap.put("AQI", String.format("%.0f", AQI)); } } } return resultMap; } @Override public Map getCompareReport(Map parameters) throws Exception { Map resultMap = new HashMap(); List> list = JSON.parseObject((String) parameters.remove("items"), new TypeReference>>() { }); String type = (String) parameters.get("type"); // parameters.putAll(getElementByType(type)); ParameterUtils.getElementByType(parameters); Integer timeLength = Integer.valueOf(parameters.remove("timeLength").toString()); if ("month".equals(type)) { for (Map map : list) { String[] formatTime = map.get("formatTime").toString().split("-"); LocalDate localDate = LocalDate.of(Integer.valueOf(formatTime[0]), Integer.valueOf(formatTime[1]), 1); int lengthOfMonth = localDate.lengthOfMonth(); if (lengthOfMonth > timeLength) { timeLength = lengthOfMonth; } } } List timeList = new ArrayList(); for (int i = 0; i < timeLength; i++) { timeList.add(String.format("%02d", "day".equals(type) || "hour".equals(type) ? i : i + 1)); } parameters.put("timeList", timeList); ExecutorService threadPool = Executors.newCachedThreadPool(); CompletionService> cs = new ExecutorCompletionService>(threadPool); for (int i = 0; i < list.size(); i++) { Map map = list.get(i); map.put("part", i); if (ObjectUtils.isEmpty(map.get("mac"))) { map.remove("mac"); } map.put("time", map.remove("formatTime")); map.putAll(parameters); cs.submit(new Callable>() { @Override public Map call() throws Exception { return getMonitorPointOrDeviceAvgData4Compare(map); } }); } List dataList = new ArrayList(); for (Map map : list) { dataList.add(cs.take().get()); } Object[] datas = new Object[list.size()]; Object[] deviceCounts = new Object[list.size()]; Object[] alarmDatas = new Object[list.size()]; Set sensors = new TreeSet(new Comparator() { @Override public int compare(String o1, String o2) { return o1.split("-")[0].compareTo(o2.split("-")[0]); //return Integer.compare(Integer.valueOf(o1.split("-")[0].replace("e", "")), Integer.valueOf(o2.split("-")[0].replace("e", ""))); } }); Map sortMap = new HashMap(); for (Object object : dataList) { Map map = (Map) object; for (String key : map.keySet()) { int index = Integer.valueOf(key.substring(key.length() - 1)); String actual = key.substring(0, key.length() - 1); Object obj = map.get(key); switch (actual) { case "data": datas[index] = obj; break; case "deviceCount": deviceCounts[index] = obj; break; case "alarmData": alarmDatas[index] = obj; if (!ObjectUtils.isEmpty(obj)) { Map mapData = (Map) obj; BigDecimal sum = mapData.remove("sum"); for (Entry entry : mapData.entrySet()) { if (!"name".equals(entry.getKey())) { sortMap.put(entry.getKey() + "-" + index, new BigDecimal(100).multiply(entry.getValue()) .divide(sum, 2, BigDecimal.ROUND_HALF_UP).doubleValue()); } } } break; case "sensors": sensors.addAll((List) obj); break; } } } List> sortList = new ArrayList>(sortMap.entrySet()); Collections.sort(sortList, new Comparator>() { @Override public int compare(Entry o1, Entry o2) { if (o2.getValue().compareTo(o1.getValue()) == 0) { String[] key1 = o1.getKey().split("-"); String[] key2 = o2.getKey().split("-"); // String sensor1 = key1[0].replace("e", ""); // String sensor2 = key2[0].replace("e", ""); // if (Integer.valueOf(sensor1).compareTo(Integer.valueOf(sensor2)) == 0) { // return Integer.compare(Integer.valueOf(key1[1]), Integer.valueOf(key2[1])); // } // return Integer.valueOf(sensor1).compareTo(Integer.valueOf(sensor2)); if (key1[0].compareTo(key2[0]) == 0) { return Integer.compare(Integer.valueOf(key1[1]), Integer.valueOf(key2[1])); } else { return key1[0].compareTo(key2[0]); } } else { return o2.getValue().compareTo(o1.getValue()); } } }); resultMap.put("times", timeList); resultMap.put("datas", Arrays.asList(datas)); resultMap.put("deviceCounts", Arrays.asList(deviceCounts)); resultMap.put("alarmDatas", Arrays.asList(alarmDatas)); resultMap.put("sensors", new ArrayList(sensors)); resultMap.put("sortList", sortList); return resultMap; } public Map getMonitorPointOrDeviceAvgData4Compare(Map parameters) throws Exception { Map resultMap = new HashMap(); List> resultList = getMonitorPointOrDeviceAvgData(parameters); List timeList = (List) parameters.get("timeList"); List sensors = (List) parameters.get("sensors"); String part = parameters.get("part").toString(); Map doubleMap = new LinkedHashMap(); for (Map map : resultList) { String time = map.get("time").toString(); time = time.substring(time.length() - 2); int index = timeList.indexOf(time); for (String sensor : sensors) { String[] split = sensor.split("-"); String sensorKey = split[0]; if (map.containsKey(sensorKey)) { Double[] doubles; if (doubleMap.containsKey(sensor)) { doubles = doubleMap.get(sensor); } else { doubles = new Double[timeList.size()]; } doubles[index] = (Double) map.get(sensorKey); doubleMap.put(sensor, doubles); } } } Object deviceCount; if (parameters.containsKey("deviceCount")) { deviceCount = parameters.remove("deviceCount"); } else { deviceCount = deviceMapper.getDeviceCountByRegion(parameters); } resultMap.put("deviceCount" + part, deviceCount); resultMap.put("data" + part, doubleMap); resultMap.put("sensors" + part, sensors); Object type = parameters.get("type"); if ("year".equals(type) || "month".equals(type)) { parameters.put("sensorKeys", Arrays.asList("e1", "e2", "e10", "e11", "e15", "e16")); List> alarmData = alarmDailyMapper.getAlarmData(parameters); if (!ObjectUtils.isEmpty(alarmData)) { resultMap.put("alarmData" + part, alarmDailyMapper.getAlarmData(parameters).get(0)); } } return resultMap; } @Override public List> getMonitorPointOrDeviceAvgData(Map parameters) throws Exception { convertQueryParam(parameters); if (!ObjectUtils.isEmpty(parameters.get("compensate"))) { parameters.put("timeUnits", "10min"); } return historyMinutelyMapper.getMonitorPointOrDeviceAvgData(parameters); } @Override public void convertQueryParam(Map parameters) throws ParseException { if (!parameters.containsKey("field")) { // String type = (String) parameters.get("type"); // parameters.putAll(getElementByType(type)); ParameterUtils.getElementByType(parameters); } String time = (String) parameters.get("time"); String format = (String) parameters.get("format"); Integer field = Integer.valueOf(parameters.get("field").toString()); Date start = DateUtils.parseDate(time, format), end = null; if (parameters.containsKey("timeb")) { end = DateUtils.parseDate((String) parameters.get("timeb"), format); } else { Calendar instance = Calendar.getInstance(); instance.setTime(start); instance.add(field, 1); end = instance.getTime(); } parameters.put("start", start); parameters.put("end", end); List sensorKeys = new ArrayList(); List sensors = new ArrayList(); if (parameters.containsKey("sensors")) { try { sensors = JSON.parseObject((String) parameters.get("sensors"), new TypeReference>() { }); for (String sensor : sensors) { sensorKeys.add(sensor.split("-")[0]); } } catch (Exception e) { sensorKeys = sensors = (List) parameters.remove("sensors"); } } else { List sensorList = sensorMapper.getSensorsByCriteria(parameters); for (Sensor sensor : sensorList) { sensorKeys.add(sensor.getSensorKey()); String string = sensor.getSensorKey() + "-" + sensor.getName() + "-" + sensor.getUnit(); if (parameters.containsKey("description")) { string += "-" + sensor.getDescription(); } sensors.add(string); } } parameters.put("sensorKeys", sensorKeys); parameters.put("sensors", sensors); } @Override public Map getMonthAverageBySensor(Map parameters) { //ValidateUtil.notNull(parameters.get("mac"), "param.is.null"); Object sensorKey = parameters.remove("macKey"); ValidateUtil.notNull(sensorKey, "param.is.null"); Map result = new HashMap(); LocalDate end = LocalDate.now(), start; // 每月一日的数据取上月的数据 if (1 == end.getDayOfMonth()) { // 上个月1日00:00:00 start = end.plusDays(-1).with(TemporalAdjusters.firstDayOfMonth()); } else { // 这个月1日00:00:00 start = end.with(TemporalAdjusters.firstDayOfMonth()); } parameters.put("start", start); parameters.put("end", end); parameters.put("sensorKeys", Arrays.asList(sensorKey)); Map average = historyMinutelyMapper.getSersionAvgByDevice(parameters); if (isEmpty(average)) { result.put("average", NULL_VALUE); } else { result.put("average", String.format("%.2f", average.get(sensorKey))); } return result; } /** * 根据线性表单的条件规则,获取多条线性表单数据 * * @param lineChartCriteria * @return */ @Override public Map>> queryLineChartDateByCrieria(LineChartCriteria lineChartCriteria) { Map>> listMap = new HashMap<>(); List sensorKeys = lineChartCriteria.getSensorKeys(); List dataConditionList = lineChartCriteria.getDataConditions(); TimePeriod timePeriod = lineChartCriteria.getTimePeriod(); sensorKeys.forEach(sensorKey -> { listMap.put(sensorKey, new ArrayList>(dataConditionList.size())); }); dataConditionList.forEach(dataCondition -> { Map> dataMap = queryOneLineChartDateByCrieria(sensorKeys, timePeriod, dataCondition); // 数据装载 listMap.forEach((sensorKey, list) -> { List rowData = dataMap.get(sensorKey); list.add(rowData); }); }); return listMap; } /** * 根据线性表单的条件规则,获取一条线性表单数据,包含 所有检测项目 * * @param sensorKeys * @param timePeriod * @param dataCondition * @return */ public Map> queryOneLineChartDateByCrieria(List sensorKeys, TimePeriod timePeriod, DataCondition dataCondition) { List timeList = ReportTimeFormat.makeTimeList(timePeriod); List> lineChartDatas = historyMinutelyMapper.selectLineChartDateByCrieria(sensorKeys, timePeriod, dataCondition); Map> lineChartDatasWithEmpty = new HashMap<>(); // lineChartDatasWithEmpty 初始化 sensorKeys.forEach(sensorKey -> { lineChartDatasWithEmpty.put(sensorKey, timeList.stream().map(time -> { Double data = null; return data; }).collect(Collectors.toList())); }); // m 为查询data的index,此处要防止m越界 int m = 0; int dataLength = lineChartDatas.size() - 1; m = dataLength > -1 ? 0 : -1; if (m > -1) { for (int n = 0; n < timeList.size(); n++) { if (m > -1) { String time = timeList.get(n); Map rowData = lineChartDatas.get(m); String keyTime = rowData.get("format_time").toString(); if (time.equals(keyTime)) { // list to map int finalN = n; sensorKeys.forEach(sensorKey -> { Object value = rowData.get(sensorKey); List lineChartDatasWithEmptyTemp = lineChartDatasWithEmpty.get(sensorKey); if (finalN < lineChartDatasWithEmptyTemp.size()) { Double sensorValue = value != null ? new Double(value.toString()) : null; lineChartDatasWithEmptyTemp.set(finalN, sensorValue); } }); // 置为 -1,防止越界 m = m < dataLength ? m + 1 : -1; } } } } return lineChartDatasWithEmpty; } private Map getElementByType(Object type) { Map resultMap = new HashMap(); switch (type.toString()) { case "year": resultMap.put("format", "yyyy"); resultMap.put("typeFormat", "%Y-%m"); resultMap.put("timeLength", 12); resultMap.put("field", Calendar.YEAR); break; case "month": resultMap.put("format", "yyyy-MM"); resultMap.put("typeFormat", "%Y-%m-%d"); resultMap.put("timeLength", 28); resultMap.put("field", Calendar.MONTH); break; case "day": resultMap.put("format", "yyyy-MM-dd"); resultMap.put("typeFormat", "%Y-%m-%d %H"); resultMap.put("timeLength", 24); resultMap.put("field", Calendar.DATE); break; case "hour": resultMap.put("format", "yyyy-MM-dd HH"); resultMap.put("typeFormat", "%Y-%m-%d %H:%i"); resultMap.put("timeLength", 60); resultMap.put("field", Calendar.HOUR); break; } return resultMap; } /* * @description 查询无人机在时间段内的sensor值 * @author ZhuDongming * @date 2019-07-25 09:21:45 * @param parameters * @return */ @Override public List>> getSensorData(Map parameters) { String startTime = parameters.get("startTime").toString(); Boolean flag = null; try { flag = DateUtils.isSameDay(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(startTime), new Date()); } catch (ParseException e) { e.printStackTrace(); } List sensors = sensorMapper.getSensorsByMac(parameters); List sensorKeys = new ArrayList<>(); for (Sensor sensor : sensors) { sensorKeys.add(sensor.getSensorKey()); } parameters.put("sensorKeys", sensorKeys); List> listMap = null; if (flag) { listMap = historyMapper.getSensorDataToday(parameters); } else { listMap = historyMinutelyMapper.getSensorData(parameters); } List>> listMaps = new ArrayList<>(); List> listMapAvg = new ArrayList<>(); List> listMapMin = new ArrayList<>(); List> listMapMax = new ArrayList<>(); if (CollectionUtils.isNotEmpty(listMap)) { for (Map map : listMap) { Map mapAvg = new LinkedHashMap<>(); Map mapMin = new LinkedHashMap<>(); Map mapMax = new LinkedHashMap<>(); mapAvg.put("time", map.get("time")); mapMin.put("time", map.get("time")); mapMax.put("time", map.get("time")); for (String key : map.keySet()) { for (Sensor sensor : sensors) { if (sensor.getSensorKey().equals(key)) { mapAvg.put(key, new BigDecimal(map.get(key).toString()).stripTrailingZeros().toPlainString() + sensor.getUnit()); } else if (("min" + sensor.getSensorKey()).equals(key)) { mapMin.put(key.substring(3), new BigDecimal(map.get(key).toString().replace("\"", "")).stripTrailingZeros().toPlainString()); } else if (("max" + sensor.getSensorKey()).equals(key)) { mapMax.put(key.substring(3), new BigDecimal(map.get(key).toString().replace("\"", "")).stripTrailingZeros().toPlainString()); } } } listMapAvg.add(mapAvg); listMapMin.add(mapMin); listMapMax.add(mapMax); } listMaps.add(listMapAvg); listMaps.add(listMapMin); listMaps.add(listMapMax); } return listMaps; } }