EquipmentAnalysisController.java 16.3 KB
package com.skua.modules.equipment.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.skua.core.api.vo.Result;
import com.skua.core.context.SpringContextUtils;
import com.skua.core.util.DateUtils;
import com.skua.modules.equipment.dto.EquipmentAnalysisDTO;
import com.skua.modules.equipment.entity.EquipmentInfo;
import com.skua.modules.equipment.service.IEquipmentInfoService;
import com.skua.modules.system.datestandard.entity.SysMonitorMetricInfo;
import com.skua.modules.system.datestandard.entity.SysStructDict;
import com.skua.modules.system.datestandard.service.ISysMonitorMetricInfoService;
import com.skua.tool.javassist.JavassistFactory;
import com.skua.tool.query.WrapperFactory;
import com.skua.tool.util.CustomDateUtils;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.text.NumberFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <pre>
 * 设备运行状态分析
 * </pre>
 *
 * @author sonin
 * @version 1.0 2022/5/23 16:15
 */
@Slf4j
@Api(tags = "设备运行状态分析")
@RestController
@RequestMapping("/equipmentAnalysis")
public class EquipmentAnalysisController {

    @Autowired
    private IEquipmentInfoService equipmentInfoService;

    @Autowired
    private ISysMonitorMetricInfoService sysMonitorMetricInfoService;

    @GetMapping("/chartsAnalysis")
    public Result<Object> chartsAnalysisCtrl(EquipmentAnalysisDTO equipmentAnalysisDTO) throws Exception {
        Result<Object> result = new Result<>();
        // 查询厂站下的设备
        QueryWrapper<EquipmentInfo> equipmentInfoQueryWrapper = new QueryWrapper<>();
        equipmentInfoQueryWrapper.select("id")
                .eq(StringUtils.isNotEmpty(equipmentAnalysisDTO.getDepartId()), "depart_id", equipmentAnalysisDTO.getDepartId());
        List<Map<String, Object>> equipmentIdMapList = equipmentInfoService.listMaps(equipmentInfoQueryWrapper);
        List<String> equipmentIdList = equipmentIdMapList.stream().map(item -> "" + item.get("id")).collect(Collectors.toList());
        // 查询SysMonitorMetricInfo下的设备的三个指标信息
        QueryWrapper<SysMonitorMetricInfo> sysMonitorMetricInfoQueryWrapper = new QueryWrapper<>();
        sysMonitorMetricInfoQueryWrapper.select("equipment_code as equipmentCode", "metric_express1 as metricExpress1", "metric_express2 as metricExpress2", "metric_express3 as metricExpress3")
                .in("equipment_code", equipmentIdList)
                .eq("metric_type", 1);
        List<Map<String, Object>> metricInfoMapList = sysMonitorMetricInfoService.listMaps(sysMonitorMetricInfoQueryWrapper);
        if (metricInfoMapList.isEmpty()) {
            result.setMessage("未配置采集点");
            return result;
        }
        // equipmentId => pgId(nm)
        Map<String, String[]> equipmentId2PgIdMap = new LinkedHashMap<>();
        List<String> pgIdList = new ArrayList<>();
        for (Map<String, Object> item : metricInfoMapList) {
            // metricExpress1: 故障点; metricExpress2: 运行点; metricExpress3: 停止点
            equipmentId2PgIdMap.put("" + item.get("equipmentCode"), new String[]{"" + item.get("metricExpress1"), "" + item.get("metricExpress2"), "" + item.get("metricExpress3")});
            pgIdList.add("" + item.get("metricExpress1"));
            pgIdList.add("" + item.get("metricExpress2"));
            pgIdList.add("" + item.get("metricExpress3"));
        }
        // todo 测试数据 xsinsert20210101
        Date currentDate = DateUtils.parse("2021-01-01", "yyyy-MM-dd");
        // Date currentDate = DateUtils.getDate();
        // 查询出最近20s nm范围内的值
        Class XsinsertClazz = JavassistFactory.create().similarClassName("Xsinsert").className("Xsinsert" + DateUtils.format(currentDate, "yyyyMMdd")).buildClass();
        List<Map<String, Object>> pgMapList = WrapperFactory.joinWrapper()
                .select("nm", "ts", "v")
                .from(XsinsertClazz)
                .where()
                .in(true, "nm", pgIdList)
                // 暂时隐藏
                .ge(true, "ts", "" + (currentDate.getTime() / 1000 - 20))
                .orderBy(true, false, "ts")
                .queryDBForList("pg-db");
        // 遍历设备并封装结果
        int runTotal = 0, stopTotal = 0, faultTotal = 0;
        boolean faultFlag, runFlag;
        for (Map.Entry<String, String[]> item : equipmentId2PgIdMap.entrySet()) {
            faultFlag = false;
            runFlag = false;
            // 处理逻辑
            // 1. 先判断 故障指标 = 1;如果是,设备算故障,否则执行第二步
            // 2. 判断   运行指标 = 1;如果是,设备算运行,否则统一算停止
            // 故障指标
            if (StringUtils.isNotEmpty(item.getValue()[0])) {
                for (Map<String, Object> it : pgMapList) {
                    if (item.getValue()[0].equals("" + it.get("nm")) && "1".equals("" + it.get("v"))) {
                        faultTotal++;
                        faultFlag = true;
                        break;
                    }
                }
            }
            // 运行指标
            if (!faultFlag && StringUtils.isNotEmpty(item.getValue()[1])) {
                for (Map<String, Object> it : pgMapList) {
                    if (item.getValue()[1].equals("" + it.get("nm")) && "1".equals("" + it.get("v"))) {
                        runTotal++;
                        runFlag = true;
                        break;
                    }
                }
            }
            // 停止指标
            if (!faultFlag && !runFlag) {
                stopTotal++;
            }
        }
        int finalRunTotal = runTotal;
        int finalStopTotal = stopTotal;
        int finalFaultTotal = faultTotal;
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(2);
        result.setResult(new HashMap<String, Object>() {{
            // 设备利用率: 运行/总台数
            put("usePercentage", numberFormat.format(100f * finalRunTotal / equipmentIdList.size()) + "%");
            // put("usePercentage", numberFormat.format(100f * finalFaultTotal / equipmentIdList.size()) + "%");
            // 设备总台数
            put("allTotal", equipmentIdList.size());
            // 设备运行台数
            put("runTotal", finalRunTotal);
            // 设备停止台数
            put("stopTotal", finalStopTotal);
            // 设备故障台数
            put("faultTotal", finalFaultTotal);
        }});
        return result;
    }

