package com.tmzn.devicelinkykc.taskQueue.runner; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.tmzn.devicelinkykc.constant.Constant; import com.tmzn.devicelinkykc.constant.DeviceOnlineStatus; import com.tmzn.devicelinkykc.constant.RedisConstant; import com.tmzn.devicelinkykc.constant.ykc.StatusConstant; import com.tmzn.devicelinkykc.constant.ykc.TransConstant; import com.tmzn.devicelinkykc.entity.BillingModel; import com.tmzn.devicelinkykc.entity.Device; import com.tmzn.devicelinkykc.entity.DeviceStatus; import com.tmzn.devicelinkykc.entity.OrderStatus; import com.tmzn.devicelinkykc.frameMsg.TransMoney; import com.tmzn.devicelinkykc.frameMsg.frameType.HeartFrameSend; import com.tmzn.devicelinkykc.frameMsg.frameType.LoginFrame; import com.tmzn.devicelinkykc.frameMsg.frameType.RealTimeStatusPushFrame; import com.tmzn.devicelinkykc.frameMsg.frameType.TransactionFlowPushFrame; import com.tmzn.devicelinkykc.message.DeviceMsgHandle; import com.tmzn.devicelinkykc.redis.RedisCache; import com.tmzn.devicelinkykc.service.*; import com.tmzn.devicelinkykc.socket.DeviceConnectionMsg; import com.tmzn.devicelinkykc.socket.SocketHandle; import com.tmzn.devicelinkykc.transdata.entity.DeviceParam; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import java.math.BigDecimal; import java.time.Instant; import java.time.ZoneId; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Component @Slf4j(topic = "MsgChargingRunner") public class MsgCharngingRunner { @Autowired private DeviceService deviceService; @Autowired private LoginFrame loginFrame; @Autowired private RedisCache redisCache; @Autowired private RealTimeStatusPushFrame realTimeStatusPushFrame; @Autowired private OrderStatusService orderStatusService; @Autowired private BillingModelService billingModelService; @Autowired private TransMoney transMoney; @Autowired private DeviceStatusService deviceStatusService; @Autowired private SocketHandle socketHandle; @Autowired DeviceMsgHandle deviceMsgHandle; @Autowired private DeviceControlerService deviceControlerService; @Autowired private TransactionFlowPushFrame transactionFlowPushFrame; private static final BigDecimal zero = new BigDecimal("0"); @Async("charngingTaskAsyncPool") public void chargingMsg(Map map) { log.info("======充电中数据上报检测====="); //这边需要给充电中的状态进行查询流水号,流水号是由云快充启动充电时的下发指令带来存库的, if (map.size() < 1) { return; } //查找所有充电中的订单 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("now_order_status", 0); //充电中状态上报 //忽略10天前的订单 long nowTime = System.currentTimeMillis(); long tm = nowTime-86400*10*1000; //10天前的就算了 queryWrapper.gt("create_time",tm ); //充电中状态上报 queryWrapper.orderByDesc("id"); //查询所有充电中设备的最新的订单记录,来上报设备状态消息.........????????????????? List list = orderStatusService.list(queryWrapper); if (list.isEmpty()) { log.info("无充电中订单上报"); return; } // Set devicePileCodes = map.keySet(); // QueryWrapper billWapper = new QueryWrapper<>(); // billWapper.in("pile_code", devicePileCodes); // List billingModels = billingModelService.list(billWapper); // if (billingModels.size() < 1) { // log.info("无计费可上报模型"); // return; // } // Map billingModelMap = billingModels.stream() // .collect(Collectors.toMap(BillingModel::getPileCode, billingModel -> billingModel)); //只上传最近的订单 Map dealMap = new HashMap<>(); list.forEach(item -> { try { //检查设备是否在线 QueryWrapper deviceStatusQueryWrapper = new QueryWrapper<>(); deviceStatusQueryWrapper.eq("pile_code", item.getPileCode()); deviceStatusQueryWrapper.eq("gun_port", item.getGunsCode()); // deviceStatusQueryWrapper.last("limit 1"); DeviceStatus statusServiceOne = deviceStatusService.getOne(deviceStatusQueryWrapper); if(statusServiceOne != null && statusServiceOne.getOnlineStatus()==StatusConstant.OFFLINE){ log.info("{}设备已离线不上报",item.getPileCode()); return; } QueryWrapper billWapper = new QueryWrapper<>(); billWapper.eq("pile_code", item.getPileCode()); billWapper.eq("device_imei", item.getDeviceImei()); BillingModel b = billingModelService.getOne(billWapper); if (b == null) { log.info("{}上报充电中未匹配计费模型", item.getPileCode()); return; } if(!deviceMsgHandle.checkConnection(item.getPileCode(),item.getDeviceImei())){ log.info("{}重新连接句柄不存在等待下次执行",item.getPileCode()); return; } DeviceConnectionMsg deviceConnectionMsg = map.get(item.getPileCode()); String k = item.getPileCode() + "_" + item.getGunsCode(); if (dealMap.containsKey(k)) { log.info("{}本轮已上报充电中只报最后一个订单", k); } else { reportOne(item, b, deviceConnectionMsg); dealMap.put(k, true); } } catch (Exception e) { log.info("{}上报充电中异常", item.getPileCode()+e.getMessage()); e.printStackTrace(); } }); log.info("======Charging status push task ending====="); } //尝试下发103 避免下发太频繁 public void try103(OrderStatus orderStatus){ String key = "try103_charging:_"+orderStatus.getDeviceImei()+"_"+orderStatus.getGunsCode(); if(redisCache.hasKey(key)){ log.info("{}-{}忽略103", orderStatus.getPileCode(), orderStatus.getGunsCode()); return; } log.info("{}-{}-5分钟内无状态103", orderStatus.getPileCode(), orderStatus.getGunsCode()); deviceControlerService.sendImeiDetail(orderStatus.getDeviceImei()); int timeout = 60; //订单3分钟内一分钟请求一次103 否则就1分钟半获取一次 if((System.currentTimeMillis()-orderStatus.getCreateTime())<180*1000){ timeout = 60; } redisCache.setCacheObject(key, System.currentTimeMillis(),timeout, TimeUnit.SECONDS); } //停止一个订单 public void stopOneOrder(OrderStatus orderStatus){ log.info("{}--id:{}设置订单关闭",orderStatus.getPileCode(),orderStatus.getId()); int port = (int) orderStatus.getGunsCode(); orderStatus.setEndTime(System.currentTimeMillis() - 1000 * 60 * 2); orderStatus.setNowOrderStatus(StatusConstant.NOW_ORDER_STATUS_CHARGING_ENDING); orderStatusService.updateById(orderStatus); deviceControlerService.stopCharge(orderStatus.getDeviceImei(), orderStatus.getDeviceImei(), port); } public void reportOne(OrderStatus orderStatus, BillingModel billingModel, DeviceConnectionMsg deviceConnectionMsg) { try103(orderStatus); //获取订单状态 String cacheKey = orderStatus.getGunsCode() == 1 ? RedisConstant.ONLINE_DEVICE_ONE : RedisConstant.ONLINE_DEVICE_TWO; DeviceStatus deviceStatus = redisCache.getCacheMapValue(cacheKey, orderStatus.getPileCode()); //每次下发一次103 long t = System.currentTimeMillis()-orderStatus.getCreateTime(); int port = (int) orderStatus.getGunsCode(); if(deviceStatus==null){ if(t<10*60*1000){ return; }else{ log.info("{}-{}无10分钟还没有记录要停止充电", orderStatus.getPileCode(), orderStatus.getGunsCode()); orderStatus.setReasonStopCharging(TransConstant.OTHER_STOP); stopOneOrder(orderStatus); } return; } if(deviceStatus.getGunStatus() != StatusConstant.CHARGING){ if(t<5*60*1000){ log.info("{}-{}-5分钟内还未变充电状态忽略", orderStatus.getPileCode(), orderStatus.getGunsCode()); return; }else{ log.info("{}-{}-5分钟后还不是充电状态录要停止充电", orderStatus.getPileCode(), orderStatus.getGunsCode()); //状态那我为 orderStatus.setReasonStopCharging(TransConstant.OTHER_STOP); stopOneOrder(orderStatus); return; } } //上送充电状态 JSONObject statusJSON = redisCache.getCacheObject(RedisConstant.DEVICE_PORT_STATUS + deviceStatus.getDeviceImei()); if(statusJSON==null){ log.info("无最近103数据{}",orderStatus.getPileCode()); try103(orderStatus); return; } Integer voltage; Integer power; if(port==1){ voltage = statusJSON.getInteger("voltage"); }else{ voltage = statusJSON.getInteger("voltage_1"); if(voltage==null){ voltage = statusJSON.getInteger("voltage"); } } if(port == 1){ power = statusJSON.getInteger("power"); }else{ power = statusJSON.getInteger("power_1"); } if(power==null){ power = 0; } if(voltage==null){ voltage = 0; } //计算实时数据 long endTime = System.currentTimeMillis(); //算电量 Map start; String transCacheKey = "ChargingTrans:"+orderStatus.getId(); if(redisCache.hasKey(transCacheKey)){ Map cached = redisCache.getCacheObject(transCacheKey); start = new HashMap<>(cached); }else{ //缓存120秒避免重复计算电量 try { start = transMoney.compute(port, billingModel, orderStatus.getCreateTime(), endTime,orderStatus); } catch (Exception e) { e.printStackTrace(); log.error("计算订单异常{},{}",orderStatus.getPileCode(),e.getMessage()); return; } redisCache.setCacheObject(transCacheKey, start, 90, TimeUnit.SECONDS); } BigDecimal elec = start.get("elec"); BigDecimal money = start.get("money"); if (elec.equals(new BigDecimal("0.0000"))) { elec = elec.add(new BigDecimal("0.0001").setScale(4, BigDecimal.ROUND_DOWN)); } log.info("{}-{}-{}充电中=>实时elec:{}>>>实时金额>>>{}=>p:{},v:{}" ,orderStatus.getPileCode(),port,elec,orderStatus.getGunsCode(),money,power,voltage); //???????????????????????????? if (money.compareTo(orderStatus.getStartMoney()) > 0) { //余额没有了,停充 orderStatus.setReasonStopCharging(TransConstant.INSUFFICIENT_BALANCE_EXCEPTION_STOP); stopOneOrder(orderStatus); log.info("{},{},{}实时状态校验时余额不足{}>>>>>>停充>>>>",orderStatus.getPileCode(),orderStatus.getGunsCode(),orderStatus.getTransOrder(),money); return; } if(orderStatus.getStartMoney().subtract(money).compareTo(new BigDecimal("0.50")) < 0) { orderStatus.setReasonStopCharging(TransConstant.INSUFFICIENT_BALANCE_EXCEPTION_STOP); stopOneOrder(orderStatus); log.info("{},{},{}实时状态校验时余额不足1{}>>>>>>停充>>>>",orderStatus.getPileCode(),orderStatus.getGunsCode(),orderStatus.getTransOrder(),money); return; } int mi = (int) (System.currentTimeMillis() - orderStatus.getCreateTime()) / 1000 / 60; realTimeStatusPushFrame.deviceStatusPush(deviceConnectionMsg, orderStatus.getTransOrder(), deviceStatus.getPileCode(), deviceStatus.getGunPort(), deviceStatus.getGunStatus(), deviceStatus.getInsertGunStatus(), voltage, power, elec, money, mi); log.info("↑↑↑{},{},{}充电中实时状态上报 ",orderStatus.getPileCode(),orderStatus.getGunsCode(),orderStatus.getId()); } }