| | |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.text.DecimalFormat; |
| | | import java.time.LocalDateTime; |
| | | import java.time.ZoneId; |
| | | import java.util.*; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.concurrent.locks.ReentrantLock; |
| | |
| | | @Transactional |
| | | public Result<?> realTimeDataHandle(RealTimeDataVo realTimeDataVo) { |
| | | TenantContext.setTenant(realTimeDataVo.getTenantid() + ""); |
| | | log.info("实时数据:" + realTimeDataVo.toString()); |
| | | // log.info("实时数据:" + realTimeDataVo.toString()); |
| | | |
| | | |
| | | // 1 查询或创建工单 |
| | |
| | | @Transactional |
| | | public Result<?> realTimeDataHandle(RealTimeDataParentVo realTimeDataParentVo) { |
| | | TenantContext.setTenant(realTimeDataParentVo.getTenantid() + ""); |
| | | log.info("实时数据:" + realTimeDataParentVo.toString()); |
| | | // log.info("实时数据:" + realTimeDataParentVo.toString()); |
| | | if (realTimeDataParentVo.getRealTime() != null) { |
| | | RealTimeDataVo realTimeDataVo = realTimeDataParentVo.getRealTime(); |
| | | |
| | |
| | | DryOrderVo orderVo = (DryOrderVo) redisUtil.hget(CacheConstants.RedisKeyEnum.WORK_ORDER.getCode(), |
| | | realTimeDataParentVo.getTenantid() + "_" + realTimeDataParentVo.getMachineid()); |
| | | // 1.2 如果有缓存记录 |
| | | if (orderVo != null && orderVo.getCode().equals(realTimeDataParentVo.getWorkorder())) { |
| | | if (orderVo != null && orderVo.getCode() != null && orderVo.getCode().equals(realTimeDataParentVo.getWorkorder())) { |
| | | |
| | | // 1.3 没有缓存记录再查询数据库 |
| | | } else { |
| | | // 根据租户id和工单号查询数据库是否有记录,有则返回,没有则新增一条再返回 |
| | | realTimeDataVo.setWorkorder(realTimeDataParentVo.getWorkorder()); |
| | | orderVo = getOrSaveDryOrderVoDB(realTimeDataVo); |
| | | } |
| | | if (orderVo == null) { |
| | |
| | | orderVo.setOrderStatus(realTimeDataVo.getWorkorder_status()); |
| | | orderVo.setEqp_status(realTimeDataVo.getEqp_status()); |
| | | // orderVo.setEqp_state(realTimeDataVo.getEqp_state()); |
| | | orderVo.setWarning(realTimeDataVo.getEqp_warning()); |
| | | orderVo.setFault(realTimeDataVo.getEqp_fault()); |
| | | if(realTimeDataParentVo.getFault()!=null && StringUtils.isNotEmpty(realTimeDataParentVo.getFault().getWarning())){ |
| | | orderVo.setWarning(realTimeDataParentVo.getFault().getWarning()); |
| | | } |
| | | if(realTimeDataParentVo.getFault()!=null && StringUtils.isNotEmpty(realTimeDataParentVo.getFault().getError())){ |
| | | orderVo.setFault(realTimeDataParentVo.getFault().getError()); |
| | | } |
| | | orderVo.setLevel(realTimeDataVo.getLevel()); |
| | | DryOrderTrendVo trendVo = new DryOrderTrendVo(realTimeDataVo); |
| | | // 2.2 保存工单含水率变化 或 重量变化 |
| | |
| | | saveOrderTrendVo(trendVo, orderVo); |
| | | orderVo.setTrendVo(trendVo); |
| | | orderVo.getBellowsTemp().put(realTimeDataVo.getTime3(), realTimeDataVo.getTemp2()); |
| | | |
| | | if (realTimeDataParentVo.getFault() != null) { |
| | | if (realTimeDataParentVo.getFault().getError() != null) { |
| | | orderVo.setFault(realTimeDataParentVo.getFault().getError()); |
| | | } |
| | | if (realTimeDataParentVo.getFault().getWarning() != null) { |
| | | orderVo.setWarning(realTimeDataParentVo.getFault().getWarning()); |
| | | } |
| | | } |
| | | |
| | | // 2.3 更新到redis缓存 |
| | | redisUtil.hset(CacheConstants.RedisKeyEnum.WORK_ORDER.getCode(), |
| | |
| | | log.error("新增设备失败:数据库保存异常!equipment={}", addEqu); |
| | | return null; |
| | | } |
| | | redisUtil.del(CommonCacheConstant.DRY_CACHE_TENANT_EQUS_LIST); |
| | | redisUtil.del(CommonCacheConstant.DRY_CACHE_TENANT_EQUS); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | |
| | | ReentrantLock orderLock = getLock(realTimeDataVo.getTenantid() + "", "order"); |
| | | orderLock.lock(); |
| | | try { |
| | | //根据租户id 和 药材id 检查最近是否存在工单 TODO 验证 |
| | | LambdaQueryWrapper<DryOrder> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.eq(DryOrder::getHerbId, herbFormula.getId()); |
| | | queryWrapper.eq(DryOrder::getTenantId, realTimeDataVo.getTenantid()); |
| | | queryWrapper.orderByDesc(DryOrder::getOrderTime); |
| | | queryWrapper.last("LIMIT 1"); |
| | | // 1 查询数据库 |
| | | DryOrder one = dryOrderService.getOne(queryWrapper); |
| | | if(one!=null){ |
| | | Date orderDate = one.getOrderTime(); |
| | | //30S内不允许新建工单,避免重复 |
| | | LocalDateTime orderTime = orderDate.toInstant() |
| | | .atZone(ZoneId.systemDefault()) |
| | | .toLocalDateTime(); |
| | | |
| | | LocalDateTime now = LocalDateTime.now(); |
| | | long secondsBetween = java.time.Duration.between(orderTime, now).getSeconds(); |
| | | boolean b = secondsBetween <= 30; |
| | | if(b){ |
| | | return BeanUtil.toBean(one, DryOrderVo.class); |
| | | } |
| | | } |
| | | |
| | | // 创建新工单 |
| | | orderVo = new DryOrderVo(realTimeDataVo); |
| | | orderVo.setHerbId(herbFormula.getId()); |
| | |
| | | LambdaQueryWrapper<DryHerbFormula> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.eq(DryHerbFormula::getTenantId, realTimeDataVo.getTenantid()); |
| | | queryWrapper.eq(DryHerbFormula::getName, realTimeDataVo.getName()); |
| | | queryWrapper.orderByDesc(DryHerbFormula::getCreateTime); |
| | | queryWrapper.last("LIMIT 1"); |
| | | DryHerbFormula one = dryHerbFormulaService.getOne(queryWrapper); |
| | | if (one == null) { |
| | | one = new DryHerbFormula(realTimeDataVo); |
| | | DryEquipment dryEquipment = equipmentService.selectByTenantIdEquipmentId(realTimeDataVo.getTenantid() + "", realTimeDataVo.getMachineid()); |
| | | if (dryEquipment != null && dryEquipment.getType() != null) { |
| | | one.setEqpType(dryEquipment.getType()); |
| | | } |
| | | |
| | | dryHerbFormulaService.save(one); |
| | | } |
| | | // if (one == null) { |
| | | // one = new DryHerbFormula(realTimeDataVo); |
| | | // DryEquipment dryEquipment = equipmentService.selectByTenantIdEquipmentId(realTimeDataVo.getTenantid() + "", realTimeDataVo.getMachineid()); |
| | | // if (dryEquipment != null && dryEquipment.getType() != null) { |
| | | // one.setEqpType(dryEquipment.getType()); |
| | | // } |
| | | // |
| | | // dryHerbFormulaService.save(one); |
| | | // } |
| | | return one; |
| | | } |
| | | |
| | |
| | | // 获取工单 |
| | | DryOrderVo order = (DryOrderVo) redisUtil.hget(CacheConstants.RedisKeyEnum.WORK_ORDER.getCode(), realTimeDataVo.getTenantid() + "_" + item.getCode()); |
| | | list.add(item.getName().substring(0, item.getName().indexOf('#') + 1)); |
| | | if (order != null) { |
| | | if (order != null && order.getDetailList()!=null && !order.getDetailList().isEmpty()) { |
| | | // 计算干燥效率,用于对比 |
| | | DryOrderTrendVo dryOrderTrendVo = order.getDetailList().get(order.getDetailList().size() - 1); |
| | | double v = order.getOriginWeight() - dryOrderTrendVo.getWeight(); |
| | |
| | | if (order != null) { |
| | | orderVo.setEnvHum(order.getEnvHum()); |
| | | orderVo.setEnvTemp(order.getEnvTemp()); |
| | | double watt = order.getWatt() - order.getDetailList().get(0).getWatt(); |
| | | double watt = order.getWatt() - (order.getDetailList().size() > 0 ?order.getDetailList().get(0).getWatt():0); |
| | | orderVo.setWatt(orderVo.getWatt() == null ? watt : orderVo.getWatt() + watt); |
| | | double steam = order.getSteam() - order.getDetailList().get(0).getSteam(); |
| | | double steam = order.getSteam() - ( order.getDetailList().size() > 0 ?order.getDetailList().get(0).getSteam():0); |
| | | orderVo.setSteam(orderVo.getSteam() == null ? steam : orderVo.getSteam() + steam); |
| | | orderVo.setOriginWeight(orderVo.getOriginWeight() == null ? order.getOriginWeight() : orderVo.getOriginWeight() + order.getOriginWeight()); |
| | | |
| | |
| | | List<DryFaultRecordVo> faultList = new ArrayList<DryFaultRecordVo>((dryFaultMap.values())); |
| | | MqMessage<List<DryFaultRecordVo>> mqMessage = new MqMessage<>(faultList, tenantId, recTopic); |
| | | //发送广播 |
| | | log.error("广播给:{}", recTopic); |
| | | // log.error("广播给:{}", recTopic); |
| | | mqttUtil.sendMqttMessage(MqttConstant.SERVICE_BROADCAST_TENANT_REAL_FAULT, mqMessage, 1); |
| | | |
| | | |
| | |
| | | List<DryFaultRecord> result = new ArrayList<>(); |
| | | if (StringUtils.isEmpty(fault)) return result; |
| | | //数据样本:"eqp_fault": "滚筒降超时-报警,风机过流报警,滚筒升超时-报警,风箱升报警", |
| | | System.err.println((faultType == 1 ? "类型:故障" : "类型:报警") + DateUtils.formatDateTime() + "--" + fault); |
| | | // System.err.println((faultType == 1 ? "类型:故障" : "类型:报警") + DateUtils.formatDateTime() + "--" + fault); |
| | | //redis中的故障 |
| | | Map<Object, Object> rFauMap = redisUtil.hmget(String.format(MqttConstant.MQTT_REAL_FAULT, tenantId)); |
| | | Map<String, Object> redFauMap = rFauMap.entrySet().stream() |
| | |
| | | //2检测已结束的故障 |
| | | //2.1如果实时数据不存在redis存在则代表故障结束,存入数据库 |
| | | Map<Object, Object> curFauMap = redisUtil.hmget(String.format(MqttConstant.MQTT_REAL_FAULT, tenantId)); |
| | | curFauMap.keySet().stream() |
| | | Map<Object, DryFaultRecordVo> collect = curFauMap.keySet().stream() |
| | | .filter(key -> { |
| | | String[] split = key.toString().split("_"); |
| | | return split[0].equals(tenantId + "") && split[1].equals(machineId); |
| | | }) |
| | | //特别注意,多个报警类型共用方法需要区分类型 |
| | | .filter(key -> !realFauMap.containsKey(key) && ((DryFaultRecordVo) curFauMap.get(key)).getFaultType() == faultType) |
| | | .forEach(key -> { |
| | | DryFaultRecordVo vo = (DryFaultRecordVo) redFauMap.get(key); |
| | | vo.setECount(vo.getECount() + 1); |
| | | if (redisUtil.hget(String.format(MqttConstant.MQTT_REAL_FAULT, tenantId), key.toString()) != null) { |
| | | //更新次数 |
| | | redisUtil.hset(String.format(MqttConstant.MQTT_REAL_FAULT, tenantId), key.toString(), vo); |
| | | System.err.println("报警次数更新,key-" + key); |
| | | } |
| | | .filter(key -> !realFauMap.containsKey(key) && (Objects.equals(((DryFaultRecordVo) curFauMap.get(key)).getFaultType(), faultType))) |
| | | .collect(Collectors.toMap(key -> key, // 保留原键 |
| | | key -> (DryFaultRecordVo) curFauMap.get(key))); |
| | | collect.keySet().forEach(key -> { |
| | | DryFaultRecordVo vo = (DryFaultRecordVo) redFauMap.get(key); |
| | | vo.setECount(vo.getECount() + 1); |
| | | if (redisUtil.hget(String.format(MqttConstant.MQTT_REAL_FAULT, tenantId), key.toString()) != null) { |
| | | //更新次数 |
| | | redisUtil.hset(String.format(MqttConstant.MQTT_REAL_FAULT, tenantId), key.toString(), vo); |
| | | System.err.println("报警次数更新,key-" + key); |
| | | } |
| | | |
| | | if (vo.getECount() >= 3) { |
| | | vo.setEndTime(new Date()); |
| | | //TODO 结束超过某个时间区间判定为错误数据 |
| | | faultRecordService.save(vo); |
| | | redisUtil.hdel(String.format(MqttConstant.MQTT_REAL_FAULT, tenantId), key); |
| | | result.add(vo); |
| | | System.err.println((faultType == 1 ? "类型:故障" : "类型:报警") + DateUtils.formatDateTime() + "存入数据库"); |
| | | } |
| | | }); |
| | | if (vo.getECount() >= 3) { |
| | | vo.setEndTime(new Date()); |
| | | //TODO 结束超过某个时间区间判定为错误数据 |
| | | faultRecordService.save(vo); |
| | | redisUtil.hdel(String.format(MqttConstant.MQTT_REAL_FAULT, tenantId), key); |
| | | result.add(vo); |
| | | // System.err.println((faultType == 1 ? "类型:故障" : "类型:报警") + DateUtils.formatDateTime() + "存入数据库"); |
| | | } |
| | | }); |
| | | |
| | | |
| | | return result; |