package com.moral.api.service.impl; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.ISqlSegment; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments; import com.baomidou.mybatisplus.core.conditions.segments.NormalSegmentList; import com.moral.api.config.mybatis.MybatisPlusConfig; import com.moral.api.entity.*; import com.moral.api.mapper.HistoryFiveMinutelyMapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.moral.api.mapper.HistoryHourlyMapper; import com.moral.api.pojo.dto.Wind.WindData; import com.moral.api.pojo.dto.historyFiveMinutely.DeviceAndFiveMinuteDataDTO; import com.moral.api.pojo.form.device.MonitorPointQueryForm; import com.moral.api.pojo.form.historyFiveMinutely.QueryDeviceAndFiveMinuteDataForm; import com.moral.api.service.DeviceService; import com.moral.api.service.HistoryFiveMinutelyService; import com.moral.api.service.MonitorPointService; import com.moral.api.utils.UnitConvertUtils; import com.moral.constant.Constants; import com.moral.constant.RedisConstants; import com.moral.constant.SeparateTableType; import com.moral.util.DateUtils; import com.moral.util.MybatisPLUSUtils; import io.lettuce.core.GeoCoordinates; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils; import java.util.*; /** *

* 5分钟数据表 服务实现类 *

* * @author moral * @since 2021-07-15 */ @Service @Slf4j public class HistoryFiveMinutelyServiceImpl extends ServiceImpl implements HistoryFiveMinutelyService { @Autowired MonitorPointService monitorPointService; @Autowired RedisTemplate redisTemplate; @Autowired HistoryFiveMinutelyMapper historyFiveMinutelyMapper; @Autowired HistoryHourlyMapper historyHourlyMapper; @Autowired DeviceService deviceService; @Override public List queryDeviceAndFiveMinuteData(QueryDeviceAndFiveMinuteDataForm form) { //取参 Integer organizationId = form.getOrganizationId(); Integer regionCode = form.getRegionCode(); String sensorCode = form.getSensorCode(); //查询组织在对应地区下的站点以及设备 List monitorPoints = monitorPointService.queryByOrgIdAndRegionCode(new MonitorPointQueryForm(organizationId, regionCode)); List devices = new ArrayList<>(); for (MonitorPoint monitorPoint : monitorPoints) { List monitorPointDevices = monitorPoint.getDevices(); if (!ObjectUtils.isEmpty(monitorPointDevices)) { //过滤掉线设备 for (Device device : monitorPointDevices) { if (!device.getState().equals(Constants.DEVICE_STATE_OFFLINE)) devices.add(device); } } } //查询所有设备对应的数据 List dtos = new ArrayList<>(); if (form.getChooseTime().equals("true")) { String time = form.getTime(); String timeUnits = DateUtils.stringToDateString(time, "yyyy-MM-dd HH:mm", DateUtils.yyyyMM_EN); for (Device device : devices) { DeviceAndFiveMinuteDataDTO dto = new DeviceAndFiveMinuteDataDTO(); String mac = device.getMac(); String dbDataStr = historyHourlyMapper.queryLastHourlyMac(mac, time, timeUnits); // String dbDataStr = historyFiveMinutelyMapper.queryLastFiveMinutely(mac, time, timeUnits); HashMap sensorValues = JSON.parseObject(dbDataStr, HashMap.class); Map sensorValue = new HashMap<>(); if (sensorValues != null && sensorValues.get(sensorCode) != null) sensorValue.put(sensorCode, sensorValues.get(sensorCode)); else sensorValue.put(sensorCode, null); dto.setDevice(device); dto.setSensorValue(sensorValue); dtos.add(dto); } return dtos; } for (Device device : devices) { DeviceAndFiveMinuteDataDTO dto = new DeviceAndFiveMinuteDataDTO(); String mac = device.getMac(); Map sensorValues = queryLastDataByMac(mac); String dbDataStr = JSON.toJSONString(sensorValues); sensorValues = JSON.parseObject(dbDataStr, HashMap.class); Map sensorValue = new HashMap<>(); if (sensorValues != null && sensorValues.get(sensorCode) != null) sensorValue.put(sensorCode, sensorValues.get(sensorCode)); else sensorValue.put(sensorCode, null); dto.setDevice(device); dto.setSensorValue(sensorValue); dtos.add(dto); } return dtos; } @Override public Map queryLastDataByMac(String mac) { //从缓存中获取 Map sensorValues = (Map) redisTemplate.opsForHash().get(RedisConstants.DATA_FIVE_MINUTES, mac); //如果没有数据从数据库查询 if (sensorValues != null) return sensorValues; QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("mac", mac); queryWrapper.orderByDesc("time"); queryWrapper.last("limit 0,1"); //获取当月的表名 Date date = new Date(); List tableNames = MybatisPLUSUtils.getTableNamesByWrapper(date, date, SeparateTableType.MONTH); List datas = multiTableQuery(queryWrapper, tableNames); if (ObjectUtils.isEmpty(datas)) return null; HistoryFiveMinutely historyFiveMinutely = datas.get(0); sensorValues = JSON.parseObject(historyFiveMinutely.getValue(), Map.class); sensorValues.put("dataTime", DateUtils.dateToDateString(historyFiveMinutely.getTime(), "yyyy-MM-dd HH:mm:ss")); return sensorValues; } @Override public List getAreaWindData(Map params) { // String timeUnits = DateUtils.dateToDateString(new Date(), DateUtils.yyyyMM_EN); // params.put("timeUnits", timeUnits); // //风场数据 // List windData = historyFiveMinutelyMapper.getAreaWindData(params); // return getWindData(windData); String chooseTime = params.get("chooseTime").toString(); List windData = null; if (chooseTime.equals("true")) { String time = params.get("time").toString(); String timeUnits = DateUtils.stringToDateString(time, "yyyy-MM-dd HH:mm", DateUtils.yyyyMM_EN); params.put("timeUnits", timeUnits); windData = historyHourlyMapper.getArea(params); } else { String timeUnits = DateUtils.dateToDateString(new Date(), DateUtils.yyyyMM_EN); params.put("timeUnits", timeUnits); //风场数据 windData = historyFiveMinutelyMapper.getAreaWindData(params); } log.info("风场数据:{}", windData); return getWindData(windData); } //获取五分钟弹窗数据 @Override public Map getPopDataByMac(Map params) { // Map datas = queryLastDataByMac(mac); String chooseTime = params.get("chooseTime").toString(); String mac = params.get("mac").toString(); Map datas = null; if (chooseTime.equals("true")) { String time = params.get("time").toString(); String timeUnits = DateUtils.stringToDateString(time, "yyyy-MM-dd HH:mm", DateUtils.yyyyMM_EN); String dbDataStr = historyHourlyMapper.queryLastHourlyMac(mac, time, timeUnits); if (dbDataStr == null) { return null; } // String dbDataStr = historyFiveMinutelyMapper.queryLastFiveMinutely(mac, time, timeUnits); datas = JSON.parseObject(dbDataStr, HashMap.class); datas.put("dataTime", time); } else { datas = queryLastDataByMac(mac); } //构建返回对象 Map result = new HashMap<>(); //创建返回因子code集合 List sensorCodes = Arrays.asList("a34004", "a34002", "a21005", "a21004", "a21026", "a05024", "a99054", "a01008", "a01007"); //获取设备信息 Device device = deviceService.getDeviceUnitAlramInforByMac(mac); //转换数据单位和名称 for (Sensor sensor : device.getVersion().getSensors()) { if (!sensorCodes.contains(sensor.getCode())) continue; Object dataO = datas.get(sensor.getCode()); if (dataO != null) { String data = String.valueOf(dataO); //转换单位 if (!sensor.getShowUnitKey().equals(sensor.getUnitKey())) data = UnitConvertUtils.calculate(data, sensor.getFormula()); //拼接单位 data = data + " " + sensor.getShowUnit(); result.put(sensor.getCode(), data); } else { result.put(sensor.getCode(), "-"); } } //添加设备名称 result.put("name", device.getName()); //添加时间 result.put("dataTime", datas.get("dataTime")); //排序 return orderSixParam(result); } //对六参以及时间进行排序 private Map orderSixParam(Map data) { LinkedHashMap result = new LinkedHashMap(); Object PM2_5 = data.get("a34004"); Object PM10 = data.get("a34002"); Object SO2 = data.get("a21026"); Object NO2 = data.get("a21004"); Object CO = data.get("a21005"); Object O3 = data.get("a05024"); Object a01008 = data.get("a01008"); Object a01007 = data.get("a01007"); Object name = data.get("name"); Object time = data.get("dataTime"); if (name != null) result.put("名称", name); if (PM2_5 != null) result.put("PM2.5", PM2_5); if (PM10 != null) result.put("PM10", PM10); if (SO2 != null) result.put("二氧化硫(SO₂)", SO2); if (NO2 != null) result.put("二氧化氮(NO₂)", NO2); if (CO != null) result.put("一氧化碳(CO)", CO); if (O3 != null) result.put("臭氧(O₃)", O3); if (time != null) result.put("时间", time); if (a01008 != null) result.put("风向", a01008); if (a01007 != null) result.put("风速", a01007); return result; } /** * 根据输入的地点坐标计算中心点 * * @param geoCoordinateList * @return */ public Map getCenterPoint(List geoCoordinateList) { int total = geoCoordinateList.size(); double X = 0, Y = 0, Z = 0; for (GeoCoordinates g : geoCoordinateList) { double lat, lon, x, y, z; lat = (double) g.getY() * Math.PI / 180; lon = (double) g.getX() * Math.PI / 180; x = Math.cos(lat) * Math.cos(lon); y = Math.cos(lat) * Math.sin(lon); z = Math.sin(lat); X += x; Y += y; Z += z; } X = X / total; Y = Y / total; Z = Z / total; double Lon = Math.atan2(Y, X); double Hyp = Math.sqrt(X * X + Y * Y); double Lat = Math.atan2(Z, Hyp); Map map = new HashMap<>(); map.put("lng", Lon * 180 / Math.PI); map.put("lat", Lat * 180 / Math.PI); return map; } public List getWindData(List windData) { List points = new ArrayList<>(); int length = 2000; int perdlen = 200; Double loma = 0d; Double lomi = 0d; Double lama = 0d; Double lami = 0d; List loList = new ArrayList<>(); List laList = new ArrayList<>(); Double U; Double V; //结果集 List list = new ArrayList<>(); List> mapList = new ArrayList<>(); for (WindData data : windData) { //经度 Double longitude = data.getLongitude(); //纬度 Double latitude = data.getLatitude(); GeoCoordinates geoCoordinates = GeoCoordinates.create(longitude, latitude); points.add(geoCoordinates); loList.add(longitude); laList.add(latitude); Map map = new HashMap<>(); //风向 Double windDir = data.getWindDir(); //风速 Double windSpeed = data.getWindSpeed(); if (windDir == null) { windDir = 0d; windSpeed = 0d; } double dir = (360.0 - (windDir + 180.0) * Math.PI / 180.0); //余弦值 U = windSpeed * Math.cos(dir); //三角正弦值 V = windSpeed * Math.sin(dir); map.put("lo", longitude); map.put("la", latitude); map.put("U", U); map.put("V", V); mapList.add(map); } //根据所有多个站点经纬度获取中心点 Map centerPoint = getCenterPoint(points); if (loList.size() > 0) { loma = Collections.max(loList); lomi = Collections.min(loList); } if (laList.size() > 0) { lama = Collections.max(laList); lami = Collections.min(laList); } Map laLaMap = new HashMap<>(); laLaMap.put("maxLo", loma); laLaMap.put("minLo", lomi); laLaMap.put("maxLa", lama); laLaMap.put("minLa", lami); Double lo1 = lomi - length * 0.00001141; // Double lo1 = lomi - length * 0.000001141 * 2; Double lo2 = loma + length * 0.00001141; // Double lo2 = loma + length * 0.000001141 * 2; // Double la2 = lami - length * 0.000000899 * 2; Double la2 = lami - length * 0.00000899; // Double la1 = lama + length * 0.000000899 * 2; Double la1 = lama + length * 0.00000899; double dx = 0.00001141 * perdlen; double dy = 0.00000899 * perdlen; // double dx = 0.000001141 * perdlen * 2; // double dy = 0.000000899 * perdlen * 2; int nx = (int) Math.floor((lo2 - lo1) / dx); int ny = (int) Math.floor((la1 - la2) / dy); List uList = new ArrayList<>(); List vList = new ArrayList<>(); int x; int y; for (int i = 0; i < mapList.size(); i++) { Double lo = (Double) mapList.get(i).get("lo"); Double la = (Double) mapList.get(i).get("la"); x = (int) Math.floor((lo - lo1) / dx); y = Math.abs((int) Math.floor((la - la1) / dy)); U = (Double) mapList.get(i).get("U"); V = (Double) mapList.get(i).get("V"); if (i == 0) { for (int j = 0; j < nx * ny; j++) { uList.add(0.0); vList.add(0.0); } } for (int j = 0; j < nx * ny; j++) { if (i == 0) { if ((y >= 2 && j == (y) * nx + x)) { int k; for (k = j - 2 * nx; k <= j + 2 * nx; k = k + nx) { uList.set(k, U); uList.set(k - 1, U); uList.set(k - 2, U); uList.set(k + 1, U); uList.set(k + 2, U); vList.set(k, V); vList.set(k - 1, V); vList.set(k - 2, V); vList.set(k + 1, V); vList.set(k + 2, V); } } } else { if (y >= 1 && j == y * nx + x) { int k; for (k = j - 2 * nx; k <= j + 2 * nx; ) { uList.set(k - 1, U); uList.set(k - 2, U); uList.set(k + 1, U); uList.set(k + 2, U); vList.set(k - 1, V); vList.set(k - 2, V); vList.set(k + 1, V); vList.set(k + 2, V); k = k + nx; } uList.set(j, U); vList.set(j, V); } } } } String uData = "\"" + "data" + "\"" + ": " + uList; String vData = "\"" + "data" + "\"" + ": " + vList; String header1 = "\"" + "header" + "\"" + ": " + "{" + "\"" + "parameterUnit" + "\"" + ": " + "\"" + "m/s" + "\"" + ", " + "\"" + "parameterNumber" + "\"" + ": " + 2 + ", " + "\"" + "dx" + "\"" + ": " + dx + ", " + "\"" + "dy" + "\"" + ": " + dy + ", " + "\"" + "parameterNumberName" + "\"" + ": " + "\"" + "eastward_wind" + "\"" + ", " + "\"" + "la1" + "\"" + ": " + la1 + ", " + "\"" + "la2" + "\"" + ": " + la2 + ", " + "\"" + "parameterCategory" + "\"" + ": " + 2 + ", " + "\"" + "lo1" + "\"" + ": " + lo1 + ", " + "\"" + "lo2" + "\"" + ": " + lo2 + ", " + "\"" + "nx" + "\"" + ": " + nx + ", " + "\"" + "ny" + "\"" + ": " + ny + ", " + "\"" + "refTime" + "\"" + ": " + "\"" + "2020-07-22 23:00:00" + "\"" + "}"; String header2 = "\"" + "header" + "\"" + ": " + "{" + "\"" + "parameterUnit" + "\"" + ": " + "\"" + "m/s" + "\"" + ", " + "\"" + "parameterNumber" + "\"" + ": " + 3 + ", " + "\"" + "dx" + "\"" + ": " + dx + ", " + "\"" + "dy" + "\"" + ": " + dy + ", " + "\"" + "parameterNumberName" + "\"" + ": " + "\"" + "eastward_wind" + "\"" + ", " + "\"" + "la1" + "\"" + ": " + la1 + ", " + "\"" + "la2" + "\"" + ": " + la2 + ", " + "\"" + "parameterCategory" + "\"" + ": " + 2 + ", " + "\"" + "lo1" + "\"" + ": " + lo1 + ", " + "\"" + "lo2" + "\"" + ": " + lo2 + ", " + "\"" + "nx" + "\"" + ": " + nx + ", " + "\"" + "ny" + "\"" + ": " + ny + ", " + "\"" + "refTime" + "\"" + ": " + "\"" + "2020-07-22 23:00:00" + "\"" + "}"; String s1 = "[" + "{" + header1 + ", " + uData + "}" + ", " + "{" + header2 + ", " + vData + "}" + "]"; JSONArray jsonArray = JSONArray.parseArray(s1); list.add(jsonArray); list.add(centerPoint.get("lng")); list.add(centerPoint.get("lat")); list.add(laLaMap); return list; } /** * @Description: 查询一段时间内某一mac的数据 * @Param: [mac, startDate, endDate] * @return: java.util.List * @Author: 陈凯裕 * @Date: 2021/9/23 */ public List getValueByMacAndTime(String mac, Date startDate, Date endDate) { QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("mac", mac); wrapper.between("time", startDate, endDate); List tableNames = MybatisPLUSUtils.getTableNamesByWrapper(startDate, endDate, SeparateTableType.MONTH); List datas = multiTableQuery(wrapper, tableNames); return datas; } /** * @Description: 多表查询,传入表名集合,以及条件wrapper,返回数据 * @Param: [wrapper, tableNames] * @return: java.util.List * @Author: 陈凯裕 * @Date: 2021/9/23 */ private List multiTableQuery(QueryWrapper wrapper, List tableNames) { List result = new ArrayList<>(); for (String tableName : tableNames) { MybatisPlusConfig.tableName.set(tableName); List datas = historyFiveMinutelyMapper.selectList(wrapper); result.addAll(datas); } MybatisPlusConfig.tableName.remove(); return result; } }