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.math.RoundingMode; 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.Iterator; 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 com.moral.common.util.ReportTimeFormat; import com.moral.entity.charts.DataCondition; import com.moral.entity.charts.LineChartCriteria; import com.moral.entity.charts.PairData; import com.moral.entity.charts.TimePeriod; 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.ResourceUtil; import com.moral.common.util.ValidateUtil; import com.moral.entity.Device; import com.moral.entity.Sensor; import com.moral.mapper.DeviceMapper; import com.moral.mapper.HistoryMinutelyMapper; import com.moral.mapper.SensorMapper; import com.moral.service.HistoryMinutelyService; @Service @SuppressWarnings({ "unchecked", "rawtypes", "unused" }) public class HistoryMinutelyServiceImpl implements HistoryMinutelyService { @Resource private HistoryMinutelyMapper historyMinutelyMapper; @Resource private DeviceMapper deviceMapper; @Resource private SensorMapper sensorMapper; // volatile @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); String[] macKeys = { "e1", "e2", "e10", "e11", "e15", "e16" }; String sensorKeyColumn = ""; for (int i = 0; i < macKeys.length; i++) { sensorKeyColumn += "AVG(json -> '$." + macKeys[i] + "[0]') " + macKeys[i]; if (i != macKeys.length -1) { sensorKeyColumn += " ,"; } } parameters.put("sensorKeyColumn", sensorKeyColumn); 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)); 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(i, 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()); } Map[] maps = new HashMap[list.size()]; Set sensors = new TreeSet(new Comparator() { @Override public int compare(String o1, String o2) { return Integer.compare(Integer.valueOf(o1.split("-")[0].replace("e", "")), Integer.valueOf(o2.split("-")[0].replace("e", ""))); } }); for (Object object : dataList) { Map map = (Map)object; for (String key : map.keySet()) { if (key.startsWith("data")) { int index = Integer.valueOf(key.replace("data", "")); maps[index] = map; } if (key.startsWith("sensors")) { sensors.addAll((List) map.get(key)); } } } resultMap.put("times", timeList); resultMap.put("datas", Arrays.asList(maps)); resultMap.put("sensors", new ArrayList(sensors)); return resultMap; } public Map> getMonitorPointOrDeviceAvgData4Compare(Map parameters) throws Exception { Map> resultMap = new HashMap>(); List> resultList = getMonitorPointOrDeviceAvgData(parameters); List timeList = (List) parameters.get("timeList"); List dataList = new ArrayList(); Set sensors = new TreeSet(new Comparator() { @Override public int compare(String o1, String o2) { return Integer.compare(Integer.valueOf(o1.split("-")[0].replace("e", "")), Integer.valueOf(o2.split("-")[0].replace("e", ""))); } }); sensors.addAll((Set)parameters.get("sensors")); 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); } } } dataList.add(doubleMap); String part = parameters.get("part").toString(); resultMap.put("data" + part, dataList); resultMap.put("sensors" + part, new ArrayList(sensors)); return resultMap; } @Override public List> getMonitorPointOrDeviceAvgData(Map parameters) throws Exception { List> resultList ; String type = (String) parameters.get("type"); if (!parameters.containsKey("field")) { parameters.putAll(getElementByType(type)); } 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); if (parameters.containsKey("sensorKey")) { List sensors; try { sensors = JSON.parseObject((String)parameters.get("sensors"), new TypeReference>() {}); parameters.put("sensors", new HashSet(sensors)); } catch (Exception e) { sensors = new ArrayList(); sensors.add((String)parameters.get("sensorKey")); } String sensorKeyColumn = ""; for (int i = 0; i < sensors.size(); i++) { String sensorKey = sensors.get(i).split("-")[0]; sensorKeyColumn += "AVG(json -> '$." + sensorKey + "[0]') " + sensorKey; if (i != sensors.size() - 1) { sensorKeyColumn += " ,"; } } parameters.put("sensorKeyColumn", sensorKeyColumn); } //sensorKeys.clear(); // 监控点平均值 if (!parameters.containsKey("mac")) { resultList = new ArrayList>(); Integer monitorPointId = Integer.valueOf(parameters.get("monitorPointId").toString()); List> deviceVersions = deviceMapper.getDeviceVersionIdByMonitorPoint(monitorPointId); ExecutorService threadPool = Executors.newCachedThreadPool(); CompletionService>> cs = new ExecutorCompletionService>>(threadPool); List> list = new ArrayList>(); for (Map map : deviceVersions) { cs.submit(new Callable>>() { @Override public List> call() throws Exception { Map parameter = new HashMap(parameters); Integer deviceVersionId = (Integer) map.get("deviceVersionId"); if (!parameter.containsKey("sensorKeyColumn")) { List> sensors = sensorMapper.getSensorsByDeviceVersionId(deviceVersionId); String sensorKeyColumn = getSensorKeyColumnBySensors(sensors, parameters); parameter.put("sensorKeyColumn", sensorKeyColumn); } List macs = deviceMapper.getDeviceMacByMonitorPointAndDeviceVersion(monitorPointId, deviceVersionId); if (ObjectUtils.isEmpty(macs) || macs.contains("null") ) { return new ArrayList>(); }else { parameter.put("macs", macs); return historyMinutelyMapper.getMonitorPointOrDeviceAvgData(parameter); } } }); } for (Map map : deviceVersions) { list.addAll(cs.take().get()); } Map> result = new LinkedHashMap>(); for (Map map : list) { time = (String) map.remove("time"); Map times = new HashMap(); if (result.containsKey(time)) { times = (Map) result.get(time); } for (Map.Entry entry : map.entrySet()) { String sensorKey = entry.getKey(); Number[] doubles = new Number[3]; Double sum = (Double) entry.getValue(); Integer count = 1; if (times.containsKey(sensorKey)) { doubles = times.get(sensorKey); sum = (Double) doubles[0] + sum; count = (Integer) doubles[1] + 1; } doubles[0] = sum; doubles[1] = count; doubles[2] = new BigDecimal(sum / count).setScale(3, RoundingMode.HALF_UP).doubleValue(); times.put(sensorKey, doubles); } result.put(time, times); } Iterator>> iterator = result.entrySet().iterator(); while(iterator.hasNext()){ Entry> entry = iterator.next(); String resultTime = entry.getKey(); Map value = entry.getValue(); Map resultMap = new HashMap(); resultMap.put("time", resultTime); for (String sensorKey : value.keySet()) { resultMap.put(sensorKey, value.get(sensorKey)[2]); } resultList.add(resultMap); } // 设备 平均值 } else { // 所有传感器 if (!parameters.containsKey("sensorKeyColumn")) { String mac = (String) parameters.get("mac"); Device device = new Device(); device.setMac(mac); device = deviceMapper.selectOne(device); List> sensors = sensorMapper.getSensorsByDeviceVersionId(device.getDeviceVersionId()); String sensorKeyColumn = getSensorKeyColumnBySensors(sensors,parameters); parameters.put("sensorKeyColumn", sensorKeyColumn); } resultList = historyMinutelyMapper.getMonitorPointOrDeviceAvgData(parameters); } return resultList; } private String getSensorKeyColumnBySensors(List> sensors,Map parameters) { String sensorKeyColumn = ""; Set sensorKeys = new HashSet(); if (parameters.containsKey("sensors")) { sensorKeys = (Set) parameters.get("sensors"); } for (int i = 0; i < sensors.size(); i++) { String sensorKey = (String) sensors.get(i).get("sensor_key"); String name = (String) sensors.get(i).get("name"); String unit = (String) sensors.get(i).get("unit"); sensorKeyColumn += "AVG(json -> '$." + sensorKey + "[0]') " + sensorKey; if (i != sensors.size() - 1) { sensorKeyColumn += " ,"; } sensorKeys.add(sensorKey + "-" + name + "-" + unit ); parameters.put("sensors", sensorKeys); } return sensorKeyColumn; } @Override public Map getMonthAverageBySensor(Map parameters) { ValidateUtil.notNull(parameters.get("mac"), "param.is.null"); ValidateUtil.notNull(parameters.get("macKey"), "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); String sensorKey = (String) parameters.get("macKey"); String sensorKeyColumn = "AVG(json -> '$." + sensorKey + "[0]') " + sensorKey; parameters.put("sensorKeyColumn", sensorKeyColumn); 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-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 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; } }