YkcMsgHandle.java 35 KB

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