YkcMsgHandle.java 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. package com.tmzn.devicelinkykc.message;
  2. import cn.hutool.db.sql.Order;
  3. import com.alibaba.fastjson2.JSONObject;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import com.tmzn.devicelinkykc.constant.Constant;
  6. import com.tmzn.devicelinkykc.constant.DeviceOnlineStatus;
  7. import com.tmzn.devicelinkykc.constant.PortStatusConstant;
  8. import com.tmzn.devicelinkykc.constant.RedisConstant;
  9. import com.tmzn.devicelinkykc.constant.ykc.BillingModelConst;
  10. import com.tmzn.devicelinkykc.constant.ykc.StatusConstant;
  11. import com.tmzn.devicelinkykc.constant.ykc.TransConstant;
  12. import com.tmzn.devicelinkykc.entity.BillingModel;
  13. import com.tmzn.devicelinkykc.entity.DeviceStatus;
  14. import com.tmzn.devicelinkykc.entity.OrderStatus;
  15. import com.tmzn.devicelinkykc.entity.TransOrder;
  16. import com.tmzn.devicelinkykc.frameMsg.DataConversion;
  17. import com.tmzn.devicelinkykc.frameMsg.TransMoney;
  18. import com.tmzn.devicelinkykc.frameMsg.frameType.*;
  19. import com.tmzn.devicelinkykc.mapstruct.TransMapping;
  20. import com.tmzn.devicelinkykc.msgEnum.YkcSendDevice;
  21. import com.tmzn.devicelinkykc.openfeign.MsgService;
  22. import com.tmzn.devicelinkykc.openfeign.transdata.DataParam;
  23. import com.tmzn.devicelinkykc.openfeign.transdata.RpcResult;
  24. import com.tmzn.devicelinkykc.redis.RedisCache;
  25. import com.tmzn.devicelinkykc.service.*;
  26. import com.tmzn.devicelinkykc.socket.DeviceConnectionMsg;
  27. import com.tmzn.devicelinkykc.socket.SocketHandle;
  28. //import com.tmzn.devicelinkykc.test.SendMsgToDevice;
  29. import com.tmzn.devicelinkykc.transdata.entity.DeviceParam;
  30. import com.tmzn.devicelinkykc.transdata.entity.MainBoard;
  31. import com.tmzn.devicelinkykc.transdata.entity.opertype.OperEnum;
  32. import com.tmzn.devicelinkykc.util.Encrytion;
  33. import com.tmzn.devicelinkykc.util.ResultUtil;
  34. import org.slf4j.Logger;
  35. import org.slf4j.LoggerFactory;
  36. import org.springframework.beans.factory.annotation.Autowired;
  37. import org.springframework.stereotype.Component;
  38. import java.io.IOException;
  39. import java.math.BigDecimal;
  40. import java.util.*;
  41. import java.util.concurrent.TimeUnit;
  42. import java.util.stream.Collectors;
  43. /**
  44. * @author xp
  45. * @date 2024/3/13
  46. * @explain " "
  47. */
  48. @Component
  49. public class YkcMsgHandle {
  50. private static final Logger logger = LoggerFactory.getLogger(YkcMsgHandle.class);
  51. private static final BigDecimal zero = new BigDecimal("0");
  52. @Autowired
  53. private RedisCache redisCache;
  54. @Autowired
  55. private OrderStatusService orderStatusService;
  56. @Autowired
  57. private DeviceStatusService deviceStatusService;
  58. @Autowired
  59. private DeviceControlerService deviceControlerService;
  60. @Autowired
  61. private CheckTime checkTime;
  62. @Autowired
  63. private BillingModelFrame billingModelFrame;
  64. @Autowired
  65. private MsgService msgService;
  66. @Autowired
  67. private BillingModelService billingModelService;
  68. @Autowired
  69. private RealTimeStatusPushFrame realTimeStatusPushFrame;
  70. @Autowired
  71. private CharngingPushFrame charngingPushFrame;
  72. @Autowired
  73. private RemoteBalanceUpdatePushFrame remoteBalanceUpdatePushFrame;
  74. @Autowired
  75. private TransMoney transMoney;
  76. @Autowired
  77. private TransactionFlowPushFrame transactionFlowPushFrame;
  78. @Autowired
  79. private TransOrderService transOrderService;
  80. @Autowired
  81. private TransMapping transMapping;
  82. public void startListening(DeviceConnectionMsg deviceConnectionMsg) {
  83. Runnable listener = () -> {
  84. boolean temp = true;
  85. while (temp) {
  86. // 接收数据帧
  87. byte[] receiveData = new byte[1024];
  88. int length = 0;
  89. try {
  90. if (deviceConnectionMsg.getSocket().isConnected()) {
  91. length = deviceConnectionMsg.getSocket().getInputStream().read(receiveData);
  92. } else {
  93. logger.info("receiveYKCData socket no>>>>");
  94. }
  95. if (length < 0) {
  96. return;
  97. }
  98. } catch (IOException e) {
  99. //e.printStackTrace();
  100. String message = e.getMessage();
  101. logger.info(deviceConnectionMsg.getDeviceId() + ":Receive YKC dataMsg IOException !!!!!!!:" + message + "!!!!!!!!" + message + "!!!!!!!!" + message + "!!!!!!!!" + message + "!!!!!!!!");
  102. //异常后操作删除所有的缓存,重新获取
  103. DataParam dataParam = new DataParam();
  104. dataParam.setDeviceId(deviceConnectionMsg.getImei());
  105. dataParam.setCcid(deviceConnectionMsg.getImei());
  106. JSONObject object1 = new JSONObject();
  107. dataParam.setData(object1);
  108. dataParam.setType(OperEnum.PortDetail.getType());
  109. msgService.sendMsg(dataParam);
  110. temp = false;
  111. continue;
  112. }
  113. byte[] response = new byte[length];
  114. //将接收到的消息类型拿到进行判断
  115. System.arraycopy(receiveData, 0, response, 0, response.length);
  116. String s = Integer.toHexString(response[5] & 0xFF);
  117. int framType = response[5] & 0xFF;//Integer.parseInt(s);
  118. int encry = response[4] & 0xFF;
  119. //消息体
  120. byte[] respone_msg = Arrays.copyOfRange(response, 6, response.length - 2);
  121. if (encry == 0) {
  122. logger.info("{},未加密消息,frame:{},data:{}",deviceConnectionMsg.getDeviceId(),framType, DataConversion.bytesToHexString(respone_msg));
  123. } else {
  124. try {
  125. String key = redisCache.getCacheMapValue(RedisConstant.YKC_KEY_MAP,deviceConnectionMsg.getDeviceId());
  126. // String key = redisCache.getCacheObject(RedisConstant.KEYS + deviceConnectionMsg.getDeviceId());
  127. respone_msg = Encrytion.decrypt(respone_msg, key.getBytes());
  128. logger.info("{},加密消息,frame:{},data:{}",deviceConnectionMsg.getDeviceId(),framType, DataConversion.bytesToHexString(respone_msg));
  129. } catch (Exception e) {
  130. logger.info("{},ykc->msg decrypt Exception",deviceConnectionMsg.getDeviceId());
  131. e.printStackTrace();
  132. }
  133. }
  134. if (framType == YkcSendDevice.LOGIN_RESPONSE.getFrameType()) {
  135. logger.info("↓↓↓↓↓"+deviceConnectionMsg.getDeviceId()+"登录认证应答"+framType);
  136. //处理登录成功与否
  137. boolean res = loginResponse(deviceConnectionMsg, respone_msg);
  138. //计费模型请求
  139. if(res){
  140. logger.info("↓↓↓↓↓"+deviceConnectionMsg.getDeviceId()+"请求计费模型");
  141. billingModelFrame.checkBillingModel(deviceConnectionMsg);
  142. }
  143. } else if (framType == YkcSendDevice.HEART_RESPONSE.getFrameType()) {
  144. //TODO:个人理解,枪不管故障还是正常都会有心跳,心跳应答正常说明设备是正常的状态,所以这里不管是同一设备的几号枪心跳都缓存下来心跳应答时间
  145. // logger.info("ykc->dev"+deviceConnectionMsg.getDeviceId()+"↓↓↓↓↓↓↓↓↓↓↓↓↓心跳包应答消息↓↓↓↓↓↓↓↓↓↓↓↓↓"+framType);
  146. deviceConnectionMsg.setHeartTime(System.currentTimeMillis());
  147. // logger.info("===========心跳包应答============over");
  148. } else if (framType == YkcSendDevice.BILLING_MODEL_VALIDATE_RESPONSE.getFrameType()) {
  149. billingModelHandle(deviceConnectionMsg, respone_msg);
  150. } else if (framType == YkcSendDevice.BILLING_MODEL_RESPONSE.getFrameType()) {
  151. logger.info("↓↓↓↓↓" + deviceConnectionMsg.getDeviceId() + "计费模型请求应答" + framType);
  152. try {
  153. billingModelFrame.setBillingModel(deviceConnectionMsg, respone_msg);
  154. } catch (Exception e) {
  155. e.printStackTrace();
  156. }
  157. } else if (framType == YkcSendDevice.BILLING_MODEL_VALIDATE_RESPONSE_SG.getFrameType()) {
  158. logger.info("↓↓↓↓↓" + deviceConnectionMsg.getDeviceId() + "深谷计费模型请求应答" + framType);
  159. try {
  160. billingModelFrame.setSgBillingModel(deviceConnectionMsg, respone_msg);
  161. } catch (Exception e) {
  162. e.printStackTrace();
  163. }
  164. } else if (framType == YkcSendDevice.TRANSACTION_RECORDS_RESPONSE.getFrameType()) {
  165. logger.info("↓↓↓↓↓" + deviceConnectionMsg.getDeviceId() + "交易记录确认");
  166. byte[] trans = Arrays.copyOfRange(respone_msg, 0, 16);
  167. byte[] reason = Arrays.copyOfRange(respone_msg, 16, 17);
  168. QueryWrapper<OrderStatus> orderStatusQueryWrapper = new QueryWrapper<>();
  169. orderStatusQueryWrapper.eq("trans_order", trans);
  170. OrderStatus one = orderStatusService.getOne(orderStatusQueryWrapper);
  171. QueryWrapper<TransOrder> transOrderQueryWrapper = new QueryWrapper<>();
  172. transOrderQueryWrapper.eq("trans_order", trans);
  173. TransOrder transOrderServiceOne = transOrderService.getOne(transOrderQueryWrapper);
  174. if (reason[0] == 0x00) {
  175. one.setTransactionOrderReplyStatus(StatusConstant.TRANSACTION_ORDER_REPLY_STATUS_SUCC);
  176. transOrderServiceOne.setFlage(StatusConstant.TRANSACTION_ORDER_REPLY_STATUS_SUCC);
  177. } else if (reason[0] == 0x01) {
  178. one.setTransactionOrderReplyStatus(StatusConstant.TRANSACTION_ORDER_REPLY_STATUS_FAIL);
  179. } else if (reason[0] == 0x02) {
  180. one.setTransactionOrderReplyStatus(StatusConstant.TRANSACTION_ORDER_REPLY_STATUS_ILLEGAL);
  181. }
  182. //接收到后将订单校验从redis剔除
  183. orderStatusService.updateById(one);
  184. transOrderService.updateById(transOrderServiceOne);
  185. } else if (framType == YkcSendDevice.DEVICE_STATUS_REQUEST.getFrameType()) {
  186. logger.info("↓↓↓↓↓{}读取实时监测数据",deviceConnectionMsg.getDeviceId());
  187. } else if (framType == YkcSendDevice.START_CHARNGING_REQUEST.getFrameType() || framType == YkcSendDevice.START_CHARNGING_REQUEST_16.getFrameType()) {
  188. logger.info("↓↓↓↓↓{}运营平台远程控制启机" + framType,deviceConnectionMsg.getDeviceId());
  189. startChargingRequest(deviceConnectionMsg, respone_msg);
  190. } else if (framType == YkcSendDevice.STOP_CHARNGING_REQUEST.getFrameType()) {
  191. logger.info("↓↓↓↓↓{}运营平台远程停机",deviceConnectionMsg.getDeviceId());
  192. stopChargingRequest(deviceConnectionMsg, respone_msg);
  193. } else if (framType == YkcSendDevice.UPDATE_BALANCE.getFrameType()) {
  194. logger.info("↓↓↓↓↓{}远程更新余额",deviceConnectionMsg.getDeviceId());
  195. try {
  196. remoteBalanceUpdate(deviceConnectionMsg, respone_msg);
  197. } catch (Exception e) {
  198. e.printStackTrace();
  199. }
  200. } else if (framType == YkcSendDevice.CHECKTIME.getFrameType()) {
  201. logger.info("↓↓↓↓↓{}对时设置" + framType,deviceConnectionMsg.getDeviceId());
  202. checkTime.checkTimeSend(deviceConnectionMsg);
  203. } else if (framType == YkcSendDevice.BILLING_MODEL_SETTING_SG.getFrameType()) {
  204. logger.info("↓↓↓↓↓{}深谷计费模型设置",deviceConnectionMsg.getDeviceId());
  205. try {
  206. //有异常就是失败
  207. billingModelFrame.setSgBillingModel(deviceConnectionMsg, respone_msg);
  208. billingModelFrame.resp(deviceConnectionMsg, (byte) 1);
  209. } catch (Exception e) {
  210. billingModelFrame.resp(deviceConnectionMsg, (byte) 0);
  211. e.printStackTrace();
  212. }
  213. } else if (framType == YkcSendDevice.BILLING_MODEL_SETTING.getFrameType()) {
  214. logger.info("↓↓↓↓↓{}计费模型设置",deviceConnectionMsg.getDeviceId());
  215. try {
  216. //有异常就是失败
  217. billingModelFrame.setBillingModel(deviceConnectionMsg, respone_msg);
  218. billingModelFrame.resp(deviceConnectionMsg, (byte) 1);
  219. } catch (Exception e) {
  220. billingModelFrame.resp(deviceConnectionMsg, (byte) 0);
  221. e.printStackTrace();
  222. }
  223. } else if (framType == YkcSendDevice.REMOTE_REBOOT.getFrameType()) {
  224. logger.info("↓↓↓↓↓{}远程重启",deviceConnectionMsg.getDeviceId());
  225. } else if (framType == YkcSendDevice.UPLOAD_FILE_UPDATE.getFrameType()) {
  226. logger.info("↓↓↓↓↓{}远程更新",deviceConnectionMsg.getDeviceId());
  227. }
  228. }
  229. };
  230. Thread thread = new Thread(listener);
  231. thread.start();
  232. }
  233. /**
  234. * 登录回复消息处理
  235. *
  236. * @param deviceConnectionMsg
  237. * @param respone_msg
  238. */
  239. private boolean loginResponse(DeviceConnectionMsg deviceConnectionMsg, byte[] respone_msg) {
  240. int login_result = respone_msg[7] & 0xFF;
  241. if (ResultUtil.isSuccess(login_result)) {
  242. //登录成功,相当于初始化心跳包接收时间更新,初始化心跳包时间相当于登录成功,心跳包能正常上传
  243. logger.info("{}login successfully", deviceConnectionMsg.getDeviceId());
  244. deviceConnectionMsg.setHeartTime(System.currentTimeMillis());
  245. deviceConnectionMsg.setLoginStatus(Constant.DEVICE_LOGIN_STATUS);
  246. return true;
  247. } else {
  248. logger.info("{}login failed ,waitting for retry", deviceConnectionMsg.getDeviceId());
  249. //登录失败等心跳包10秒后进行重试
  250. return false;
  251. }
  252. }
  253. /**
  254. * 接收到云快充启机指令的处理
  255. *
  256. * @param deviceConnectionMsg
  257. * @param respone_msg
  258. */
  259. private void startChargingRequest(DeviceConnectionMsg deviceConnectionMsg, byte[] respone_msg) {
  260. try {
  261. //1.解析出启动充电流水号
  262. //查询设备sn和imie
  263. QueryWrapper<DeviceStatus> deviceStatusQueryWrapper = new QueryWrapper<>();
  264. deviceStatusQueryWrapper.eq("pile_code", deviceConnectionMsg.getDeviceId());
  265. List<DeviceStatus> list = deviceStatusService.list(deviceStatusQueryWrapper);
  266. //可能双枪
  267. DeviceStatus deviceStatus = list.get(0);
  268. //切出订单号,保存在连接的该设备中
  269. byte[] transOrder = Arrays.copyOfRange(respone_msg, 0, 16);
  270. //测试
  271. t = transOrder;
  272. byte[] guns = Arrays.copyOfRange(respone_msg, 23, 24);
  273. byte[] card = Arrays.copyOfRange(respone_msg, 32, 40);
  274. byte[] logCard = Arrays.copyOfRange(respone_msg, 24, 32);
  275. byte[] startMoney = Arrays.copyOfRange(respone_msg, respone_msg.length - 6, respone_msg.length - 2);
  276. boolean temp = false;
  277. int result = 0x00; //失败
  278. int reason = 0x00; //无
  279. if (guns[0] == 1) {
  280. DeviceStatus oneDeviceStatus = redisCache.getCacheMapValue(RedisConstant.ONLINE_DEVICE_ONE, deviceConnectionMsg.getDeviceId());
  281. logger.info(oneDeviceStatus.toString());
  282. if (oneDeviceStatus.getOnlineStatus() == StatusConstant.OFFLINE || StatusConstant.OFFLINE == oneDeviceStatus.getGunStatus()) {
  283. //离线上报
  284. reason = 0x04;
  285. temp = true;
  286. } else if (StatusConstant.CHARGING == oneDeviceStatus.getGunStatus()) {
  287. //枪已在充电中
  288. reason = 0x02;
  289. temp = true;
  290. } else if (StatusConstant.FAULT == oneDeviceStatus.getGunStatus()) {
  291. //枪故障
  292. reason = 0x03;
  293. temp = true;
  294. } else if (StatusConstant.INSERT_GUNS_NO == oneDeviceStatus.getInsertGunStatus()) {
  295. //未插枪
  296. reason = 0x05;
  297. temp = false;
  298. } else if (PortStatusConstant.EMERGENCY_STOP == oneDeviceStatus.getGunStatus()) {
  299. //急停没复位,也是启充失败
  300. temp = true;
  301. }
  302. } else if (guns[0] == 2) {
  303. DeviceStatus twoDeviceStatus = redisCache.getCacheMapValue(RedisConstant.ONLINE_DEVICE_TWO, deviceConnectionMsg.getDeviceId());
  304. if (twoDeviceStatus.getOnlineStatus() == StatusConstant.OFFLINE || StatusConstant.OFFLINE == twoDeviceStatus.getGunStatus()) {
  305. //离线上报
  306. reason = 0x04;
  307. temp = true;
  308. } else if (StatusConstant.CHARGING == twoDeviceStatus.getGunStatus()) {
  309. //枪已在充电中
  310. reason = 0x02;
  311. temp = true;
  312. } else if (StatusConstant.FAULT == twoDeviceStatus.getGunStatus()) {
  313. //枪故障
  314. reason = 0x03;
  315. temp = true;
  316. } else if (StatusConstant.INSERT_GUNS_NO == twoDeviceStatus.getInsertGunStatus()) {
  317. //未插枪
  318. reason = 0x05;
  319. temp = true;
  320. } else if (PortStatusConstant.EMERGENCY_STOP == twoDeviceStatus.getGunStatus()) {
  321. //急停没复位,也是启充失败
  322. temp = true;
  323. }
  324. }
  325. if (temp) {
  326. logger.info("启动失败{}:reason:{}" ,deviceConnectionMsg.getDeviceId(), reason);
  327. charngingPushFrame.startStatus(deviceConnectionMsg, transOrder, guns[0], result, reason);
  328. Map<String, BigDecimal> compute = transMoney.getTransData();
  329. transactionFlowPushFrame.sendTrans(deviceConnectionMsg, transOrder, deviceStatus.getPileCode(), guns[0], System.currentTimeMillis(), System.currentTimeMillis(), new BillingModel(), card, compute, TransConstant.START_FAIL);
  330. return;
  331. }
  332. BigDecimal bigDecimalmoney = DataConversion.arrToBigDec(startMoney, 2, 2).setScale(2, BigDecimal.ROUND_UP);
  333. logger.info("{}开始充电,startMoney" + bigDecimalmoney + "sbyt+" + DataConversion.bytesToHexString(startMoney),deviceConnectionMsg.getDeviceId());
  334. OrderStatus orderStatus = new OrderStatus();
  335. orderStatus.setDeviceSn(deviceStatus.getDeviceSn());
  336. orderStatus.setDeviceImei(deviceConnectionMsg.getImei());
  337. orderStatus.setPileCode(deviceStatus.getPileCode());
  338. orderStatus.setGunsCode(guns[0]);
  339. orderStatus.setStartMoney(bigDecimalmoney);
  340. orderStatus.setCard(card);
  341. orderStatus.setTransOrder(transOrder);
  342. orderStatus.setCreateTime(System.currentTimeMillis());
  343. //2.保存交易流水号并记录本次交易流水状态
  344. orderStatusService.save(orderStatus);
  345. this.saveOrder(orderStatus);
  346. //setMoney(orderStatus);//让设备记余额不足情况,启充时要传启充金额money,传0就是启充默认值
  347. //3.向设备发送启机指令
  348. if (reason == 0x05) {
  349. //未插枪不启充设备,但是返回未插枪
  350. logger.info("{}未插枪等待充电订单:" + DataConversion.bytesToHexString(transOrder),deviceConnectionMsg.getDeviceId());
  351. charngingPushFrame.startStatus(deviceConnectionMsg, transOrder, guns[0], result, reason);
  352. redisCache.setCacheObject(RedisConstant.NO_INSERT_GUN_YKC + deviceStatus.getPileCode(), DataConversion.bytesToHexString(transOrder), 60 * 1000, TimeUnit.MILLISECONDS);
  353. } else {
  354. deviceControlerService.startCharge(deviceStatus.getDeviceImei(), deviceStatus.getDeviceImei(), (int) guns[0], 0);
  355. }
  356. String gunCode = String.valueOf(guns[0]);
  357. //标记最后订单时间 5分钟内不上报空闲状态 避免刚下单状态还没更新就被freeTask任务给顶掉了
  358. redisCache.setCacheMapValue(RedisConstant.PILE_GUN_PAY_TIME, orderStatus.getPileCode() + "_" + gunCode, System.currentTimeMillis());
  359. //TODO:在处理设备消息的地方需要处理设备启动充电是否成功
  360. //TODO:保存交易流水时保存一个交易订单
  361. } catch (Exception e) {
  362. logger.info("{}启动充电异常,{}",deviceConnectionMsg.getDeviceId(),e.getMessage());
  363. realTimeStatusPushFrame.deviceStatusPush(deviceConnectionMsg, t, deviceConnectionMsg.getDeviceId(), (byte) 1, (byte) 2, (byte) 1, 0, 0, zero, zero, 0);
  364. e.printStackTrace();
  365. }
  366. }
  367. private static byte[] t = new byte[16];
  368. /**
  369. * 计费模型校验应答处理
  370. *
  371. * @param deviceConnectionMsg
  372. * @param respone_msg
  373. */
  374. private void billingModelHandle(DeviceConnectionMsg deviceConnectionMsg, byte[] respone_msg) {
  375. byte[] modelNum = Arrays.copyOfRange(respone_msg, 7, 9);
  376. byte[] result = Arrays.copyOfRange(respone_msg, 9, 10);
  377. logger.info("计费模型验证应答" + deviceConnectionMsg.getDeviceId() + ">>modelNum:" + DataConversion.bytesToHexString(modelNum) + ";result:" + DataConversion.bytesToHexString(result));
  378. if (result[0] == BillingModelConst.DIFFERENT) {
  379. logger.info("获取计费模型{}", deviceConnectionMsg.getDeviceId());
  380. //不一致请求计费模型,再向平台请求计费模型0x09
  381. billingModelFrame.getBillingModel(deviceConnectionMsg);
  382. }
  383. }
  384. /**
  385. * 停机指令处理
  386. *
  387. * @param deviceConnectionMsg
  388. * @param respone_msg
  389. */
  390. private void stopChargingRequest(DeviceConnectionMsg deviceConnectionMsg, byte[] respone_msg) {
  391. byte[] guns = Arrays.copyOfRange(respone_msg, 7, 8);
  392. //查询设备sn和imie
  393. QueryWrapper<DeviceStatus> deviceStatusQueryWrapper = new QueryWrapper<>();
  394. deviceStatusQueryWrapper.eq("pile_code", deviceConnectionMsg.getDeviceId());
  395. List<DeviceStatus> list = deviceStatusService.list(deviceStatusQueryWrapper);
  396. DeviceStatus deviceStatus = list.get(0);
  397. try {
  398. TimeUnit.MILLISECONDS.sleep(300);
  399. } catch (InterruptedException e) {
  400. e.printStackTrace();
  401. }
  402. RpcResult rpcResult = deviceControlerService.stopCharge(deviceStatus.getDeviceImei(), deviceStatus.getDeviceImei(), (int) guns[0]);
  403. if (rpcResult.isOk()) {
  404. //发送停充成功,一般没有指令发送成功设备不执行
  405. /* //deviceStatus.setGunStatus((byte) PortStatusConstant.INSERT_GUN);
  406. deviceStatus.setOnlineStatus(DeviceOnlineStatus.ONLINE);
  407. deviceStatus.setUpdateTime(System.currentTimeMillis());
  408. deviceStatusService.updateById(deviceStatus);*/
  409. QueryWrapper<OrderStatus> orderStatusQueryWrapper = new QueryWrapper<>();
  410. orderStatusQueryWrapper.eq("device_imei", deviceStatus.getDeviceImei()).eq("guns_code", guns[0]).orderByDesc("create_time").last("limit 1");
  411. OrderStatus statusServiceOne = orderStatusService.getOne(orderStatusQueryWrapper);
  412. statusServiceOne.setEndTime(System.currentTimeMillis());
  413. statusServiceOne.setReasonStopCharging(TransConstant.APP_REMOTE_STOP);
  414. orderStatusService.updateById(statusServiceOne);
  415. redisCache.setCacheMapValue(guns[0] == 1 ? RedisConstant.ONLINE_DEVICE_ONE : RedisConstant.ONLINE_DEVICE_TWO, deviceStatus.getPileCode(), deviceStatus);
  416. } else {
  417. logger.info("stop charging device:" + deviceStatus.getDeviceSn() + ";port:" + guns[0] + "stop charnging fail");
  418. }
  419. //获取端口状态
  420. DeviceParam deviceParam = new DeviceParam();
  421. deviceParam.setDeviceId(deviceStatus.getDeviceImei());
  422. deviceParam.setCcid(deviceStatus.getDeviceImei());
  423. deviceControlerService.sendPortDetailCmd(deviceParam);
  424. }
  425. /***
  426. * 远程余额更新
  427. * @param deviceConnectionMsg
  428. * @param respone_msg
  429. */
  430. private void remoteBalanceUpdate(DeviceConnectionMsg deviceConnectionMsg, byte[] respone_msg) throws Exception {
  431. byte[] pileCode = Arrays.copyOfRange(respone_msg, 0, 7);
  432. byte[] guns = Arrays.copyOfRange(respone_msg, 7, 8);
  433. byte[] card = Arrays.copyOfRange(respone_msg, 8, 16);
  434. byte[] balance = Arrays.copyOfRange(respone_msg, 16, 20);
  435. BigDecimal bigDecimal = DataConversion.arrToBigDec(balance, 2, 2);
  436. String pile = DataConversion.bytesToHexString(pileCode);
  437. logger.info("更新余额>>" + bigDecimal + ";pileCode:" + pile);
  438. //TODO:1.这里更新的余额需要针对充电桩使用的人员进行修改;(考虑后台计费);2.更新操作完成时候响应云快充更新结果
  439. //拿当前的订单去更新余额
  440. QueryWrapper<OrderStatus> orderStatusQueryWrapper = new QueryWrapper<>();
  441. orderStatusQueryWrapper.eq("pile_code", pile).eq("guns_code", guns[0]).eq("card", card).orderByDesc("create_time").last("limit 1");
  442. OrderStatus statusServiceOne = orderStatusService.getOne(orderStatusQueryWrapper);
  443. QueryWrapper<BillingModel> billingModelQueryWrapper = new QueryWrapper<>();
  444. billingModelQueryWrapper.eq("pile_code", pile);
  445. BillingModel model = billingModelService.getOne(billingModelQueryWrapper);
  446. //后台计费
  447. Map<String, BigDecimal> map = transMoney.compute(1, model, statusServiceOne.getCreateTime(), System.currentTimeMillis());
  448. BigDecimal money = statusServiceOne.getStartMoney().subtract(map.get("money")).setScale(4, BigDecimal.ROUND_DOWN);
  449. BigDecimal add = money.add(bigDecimal);
  450. statusServiceOne.setStartMoney(add);
  451. orderStatusService.updateById(statusServiceOne);
  452. //这里测试默认更新成功
  453. remoteBalanceUpdatePushFrame.updateBalance(deviceConnectionMsg, card, (byte) 0x00);
  454. }
  455. //保存订单开始状态,记录充电的交易流水
  456. private void saveOrder(OrderStatus orderStatus) {
  457. TransOrder transOrder = transMapping.orderStatusToTransOrder(orderStatus);
  458. byte[] transOrders = new byte[8];
  459. System.arraycopy(orderStatus.getTransOrder(), 8, transOrders, 0, transOrders.length);
  460. //为了云快充app显示的订单号一致,将订单号格式转化一下
  461. transOrder.setTrans(DataConversion.bytesToHexString(transOrders));
  462. boolean b = transOrderService.saveOrUpdate(transOrder);
  463. logger.info("保存订单>>>>>" + DataConversion.bytesToHexString(orderStatus.getTransOrder()) + "结果:" + b);
  464. }
  465. //余额不足解决办法,将下发的余额和尖峰平谷中最贵的价格发送到主板参数中,配合主板参数进行余额不足判定
  466. private void setMoney(OrderStatus orderStatus) {
  467. QueryWrapper<BillingModel> orderStatusQueryWrapper = new QueryWrapper<>();
  468. orderStatusQueryWrapper.eq("pile_code", orderStatus.getPileCode());
  469. BillingModel billingModel = billingModelService.getOne(orderStatusQueryWrapper);
  470. MainBoard mainBoard = new MainBoard();
  471. mainBoard.setBottomPrice(billingModel.getSharpPrice().add(billingModel.getSharpServiceFee()).intValue());
  472. mainBoard.setBottomServicePrice(0);
  473. mainBoard.setPeakPrice(billingModel.getSharpPrice().add(billingModel.getSharpServiceFee()).intValue());
  474. mainBoard.setPeakServicePrice(0);
  475. mainBoard.setBottomStart(0);
  476. mainBoard.setBottomEnd(24);
  477. mainBoard.setFeeType(0x00);
  478. //设置主板参数
  479. deviceControlerService.setMainBoard(orderStatus.getDeviceImei(), orderStatus.getDeviceImei(), mainBoard);
  480. }
  481. }