package com.jjt.biz.service.impl; import com.jjt.biz.domain.TwinDevice; import com.jjt.biz.service.IApiService; import com.jjt.biz.service.ITwinDeviceService; import com.jjt.biz.vo.*; import com.jjt.calc.domain.TwinCalcDay; import com.jjt.calc.service.ITwinCalcDayService; import com.jjt.calc.service.ITwinFormulaInfoService; import com.jjt.calc.service.ITwinPanHeadInfoService; import com.jjt.common.constant.CacheConstants; import com.jjt.common.core.redis.RedisCache; import com.jjt.utils.AsyncService; import com.jjt.utils.IotService; import com.jjt.utils.Tools; import com.jjt.ws.domain.TwinWorkshopCalc; import com.jjt.ws.service.ITwinWorkshopCalcService; import com.jjt.ws.service.ITwinWorkshopService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.util.*; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.stream.Collectors; /** * 首页统计数据 * * @author wukai * @date 2024/5/4 20:35 */ @Service @Slf4j public class ApiServiceImpl implements IApiService { @Resource private ITwinCalcDayService twinCalcDayService; @Resource private ITwinPanHeadInfoService panHeadInfoService; @Resource private ITwinDeviceService deviceService; @Resource private IotService iotService; @Resource private AsyncService asyncService; @Resource private ITwinFormulaInfoService twinFormulaInfoService; @Resource private RedisCache redisCache; @Resource private ITwinWorkshopService workshopService; @Resource private ITwinWorkshopCalcService wsCalcService; /** * 首页统计数据 */ @Override public void today() { List weekDataList = new ArrayList<>(); IndexData indexData = new IndexData(); IndexEfficiency efficiency = new IndexEfficiency(); TwinCalcDay calcDay = twinCalcDayService.today(); /* 获取当天产量数据 */ efficiency.setAEfficiency(calcDay.getEfficiencyA().floatValue()); efficiency.setBEfficiency(calcDay.getEfficiencyB().floatValue()); efficiency.setTotalLength(calcDay.getLength().floatValue()); efficiency.setALength(calcDay.getLengthA().floatValue()); efficiency.setBLength(calcDay.getLengthB().floatValue()); //界面上重新计算重量 2024-12-25 用总长度除以373 BigDecimal tw = calcDay.getLength().divide(BigDecimal.valueOf(373), 2, BigDecimal.ROUND_HALF_UP); BigDecimal aw = calcDay.getLengthA().divide(BigDecimal.valueOf(373), 2, BigDecimal.ROUND_HALF_UP); BigDecimal bw = calcDay.getLengthB().divide(BigDecimal.valueOf(373), 2, BigDecimal.ROUND_HALF_UP); efficiency.setTotalWeight(tw.floatValue()); efficiency.setAWeight(aw.floatValue()); efficiency.setBWeight(bw.floatValue()); efficiency.setATime(calcDay.getOpenTimeA().divide(BigDecimal.valueOf(3600), 2, BigDecimal.ROUND_HALF_UP).floatValue()); efficiency.setBTime(calcDay.getOpenTimeB().divide(BigDecimal.valueOf(3600), 2, BigDecimal.ROUND_HALF_UP).floatValue()); //如果产量累计产量为0,则稼动和生产时间都为0 if (efficiency.getALength() == 0f) { efficiency.setAEfficiency(0f); efficiency.setATime(0f); } //如果产量累计产量为0,则稼动和生产时间都为0 if (efficiency.getBLength() == 0f) { efficiency.setBEfficiency(0f); efficiency.setBTime(0f); } indexData.setEfficiency(efficiency); //7点前是属于前一生产天,所以这里直接减7小时即可 LocalDateTime ldt = LocalDateTime.now().minusHours(7); //获取前面7天的数据 LocalDate localDate = ldt.toLocalDate().minusDays(7); // TwinWorkshop ws = workshopService.selectTwinWorkshopByWsCode("WS02-D"); Date date = Date.from(localDate.atStartOfDay(ZoneOffset.of("+8")).toInstant()); List wsCalcList = wsCalcService.listByWsCodeDate("WS02-D", date); //按日期统计用量 Map resultMap = wsCalcList.stream().collect(Collectors.toMap(TwinWorkshopCalc::getDataDate, obj -> obj)); List list = twinCalcDayService.selectTwinCalcDayListByTime(date); Map> dayGroup = list.stream().collect(Collectors.groupingBy(TwinCalcDay::getTime, LinkedHashMap::new, Collectors.toList())); for (Map.Entry> entry : dayGroup.entrySet()) { TwinCalcDay day = new TwinCalcDay(entry.getKey()); List days = entry.getValue(); day.calcDays(days); WeekData weekData = new WeekData(); weekData.convert(day); TwinWorkshopCalc ws = resultMap.get(entry.getKey()); if (ws != null) { weekData.setAKwh(ws.getAValue()); weekData.setBKwh(ws.getBValue()); weekData.setKwh(ws.getTotalValue()); } else { weekData.setAKwh(BigDecimal.ZERO); weekData.setBKwh(BigDecimal.ZERO); weekData.setKwh(BigDecimal.ZERO); } weekDataList.add(weekData); } indexData.setWeekData(weekDataList); IndexDevice device = new IndexDevice(); device.setRunningRatio(calcDay.getRunningRatio()); indexData.setDevice(device); redisCache.setCacheObject(CacheConstants.INDEX_CALC, indexData); } /** * 统计当前数据 */ @Override public void curr() { IndexData indexData = new IndexData(); List alarmList = new ArrayList<>(); //配方统计数据 List formulaTotal = new ArrayList<>(); //配方明细数据 List formulaDetail = new ArrayList<>(); //送经量 List warpList = new ArrayList<>(); //平方米克重统计数据 List gramMasses = new ArrayList<>(); //平方米克重明细数据 List gramMassDetails = new ArrayList<>(); iotService.getToken(); TwinDevice searchDevice = new TwinDevice(); searchDevice.setOnline("1"); List list = deviceService.selectTwinDeviceList(searchDevice); List>> futureList = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { TwinDevice twinDevice = list.get(i); futureList.add(asyncService.currData(twinDevice)); } int stop1 = 0, stop2 = 0, stop6 = 0, stop8 = 0, onlineNum = 0, otherStop = 0, stopPan = 0; //停机明细 List stopList = new ArrayList<>(); //所有设备当前数据 Map> currMap = new HashMap<>(16); try { for (Future> future : futureList) { Map map = future.get(); TwinDevice device = (TwinDevice) map.get("device"); //判断是否小经编 boolean isSmall = device.getDeviceCode().startsWith("C_"); currMap.put(device.getDeviceCode(), map); StopDetailVO sdVO = new StopDetailVO(); sdVO.setDeviceId(device.getDeviceId()); sdVO.setDeviceName(device.getDeviceName()); sdVO.setHasData(true); int total = (int) map.get("total"); if (total == 0) { //可能会出现接口返回无数据的情况,需要设置设备状态为离线 sdVO.setHasData(false); stopList.add(sdVO); otherStop++; continue; } float speed = (float) map.get("Capacity_data_1"); int stopStatus = (int) map.get("Capacity_data_48"); Object data4 = map.get("Capacity_data_4"); if (device.getDeviceCode().startsWith("D_")) { speed = (float) map.get("Capacity_data_117"); stopStatus = (int) map.get("Capacity_data_118"); data4 = map.get("Capacity_data_110"); } sdVO.setStop(stopStatus); sdVO.setSpeed(speed); stopList.add(sdVO); if (data4 instanceof Integer && (Integer) data4 == 0 || data4 instanceof Float && (Float) data4 == 0f) { //Capacity_data_4,如果设定落布米数为0,则证明当前数据无效 //不能跟上面判断合并,不然报空指针 continue; } //停机统计--start IndexAlarm stopCalc = new IndexAlarm(); stopCalc.setCode(device.getDeviceCode()); stopCalc.setName(device.getDeviceName()); int alarmType = 0; if (speed > 0f || stopStatus == 0) { onlineNum++; } else { switch (stopStatus) { case 1: stop1++; alarmType = 10001; break; case 2: stop2++; alarmType = 10002; break; case 6: stop6++; alarmType = 10006; break; case 7: //7-盘头剩余圈数达到停机,表示停机叫料 stop8++; alarmType = 10008; break; default: otherStop++; } } if (alarmType != 0) { stopCalc.setType(alarmType); alarmList.add(stopCalc); } //停机统计--end IndexPan pan = new IndexPan(); pan.setCode(device.getDeviceCode()); pan.setName(device.getDeviceName()); //处理配方明细数据 FormulaDetail detail = new FormulaDetail(isSmall, map); formulaDetail.add(detail); //处理平方米克重明细数据 GramMassDetail gramMassDetail = new GramMassDetail(isSmall, map); gramMassDetails.add(gramMassDetail); //处理送经量数据 WarpRunIn warpRunIn = new WarpRunIn(isSmall, map); warpList.add(warpRunIn); //盘头小于200圈的统计--start int len = 5; if (!isSmall) { len = 10; } boolean panFlag = false; for (int i = 0; i < len; i++) { int pos = 15 + i; int v = (int) map.get("Capacity_data_" + pos); if (v < 200) { //盘头小于200圈 panFlag = true; break; } } if (panFlag) { stopPan++; } //盘头小于200圈的统计--end if (isSmall) { for (int i = 0; i < Tools.ALLOW_ALARM.length; i++) { //允许的告警编号 boolean flag = (boolean) map.get("Alarm_unit_" + Tools.ALLOW_ALARM[i]); if (flag) { IndexAlarm indexAlarm = new IndexAlarm(); indexAlarm.setCode(device.getDeviceCode()); indexAlarm.setName(device.getDeviceName()); indexAlarm.setType(i); alarmList.add(indexAlarm); } } } } } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); } indexData.setAlarm(alarmList); IndexDevice device = new IndexDevice(); device.setTotal(list.size()); device.setOnline(onlineNum); device.setStop1(stop1); device.setStop2(stop2); device.setStop6(stop6); device.setStop8(stop8); device.setStopPan(stopPan); // 2024-11-18 告警数改为其他停机数 // device.setAlarm(alarmList.size()); device.setAlarm(otherStop); BigDecimal ratio = BigDecimal.valueOf(onlineNum * 100L).divide(BigDecimal.valueOf(list.size()), 2, RoundingMode.HALF_UP); device.setRunningRatio(ratio.doubleValue()); indexData.setDevice(device); Map temp = formulaDetail.stream().collect(Collectors.groupingBy(FormulaDetail::getFormula_data_15, Collectors.counting())); for (Float v : temp.keySet()) { FormulaTotal total = new FormulaTotal(); total.setHeight(v); int num = Math.toIntExact(temp.get(v)); total.setNum(num); float percent = BigDecimal.valueOf(num).divide(BigDecimal.valueOf(list.size()), 2, RoundingMode.HALF_UP).floatValue(); total.setPercent(percent); formulaTotal.add(total); } temp = gramMassDetails.stream().collect(Collectors.groupingBy(GramMassDetail::getGramMass, Collectors.counting())); for (Float v : temp.keySet()) { GramMass total = new GramMass(); total.setGramMass(v); int num = Math.toIntExact(temp.get(v)); total.setNum(num); float percent = BigDecimal.valueOf(num).divide(BigDecimal.valueOf(list.size()), 2, RoundingMode.HALF_UP).floatValue(); total.setPercent(percent); gramMasses.add(total); } redisCache.setCacheObject(CacheConstants.DEVICE_CURRENT, currMap); redisCache.setCacheObject(CacheConstants.INDEX_ALARM, indexData); redisCache.setCacheObject(CacheConstants.INDEX_FORMULA_TOTAL, formulaTotal); redisCache.setCacheObject(CacheConstants.INDEX_FORMULA_DETAIL, formulaDetail); redisCache.setCacheObject(CacheConstants.INDEX_WARP_RUN_IN, warpList); redisCache.setCacheObject(CacheConstants.INDEX_GRAM_MASS, gramMasses); redisCache.setCacheObject(CacheConstants.INDEX_GRAM_MASS_DETAIL, gramMassDetails); redisCache.setCacheObject(CacheConstants.STOP_DETAIL, stopList); calcLength(); } /** * 统计产量数据 */ private void calcLength() { IndexData indexData = redisCache.getCacheObject(CacheConstants.INDEX_CALC); IndexEfficiency efficiency = indexData.getEfficiency(); TwinCalcDay calcDay = twinCalcDayService.calcLength(); efficiency.setTotalLength(calcDay.getLength().floatValue()); efficiency.setALength(calcDay.getLengthA().floatValue()); efficiency.setBLength(calcDay.getLengthB().floatValue()); //界面上重新计算重量 2024-12-25 用总长度除以373 BigDecimal tw = calcDay.getLength().divide(BigDecimal.valueOf(373), 2, BigDecimal.ROUND_HALF_UP); BigDecimal aw = calcDay.getLengthA().divide(BigDecimal.valueOf(373), 2, BigDecimal.ROUND_HALF_UP); BigDecimal bw = calcDay.getLengthB().divide(BigDecimal.valueOf(373), 2, BigDecimal.ROUND_HALF_UP); efficiency.setTotalWeight(tw.floatValue()); efficiency.setAWeight(aw.floatValue()); efficiency.setBWeight(bw.floatValue()); redisCache.setCacheObject(CacheConstants.INDEX_CALC, indexData); } }