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.Device; 
 | 
import com.moral.api.entity.HistoryFiveMinutely; 
 | 
import com.moral.api.entity.HistoryHourly; 
 | 
import com.moral.api.entity.MonitorPoint; 
 | 
import com.moral.api.mapper.HistoryFiveMinutelyMapper; 
 | 
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 
 | 
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.HistoryFiveMinutelyService; 
 | 
import com.moral.api.service.MonitorPointService; 
 | 
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 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.*; 
 | 
  
 | 
/** 
 | 
 * <p> 
 | 
 * 5分钟数据表 服务实现类 
 | 
 * </p> 
 | 
 * 
 | 
 * @author moral 
 | 
 * @since 2021-07-15 
 | 
 */ 
 | 
@Service 
 | 
public class HistoryFiveMinutelyServiceImpl extends ServiceImpl<HistoryFiveMinutelyMapper, HistoryFiveMinutely> implements HistoryFiveMinutelyService { 
 | 
  
 | 
    @Autowired 
 | 
    MonitorPointService monitorPointService; 
 | 
    @Autowired 
 | 
    RedisTemplate redisTemplate; 
 | 
    @Autowired 
 | 
    HistoryFiveMinutelyMapper historyFiveMinutelyMapper; 
 | 
  
 | 
    @Override 
 | 
    public List<DeviceAndFiveMinuteDataDTO> queryDeviceAndFiveMinuteData(QueryDeviceAndFiveMinuteDataForm form) { 
 | 
        //取参 
 | 
        Integer organizationId = form.getOrganizationId(); 
 | 
        Integer regionCode = form.getRegionCode(); 
 | 
        String sensorCode = form.getSensorCode(); 
 | 
        //查询组织在对应地区下的站点以及设备 
 | 
        List<MonitorPoint> monitorPoints = monitorPointService.queryByOrgIdAndRegionCode(new MonitorPointQueryForm(organizationId, regionCode)); 
 | 
        List<Device> devices = new ArrayList<>(); 
 | 
        for (MonitorPoint monitorPoint : monitorPoints) { 
 | 
            List<Device> monitorPointDevices = monitorPoint.getDevices(); 
 | 
            if (!ObjectUtils.isEmpty(monitorPointDevices)) 
 | 
                devices.addAll(monitorPointDevices); 
 | 
        } 
 | 
        //查询所有设备对应的数据 
 | 
        List<DeviceAndFiveMinuteDataDTO> dtos = new ArrayList<>(); 
 | 
        for (Device device : devices) { 
 | 
            DeviceAndFiveMinuteDataDTO dto = new DeviceAndFiveMinuteDataDTO(); 
 | 
            String mac = device.getMac(); 
 | 
            //从缓存中获取 
 | 
            Map<String, Object> sensorValues = (Map<String, Object>) redisTemplate.opsForHash().get(RedisConstants.DATA_FIVE_MINUTES, mac); 
 | 
            //如果没有数据从数据库查询 
 | 
            HistoryFiveMinutely dbHistoryFiveMinutely = queryLastDataByMac(mac); 
 | 
            if(ObjectUtils.isEmpty(dbHistoryFiveMinutely)) 
 | 
                continue; 
 | 
            String dbDataStr = dbHistoryFiveMinutely.getValue(); 
 | 
            sensorValues = JSON.parseObject(dbDataStr, HashMap.class); 
 | 
            Map<String,Object> 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 HistoryFiveMinutely queryLastDataByMac(String mac) { 
 | 
        QueryWrapper<HistoryFiveMinutely> queryWrapper = new QueryWrapper<>(); 
 | 
        queryWrapper.eq("mac",mac); 
 | 
        queryWrapper.orderByDesc("time"); 
 | 
        queryWrapper.last("limit 0,1"); 
 | 
        List<HistoryFiveMinutely> historyFiveMinutelies = historyFiveMinutelyMapper.selectList(queryWrapper); 
 | 
        if(ObjectUtils.isEmpty(historyFiveMinutelies)) 
 | 
            return null; 
 | 
        return historyFiveMinutelies.get(0); 
 | 
    } 
 | 
  
 | 
  
 | 
    @Override 
 | 
    public List<Object> getAreaWindData(Map<String, Object> params) { 
 | 
        String timeUnits = DateUtils.dateToDateString(new Date(), DateUtils.yyyyMM_EN); 
 | 
        params.put("timeUnits", timeUnits); 
 | 
        //风场数据 
 | 
        List<WindData> windData = historyFiveMinutelyMapper.getAreaWindData(params); 
 | 
        return getWindData(windData); 
 | 
    } 
 | 
  
 | 
  
 | 
    /** 
 | 
     * 根据输入的地点坐标计算中心点 
 | 
     * 
 | 
     * @param geoCoordinateList 
 | 
     * @return 
 | 
     */ 
 | 
    public Map<String, Double> getCenterPoint(List<GeoCoordinates> 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<String, Double> map = new HashMap<>(); 
 | 
        map.put("lng", Lon * 180 / Math.PI); 
 | 
        map.put("lat", Lat * 180 / Math.PI); 
 | 
        return map; 
 | 
    } 
 | 
  
 | 
    public List<Object> getWindData(List<WindData> windData) { 
 | 
        List<GeoCoordinates> points = new ArrayList<>(); 
 | 
        int length = 2000; 
 | 
        int perdlen = 200; 
 | 
        Double loma = 0d; 
 | 
        Double lomi = 0d; 
 | 
        Double lama = 0d; 
 | 
        Double lami = 0d; 
 | 
        List<Double> loList = new ArrayList<>(); 
 | 
        List<Double> laList = new ArrayList<>(); 
 | 
        Double U; 
 | 
        Double V; 
 | 
        //结果集 
 | 
        List<Object> list = new ArrayList<>(); 
 | 
        List<Map<String, Object>> 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<String, Object> 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<String, Double> 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<String, Object> 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 lo2 = loma + length * 0.00001141; 
 | 
        Double la2 = lami - length * 0.00000899; 
 | 
        Double la1 = lama + length * 0.00000899; 
 | 
  
 | 
        double dx = 0.00001141 * perdlen; 
 | 
        double dy = 0.00000899 * perdlen; 
 | 
        int nx = (int) Math.floor((lo2 - lo1) / dx); 
 | 
        int ny = (int) Math.floor((la1 - la2) / dy); 
 | 
  
 | 
  
 | 
        List<Double> uList = new ArrayList<>(); 
 | 
        List<Double> 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<com.moral.api.entity.HistoryHourly> 
 | 
     * @Author: 陈凯裕 
 | 
     * @Date: 2021/9/23 
 | 
     */ 
 | 
    public List<HistoryFiveMinutely> getValueByMacAndTime(String mac, Date startDate, Date endDate){ 
 | 
        QueryWrapper<HistoryFiveMinutely> wrapper = new QueryWrapper<>(); 
 | 
        wrapper.eq("mac",mac); 
 | 
        wrapper.between("time",startDate,endDate); 
 | 
        List<String> tableNames = MybatisPLUSUtils.getTableNamesByWrapper(startDate, endDate, SeparateTableType.MONTH); 
 | 
        List<HistoryFiveMinutely> datas = multiTableQuery(wrapper, tableNames); 
 | 
        return datas; 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * @Description: 多表查询,传入表名集合,以及条件wrapper,返回数据 
 | 
     * @Param: [wrapper, tableNames] 
 | 
     * @return: java.util.List<com.moral.api.entity.HistoryHourly> 
 | 
     * @Author: 陈凯裕 
 | 
     * @Date: 2021/9/23 
 | 
     */ 
 | 
    private List<HistoryFiveMinutely> multiTableQuery(QueryWrapper<HistoryFiveMinutely> wrapper,List<String> tableNames){ 
 | 
        List<HistoryFiveMinutely> result = new ArrayList<>(); 
 | 
        for (String tableName : tableNames) { 
 | 
            MybatisPlusConfig.tableName.set(tableName); 
 | 
            List<HistoryFiveMinutely> datas = historyFiveMinutelyMapper.selectList(wrapper); 
 | 
            result.addAll(datas); 
 | 
        } 
 | 
        return result; 
 | 
    } 
 | 
  
 | 
  
 | 
  
 | 
  
 | 
} 
 |