MsgCharngingRunner.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. package com.tmzn.devicelinkykc.taskQueue.runner;
  2. import com.alibaba.fastjson2.JSONObject;
  3. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  4. import com.tmzn.devicelinkykc.constant.Constant;
  5. import com.tmzn.devicelinkykc.constant.DeviceOnlineStatus;
  6. import com.tmzn.devicelinkykc.constant.RedisConstant;
  7. import com.tmzn.devicelinkykc.constant.ykc.StatusConstant;
  8. import com.tmzn.devicelinkykc.constant.ykc.TransConstant;
  9. import com.tmzn.devicelinkykc.entity.BillingModel;
  10. import com.tmzn.devicelinkykc.entity.Device;
  11. import com.tmzn.devicelinkykc.entity.DeviceStatus;
  12. import com.tmzn.devicelinkykc.entity.OrderStatus;
  13. import com.tmzn.devicelinkykc.frameMsg.TransMoney;
  14. import com.tmzn.devicelinkykc.frameMsg.frameType.HeartFrameSend;
  15. import com.tmzn.devicelinkykc.frameMsg.frameType.LoginFrame;
  16. import com.tmzn.devicelinkykc.frameMsg.frameType.RealTimeStatusPushFrame;
  17. import com.tmzn.devicelinkykc.frameMsg.frameType.TransactionFlowPushFrame;
  18. import com.tmzn.devicelinkykc.message.DeviceMsgHandle;
  19. import com.tmzn.devicelinkykc.redis.RedisCache;
  20. import com.tmzn.devicelinkykc.service.*;
  21. import com.tmzn.devicelinkykc.socket.DeviceConnectionMsg;
  22. import com.tmzn.devicelinkykc.socket.SocketHandle;
  23. import com.tmzn.devicelinkykc.transdata.entity.DeviceParam;
  24. import lombok.extern.slf4j.Slf4j;
  25. import org.springframework.beans.factory.annotation.Autowired;
  26. import org.springframework.scheduling.annotation.Async;
  27. import org.springframework.stereotype.Component;
  28. import java.math.BigDecimal;
  29. import java.time.Instant;
  30. import java.time.ZoneId;
  31. import java.util.HashMap;
  32. import java.util.List;
  33. import java.util.Map;
  34. import java.util.Set;
  35. import java.util.concurrent.TimeUnit;
  36. import java.util.stream.Collectors;
  37. @Component
  38. @Slf4j(topic = "MsgChargingRunner")
  39. public class MsgCharngingRunner {
  40. @Autowired
  41. private DeviceService deviceService;
  42. @Autowired
  43. private LoginFrame loginFrame;
  44. @Autowired
  45. private RedisCache redisCache;
  46. @Autowired
  47. private RealTimeStatusPushFrame realTimeStatusPushFrame;
  48. @Autowired
  49. private OrderStatusService orderStatusService;
  50. @Autowired
  51. private BillingModelService billingModelService;
  52. @Autowired
  53. private TransMoney transMoney;
  54. @Autowired
  55. private DeviceStatusService deviceStatusService;
  56. @Autowired
  57. private SocketHandle socketHandle;
  58. @Autowired
  59. DeviceMsgHandle deviceMsgHandle;
  60. @Autowired
  61. private DeviceControlerService deviceControlerService;
  62. @Autowired
  63. private TransactionFlowPushFrame transactionFlowPushFrame;
  64. private static final BigDecimal zero = new BigDecimal("0");
  65. @Async("charngingTaskAsyncPool")
  66. public void chargingMsg(Map<String, DeviceConnectionMsg> map) {
  67. log.info("======充电中数据上报检测=====");
  68. //这边需要给充电中的状态进行查询流水号,流水号是由云快充启动充电时的下发指令带来存库的,
  69. if (map.size() < 1) {
  70. return;
  71. }
  72. //查找所有充电中的订单
  73. QueryWrapper<OrderStatus> queryWrapper = new QueryWrapper<>();
  74. queryWrapper.eq("now_order_status", 0); //充电中状态上报
  75. //忽略10天前的订单
  76. long nowTime = System.currentTimeMillis();
  77. long tm = nowTime-86400*10*1000;
  78. //10天前的就算了
  79. queryWrapper.gt("create_time",tm ); //充电中状态上报
  80. queryWrapper.orderByDesc("id");
  81. //查询所有充电中设备的最新的订单记录,来上报设备状态消息.........?????????????????
  82. List<OrderStatus> list = orderStatusService.list(queryWrapper);
  83. if (list.isEmpty()) {
  84. log.info("无充电中订单上报");
  85. return;
  86. }
  87. Set<String> devicePileCodes = map.keySet();
  88. QueryWrapper<BillingModel> billWapper = new QueryWrapper<>();
  89. billWapper.in("pile_code", devicePileCodes);
  90. List<BillingModel> billingModels = billingModelService.list(billWapper);
  91. if (billingModels.size() < 1) {
  92. log.info("无计费可上报模型");
  93. return;
  94. }
  95. Map<String, BillingModel> billingModelMap = billingModels.stream()
  96. .collect(Collectors.toMap(BillingModel::getPileCode, billingModel -> billingModel));
  97. //只上传最近的订单
  98. Map<String, Boolean> dealMap = new HashMap<>();
  99. list.forEach(item -> {
  100. try {
  101. if(!deviceMsgHandle.checkConnection(item.getPileCode(),item.getDeviceImei())){
  102. log.info("{}重新连接句柄不存在等待下次执行",item.getPileCode());
  103. return;
  104. }
  105. DeviceConnectionMsg deviceConnectionMsg = map.get(item.getPileCode());
  106. BillingModel b = billingModelMap.get(item.getPileCode());
  107. if (b == null) {
  108. log.info("{}上报充电中未匹配计费模型", item.getPileCode());
  109. return;
  110. }
  111. String k = item.getPileCode() + "_" + item.getGunsCode();
  112. if (dealMap.containsKey(k)) {
  113. log.info("{}本轮已上报充电中只报最后一个订单", k);
  114. } else {
  115. reportOne(item, b, deviceConnectionMsg);
  116. dealMap.put(k, true);
  117. }
  118. } catch (Exception e) {
  119. log.info("{}上报充电中异常", item.getPileCode()+e.getMessage());
  120. e.printStackTrace();
  121. }
  122. });
  123. log.info("======Charging status push task ending=====");
  124. }
  125. //尝试下发103 避免下发太频繁
  126. public void try103(OrderStatus orderStatus){
  127. String key = "try103_charging:_"+orderStatus.getDeviceImei()+"_"+orderStatus.getGunsCode();
  128. if(redisCache.hasKey(key)){
  129. log.info("{}-{}忽略103", orderStatus.getPileCode(), orderStatus.getGunsCode());
  130. return;
  131. }
  132. log.info("{}-{}-5分钟内无状态103", orderStatus.getPileCode(), orderStatus.getGunsCode());
  133. deviceControlerService.sendImeiDetail(orderStatus.getDeviceImei());
  134. int timeout = 60;
  135. //订单3分钟内一分钟请求一次103 否则就1分钟半获取一次
  136. if((System.currentTimeMillis()-orderStatus.getCreateTime())<180*1000){
  137. timeout = 60;
  138. }
  139. redisCache.setCacheObject(key, System.currentTimeMillis(),timeout, TimeUnit.SECONDS);
  140. }
  141. //停止一个订单
  142. public void stopOneOrder(OrderStatus orderStatus){
  143. log.info("{}--id:{}设置订单关闭",orderStatus.getPileCode(),orderStatus.getId());
  144. int port = (int) orderStatus.getGunsCode();
  145. orderStatus.setEndTime(System.currentTimeMillis() - 1000 * 60 * 2);
  146. orderStatus.setNowOrderStatus(StatusConstant.NOW_ORDER_STATUS_CHARGING_ENDING);
  147. orderStatusService.updateById(orderStatus);
  148. deviceControlerService.stopCharge(orderStatus.getDeviceImei(), orderStatus.getDeviceImei(), port);
  149. }
  150. public void reportOne(OrderStatus orderStatus, BillingModel billingModel, DeviceConnectionMsg deviceConnectionMsg) {
  151. try103(orderStatus);
  152. //获取订单状态
  153. String cacheKey = orderStatus.getGunsCode() == 1 ? RedisConstant.ONLINE_DEVICE_ONE : RedisConstant.ONLINE_DEVICE_TWO;
  154. DeviceStatus deviceStatus = redisCache.getCacheMapValue(cacheKey, orderStatus.getPileCode());
  155. //每次下发一次103
  156. long t = System.currentTimeMillis()-orderStatus.getCreateTime();
  157. int port = (int) orderStatus.getGunsCode();
  158. if(deviceStatus==null){
  159. if(t<10*60*1000){
  160. return;
  161. }else{
  162. log.info("{}-{}无10分钟还没有记录要停止充电", orderStatus.getPileCode(), orderStatus.getGunsCode());
  163. orderStatus.setReasonStopCharging(TransConstant.OTHER_STOP);
  164. stopOneOrder(orderStatus);
  165. }
  166. return;
  167. }
  168. if(deviceStatus.getGunStatus() != StatusConstant.CHARGING){
  169. if(t<5*60*1000){
  170. log.info("{}-{}-5分钟内还未变充电状态忽略", orderStatus.getPileCode(), orderStatus.getGunsCode());
  171. return;
  172. }else{
  173. log.info("{}-{}-5分钟后还不是充电状态录要停止充电", orderStatus.getPileCode(), orderStatus.getGunsCode());
  174. //状态那我为
  175. orderStatus.setReasonStopCharging(TransConstant.OTHER_STOP);
  176. stopOneOrder(orderStatus);
  177. return;
  178. }
  179. }
  180. //上送充电状态
  181. JSONObject statusJSON = redisCache.getCacheObject(RedisConstant.DEVICE_PORT_STATUS + deviceStatus.getDeviceImei());
  182. if(statusJSON==null){
  183. log.info("无最近103数据{}",orderStatus.getPileCode());
  184. try103(orderStatus);
  185. return;
  186. }
  187. Integer voltage;
  188. Integer power;
  189. if(port==1){
  190. voltage = statusJSON.getInteger("voltage");
  191. }else{
  192. voltage = statusJSON.getInteger("voltage_1");
  193. if(voltage==null){
  194. voltage = statusJSON.getInteger("voltage");
  195. }
  196. }
  197. if(port == 1){
  198. power = statusJSON.getInteger("power");
  199. }else{
  200. power = statusJSON.getInteger("power_1");
  201. }
  202. if(power==null){
  203. power = 0;
  204. }
  205. if(voltage==null){
  206. voltage = 0;
  207. }
  208. //计算实时数据
  209. long endTime = System.currentTimeMillis();
  210. //算电量
  211. Map<String, BigDecimal> start = transMoney.getTransData();
  212. String transCacheKey = "ChargingTrans:"+orderStatus.getId();
  213. if(redisCache.hasKey(transCacheKey)){
  214. start = redisCache.getCacheObject(transCacheKey);
  215. }else{
  216. //缓存120秒避免重复计算电量
  217. try {
  218. start = transMoney.compute(port, billingModel, orderStatus.getCreateTime(), endTime);
  219. } catch (Exception e) {
  220. e.printStackTrace();
  221. log.error("计算订单异常{},{}",orderStatus.getPileCode(),e.getMessage());
  222. return;
  223. }
  224. redisCache.setCacheObject(transCacheKey, start, 90, TimeUnit.SECONDS);
  225. }
  226. BigDecimal elec = start.get("elec");
  227. BigDecimal money = start.get("money");
  228. if (elec.equals(new BigDecimal("0.0000"))) {
  229. elec = elec.add(new BigDecimal("0.0001").setScale(4, BigDecimal.ROUND_DOWN));
  230. }
  231. log.info("{}-{}-{}充电中=>实时elec:{}>>>实时金额>>>{}=>p:{},v:{}" ,orderStatus.getPileCode(),port,elec,orderStatus.getGunsCode(),money,power,voltage);
  232. //????????????????????????????
  233. if (money.compareTo(orderStatus.getStartMoney()) > 0) {
  234. //余额没有了,停充
  235. orderStatus.setReasonStopCharging(TransConstant.INSUFFICIENT_BALANCE_EXCEPTION_STOP);
  236. stopOneOrder(orderStatus);
  237. log.info("{},{},{}实时状态校验时余额不足>>>>>>停充>>>>",orderStatus.getPileCode(),orderStatus.getGunsCode(),orderStatus.getTransOrder());
  238. return;
  239. }
  240. int mi = (int) (System.currentTimeMillis() - orderStatus.getCreateTime()) / 1000 / 60;
  241. realTimeStatusPushFrame.deviceStatusPush(deviceConnectionMsg, orderStatus.getTransOrder(), deviceStatus.getPileCode(), deviceStatus.getGunPort(), deviceStatus.getGunStatus(), deviceStatus.getInsertGunStatus(), voltage, power, elec, money, mi);
  242. log.info("↑↑↑{},{},{}充电中实时状态上报 ",orderStatus.getPileCode(),orderStatus.getGunsCode(),orderStatus.getId());
  243. }
  244. }