    @GetMapping("/tableAnalysis")
    public Result<Object> tableAnalysisCtrl(EquipmentAnalysisDTO equipmentAnalysisDTO) throws Exception {
        Result<Object> result = new Result<>();
        List<Map<String, Object>> mapList = WrapperFactory.joinWrapper()
                .select("equipment_info.id as id", "equipment_info.equipment_name as equipmentName", "sys_struct_dict.struct_name as structName", "sys_monitor_metric_info.metric_express1 as metricExpress1", "sys_monitor_metric_info.metric_express2 as metricExpress2", "sys_monitor_metric_info.metric_express3 as metricExpress3")
                .from(SysMonitorMetricInfo.class)
                .innerJoin(EquipmentInfo.class, EquipmentInfo.class.getDeclaredField("id"), SysMonitorMetricInfo.class.getDeclaredField("equipmentCode"))
                .innerJoin(SysStructDict.class, SysStructDict.class.getDeclaredField("id"), SysMonitorMetricInfo.class.getDeclaredField("structCode"))
                .where()
                .eq(true, "sys_monitor_metric_info.metric_type", 1)
                .like(StringUtils.isNotEmpty(equipmentAnalysisDTO.getStructName()), "sys_struct_dict.struct_name", equipmentAnalysisDTO.getStructName())
                .like(StringUtils.isNotEmpty(equipmentAnalysisDTO.getEquipmentName()), "equipment_info.equipment_name", equipmentAnalysisDTO.getEquipmentName())
                .queryWrapperForList();
        if (mapList.isEmpty()) {
            result.setMessage("请关联构筑物!");
            return result;
        }
        // equipmentId => pgId(nm)
        Map<String, String[]> equipmentId2PgIdMap = new LinkedHashMap<>();
        List<String> pgIdList = new ArrayList<>();
        for (Map<String, Object> item : mapList) {
            // metricExpress1: 故障点; metricExpress2: 运行点; metricExpress3: 停止点
            equipmentId2PgIdMap.put("" + item.get("id"), new String[]{"" + item.get("metricExpress1"), "" + item.get("metricExpress2"), "" + item.get("metricExpress3"), "未知"});
            pgIdList.add("" + item.get("metricExpress1"));
            pgIdList.add("" + item.get("metricExpress2"));
            pgIdList.add("" + item.get("metricExpress3"));
        }
        // todo 测试数据 xsinsert20210101
        Date currentDate = DateUtils.parse("2021-01-01", "yyyy-MM-dd");
        // Date currentDate = DateUtils.getDate();
        // 查询出最近20s nm范围内的值
        Class XsinsertClazz = JavassistFactory.create().similarClassName("Xsinsert").className("Xsinsert" + DateUtils.format(currentDate, "yyyyMMdd")).buildClass();
        List<Map<String, Object>> pgMapList = WrapperFactory.joinWrapper()
                .select("nm", "ts", "v")
                .from(XsinsertClazz)
                .where()
                .in(true, "nm", pgIdList)
                // 暂时隐藏
                .ge(true, "ts", "" + (currentDate.getTime() / 1000 - 20))
                .orderBy(true, false, "ts")
                .queryDBForList("pg-db");
        boolean faultFlag, runFlag;
        for (Map.Entry<String, String[]> item : equipmentId2PgIdMap.entrySet()) {
            faultFlag = false;
            runFlag = false;
            // 处理逻辑
            // 1. 先判断 故障指标 = 1;如果是,设备算故障,否则执行第二步
            // 2. 判断   运行指标 = 1;如果是,设备算运行,否则统一算停止
            // 故障指标
            if (StringUtils.isNotEmpty(item.getValue()[0])) {
                for (Map<String, Object> it : pgMapList) {
                    if (item.getValue()[0].equals("" + it.get("nm")) && "1".equals("" + it.get("v"))) {
                        item.getValue()[3] = "故障";
                        faultFlag = true;
                        break;
                    }
                }
            }
            // 运行指标
            if (!faultFlag && StringUtils.isNotEmpty(item.getValue()[1])) {
                for (Map<String, Object> it : pgMapList) {
                    if (item.getValue()[1].equals("" + it.get("nm")) && "1".equals("" + it.get("v"))) {
                        item.getValue()[3] = "运行";
                        runFlag = true;
                        break;
                    }
                }
            }
            // 停止指标
            if (!faultFlag && !runFlag) {
                item.getValue()[3] = "停止";
            }
        }
        for (Map<String, Object> item : mapList) {
            item.put("status", equipmentId2PgIdMap.get("" + item.get("id"))[3]);
        }
        result.setResult(mapList);
        return result;
    }

    @GetMapping("/tableDetail")
    public Result<Object> tableDetailCtrl(EquipmentAnalysisDTO equipmentAnalysisDTO) throws Exception {
        Result<Object> result = new Result<>();
        QueryWrapper<SysMonitorMetricInfo> sysMonitorMetricInfoQueryWrapper = new QueryWrapper<>();
        sysMonitorMetricInfoQueryWrapper
                .eq("equipment_code", equipmentAnalysisDTO.getEquipmentId())
                .eq("metric_type", 0);
        List<SysMonitorMetricInfo> sysMonitorMetricInfoList = sysMonitorMetricInfoService.list(sysMonitorMetricInfoQueryWrapper);
        Map<String, SysMonitorMetricInfo> pgId2EntityMap = sysMonitorMetricInfoList.stream().collect(Collectors.toMap(SysMonitorMetricInfo::getId, item -> item));
        if (pgId2EntityMap.isEmpty()) {
            result.setMessage("请关联构筑物!");
            return result;
        }
        // todo 测试数据 xsinsert20210101
        Date currentDate = DateUtils.parse("2021-01-01", "yyyy-MM-dd");
        // Date currentDate = DateUtils.getDate();
        // 查询出最近20s nm范围内的值
        Class XsinsertClazz = JavassistFactory.create().similarClassName("Xsinsert").className("Xsinsert" + DateUtils.format(currentDate, "yyyyMMdd")).buildClass();
        List<Map<String, Object>> pgMapList = WrapperFactory.joinWrapper()
                .select("nm", "ts", "v")
                .from(XsinsertClazz)
                .where()
                .in(true, "nm", pgId2EntityMap.keySet())
                // 暂时隐藏
                .ge(true, "ts", "" + (currentDate.getTime() / 1000 - 20))
                .orderBy(true, false, "ts")
                .queryDBForList("pg-db");
        Map<String, Map<String, String>> pgId2ValMap = new LinkedHashMap<>();
        for (Map<String, Object> item : pgMapList) {
            pgId2ValMap.putIfAbsent("" + item.get("nm"), new HashMap<String, String>() {{
                put("val", "" + item.get("v"));
                put("ts", "" + item.get("ts"));
            }});
        }
        List<Map<String, Object>> resList = new ArrayList<>();
        for (Map.Entry<String, Map<String, String>> item : pgId2ValMap.entrySet()) {
            resList.add(new HashMap<String, Object>() {{
                put("pgId", item.getKey());
                put("pgVal", item.getValue().get("v"));
                put("dataTime", DateUtils.format(new Date(Long.parseLong("" + item.getValue().get("ts")) * 1000), "yyyy-MM-dd HH:mm:ss"));
                put("metricName", pgId2EntityMap.get(item.getKey()).getMetricName());
            }});
        }
        result.setResult(resList);
        return result;
    }

    @GetMapping("/chartsDetail")
    public Result<Object> chartsDetailCtrl(EquipmentAnalysisDTO equipmentAnalysisDTO) throws Exception {
        Result<Object> result = new Result<>();
        JdbcTemplate jdbcTemplate = (JdbcTemplate) SpringContextUtils.getBean("master");
        Map<String, Object> sysFactoryDeviceMap = jdbcTemplate.queryForMap("select device_id as deviceId from sys_factory_device where depart_id = ?", new Object[]{equipmentAnalysisDTO.getDepartId()});
        // 获取countXXX表
        Class countClazz = JavassistFactory.create().similarClassName("Count").className(sysFactoryDeviceMap.get("deviceId").toString().toLowerCase() + "Count").buildClass();
        List<Map<String, Object>> pgMapList = WrapperFactory.joinWrapper()
                .select("nm", "ts", "v")
                .from(countClazz)
                .where()
                .eq(true, "nm", equipmentAnalysisDTO.getPgId())
                .ge(true, "ts", "" + DateUtils.parse(equipmentAnalysisDTO.getStartTime(), "yyyy-MM-dd HH:mm:ss").getTime() / 1000)
                .le(true, "ts", "" + DateUtils.parse(equipmentAnalysisDTO.getEndTime(), "yyyy-MM-dd HH:mm:ss").getTime() / 1000)
                .orderBy(true, false, "ts")
                .queryDBForList("pg-db");
        // 求charts: time => pgId => val
        Map<String, Map<String, String>> time2PgId2ValMap = new LinkedHashMap<>();
        List<String> xDataList = CustomDateUtils.interval(equipmentAnalysisDTO.getStartTime(), equipmentAnalysisDTO.getEndTime(), equipmentAnalysisDTO.getTimeFormat(), equipmentAnalysisDTO.getTimeField(), 1);
        // 初始化time和pgId
        for (String time : xDataList) {
            time2PgId2ValMap.putIfAbsent(time, new LinkedHashMap<>());
            time2PgId2ValMap.get(time).put(equipmentAnalysisDTO.getPgId(), "0");
        }
        // 解析数据,获取charts结果集
        String nm, ts, v;
        for (Map<String, Object> item : pgMapList) {
            nm = "" + item.get("nm");
            ts = "" + item.get("ts");
            v = "" + item.get("v");
            String time = DateUtils.format(new Date(Long.parseLong(ts) * 1000), equipmentAnalysisDTO.getTimeFormat());
            if (time2PgId2ValMap.get(time) != null && "0".equals(time2PgId2ValMap.get(time).get(nm))) {
                time2PgId2ValMap.get(time).put(nm, v);
            }
        }
        result.setResult(time2PgId2ValMap);
        return result;
    }

}