DeviceMsgHandle.java 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. package com.tmzn.devicelinkykc.message;
  2. import cn.hutool.http.HttpRequest;
  3. import cn.hutool.http.HttpResponse;
  4. import com.alibaba.fastjson2.JSONArray;
  5. import com.alibaba.fastjson2.JSONObject;
  6. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  7. import com.tmzn.devicelinkykc.constant.Constant;
  8. import com.tmzn.devicelinkykc.constant.DeviceOnlineStatus;
  9. import com.tmzn.devicelinkykc.constant.PortStatusConstant;
  10. import com.tmzn.devicelinkykc.constant.RedisConstant;
  11. import com.tmzn.devicelinkykc.constant.ykc.StatusConstant;
  12. import com.tmzn.devicelinkykc.constant.ykc.TransConstant;
  13. import com.tmzn.devicelinkykc.entity.*;
  14. import com.tmzn.devicelinkykc.frameMsg.DataConversion;
  15. import com.tmzn.devicelinkykc.frameMsg.FrameDataSplicing;
  16. import com.tmzn.devicelinkykc.frameMsg.TransMoney;
  17. import com.tmzn.devicelinkykc.frameMsg.frameType.CharngingPushFrame;
  18. import com.tmzn.devicelinkykc.frameMsg.frameType.LoginFrame;
  19. import com.tmzn.devicelinkykc.frameMsg.frameType.RealTimeStatusPushFrame;
  20. import com.tmzn.devicelinkykc.frameMsg.frameType.TransactionFlowPushFrame;
  21. import com.tmzn.devicelinkykc.msgparser.MessageParseMgr;
  22. import com.tmzn.devicelinkykc.openfeign.transdata.RpcResult;
  23. import com.tmzn.devicelinkykc.redis.RedisCache;
  24. import com.tmzn.devicelinkykc.service.*;
  25. import com.tmzn.devicelinkykc.socket.DeviceConnectionMsg;
  26. import com.tmzn.devicelinkykc.socket.SocketHandle;
  27. import com.tmzn.devicelinkykc.transdata.constant.NormalChargeConstant;
  28. import com.tmzn.devicelinkykc.transdata.entity.DeviceParam;
  29. import com.tmzn.devicelinkykc.util.Encrytion;
  30. import org.apache.logging.log4j.util.Strings;
  31. import org.slf4j.Logger;
  32. import org.slf4j.LoggerFactory;
  33. import org.springframework.beans.BeanUtils;
  34. import org.springframework.beans.factory.annotation.Autowired;
  35. import org.springframework.stereotype.Component;
  36. import org.springframework.stereotype.Controller;
  37. import java.io.IOException;
  38. import java.math.BigDecimal;
  39. import java.util.*;
  40. import java.util.concurrent.ConcurrentHashMap;
  41. import java.util.concurrent.TimeUnit;
  42. /**
  43. * @author xp
  44. * @date 2024/3/13
  45. * @explain " 设备消息处理 "
  46. * //TODO:考虑设备上来的消息只走数据库查询不走redis订阅数据
  47. */
  48. @Component
  49. public class DeviceMsgHandle {
  50. @Autowired
  51. private DeviceStatusService deviceStatusService;
  52. @Autowired
  53. private SocketHandle socketHandle;
  54. @Autowired
  55. private RedisCache redisCache;
  56. @Autowired
  57. private RealTimeStatusPushFrame realTimeStatusPushFrame;
  58. @Autowired
  59. private TransactionFlowPushFrame transactionFlowPushFrame;
  60. @Autowired
  61. private LoginFrame loginFrame;
  62. @Autowired
  63. private CharngingPushFrame charngingPushFrame;
  64. @Autowired
  65. private DeviceService deviceService;
  66. @Autowired
  67. private OrderStatusService orderStatusService;
  68. @Autowired
  69. private DeviceControlerService deviceControlerService;
  70. @Autowired
  71. private MessageParseMgr messageParseMgr;
  72. @Autowired
  73. private BillingModelService billingModelService;
  74. @Autowired
  75. private TransMoney transMoney;
  76. private static final Logger logger = LoggerFactory.getLogger(DeviceMsgHandle.class);
  77. private Long lastLogTime;
  78. private static final Long gap = 1000 * 30L;
  79. private static final BigDecimal zero = new BigDecimal("0");
  80. public void deviceMsg(String msg) throws Exception {
  81. //必须过滤调非云快充设备
  82. //logger.info("redis中msg>>>" + msg);
  83. msg = msg.substring(1, msg.length() - 1);
  84. msg = msg.replace("\\", "");
  85. // checkActive(msg);
  86. JSONObject jsonObject = null;
  87. try {
  88. jsonObject = JSONObject.parseObject(msg);
  89. } catch (Exception e) {
  90. //这里正常格式才走,不正常的格式不打印报错了;可能有其他格式的数据过来;正常要解析的数据是能走到JSON中的
  91. logger.info("device msg conversion exception not processed!!!" + msg);
  92. return;
  93. //e.printStackTrace();
  94. }
  95. String imei = jsonObject.getString("imei");
  96. if (Strings.isEmpty(imei)) {
  97. return;
  98. }
  99. String pileCode = "";
  100. try {
  101. pileCode = redisCache.getCacheMapValue(RedisConstant.DEVICE_IMEI_PILE_MAP, imei);
  102. if (Strings.isEmpty(pileCode)) {
  103. return;
  104. }
  105. } catch (Exception e) {
  106. e.printStackTrace();
  107. return;
  108. }
  109. //logger.info("{},msg>>>" + msg, imei);
  110. //设备状态更新,true:没有type不是设备上送类型不往云快充处理 false:需要根据设备消息类型往下处理是不是需要上报云快充
  111. boolean packageFlag = false;
  112. try{
  113. int cmd = jsonObject.getInteger("cmd");
  114. if(cmd == 75960 && jsonObject.containsKey("data")){
  115. JSONArray dataArray = jsonObject.getJSONArray("data");
  116. List<Integer> dataListDirect = dataArray.toJavaList(Integer.class);
  117. List<List<Integer>> packages = Encrytion.parseMorePackage(dataListDirect);
  118. if(packages.size()>0){
  119. packageFlag = true;
  120. for(int i=0;i<packages.size();i++){
  121. try{
  122. Integer type = packages.get(i).get(1);
  123. JSONObject newObj = new JSONObject();
  124. newObj.put("imei", jsonObject.get("imei"));
  125. newObj.put("dev_id",jsonObject.get("dev_id"));
  126. newObj.put("data",packages.get(i));//重写拆
  127. newObj.put("cmd",cmd);// 包data
  128. newObj.put("type",type); //重写拆包
  129. JSONObject realData = messageParseMgr.parseMessage(cmd+"_"+type,newObj);
  130. if(realData!=null){
  131. newObj.put("real_data",realData);//重写拆包后real_data
  132. }
  133. if(packages.size()>1){
  134. logger.info("new object,{}",newObj);
  135. }
  136. handleDeviceMsg(newObj, pileCode);
  137. }catch (Exception e){
  138. e.printStackTrace();
  139. logger.info("拆包处理异常{},{}",e.getMessage(),msg);
  140. }
  141. }
  142. return;
  143. }
  144. }
  145. }catch (Exception e){
  146. e.printStackTrace();
  147. logger.error("拆包异常--{}---{}",e.getMessage(),msg);
  148. }
  149. if(packageFlag){
  150. // logger.info("p0");
  151. return;
  152. }
  153. try {
  154. handleDeviceMsg(jsonObject, pileCode);
  155. } catch (Exception e) {
  156. logger.error("处理消息失败{},{}", imei, e.getMessage());
  157. e.printStackTrace();
  158. }
  159. }
  160. public void testMsg(String msg) throws Exception {
  161. logger.info("testmsg>>>" + msg);
  162. JSONObject jsonObject = null;
  163. jsonObject = JSONObject.parseObject(msg);
  164. String imei = jsonObject.getString("imei");
  165. try {
  166. String pileCode = redisCache.getCacheMapValue(RedisConstant.DEVICE_IMEI_PILE_MAP, imei);
  167. if (Strings.isEmpty(pileCode)) {
  168. logger.info("非云快充设备");
  169. return;
  170. }
  171. handleDeviceMsg(jsonObject, pileCode);
  172. } catch (Exception e) {
  173. return;
  174. }
  175. //设备状态更新,true:没有type不是设备上送类型不往云快充处理 false:需要根据设备消息类型往下处理是不是需要上报云快充
  176. }
  177. private void checkActive(String s) {
  178. Long now = System.currentTimeMillis();
  179. if (lastLogTime == null) {
  180. lastLogTime = now;
  181. }
  182. Long gap = now - lastLogTime;
  183. if (gap > gap) {
  184. //logger.info("message:,{}", s);
  185. lastLogTime = now;
  186. }
  187. }
  188. //处理离线消息
  189. //查找所有端口状态置为下线 并推送状态给云快充
  190. private void handleOffline(String imei) {
  191. QueryWrapper<DeviceStatus> deviceStatusQueryWrapper = new QueryWrapper<>();
  192. deviceStatusQueryWrapper.eq("device_imei", imei);
  193. List<DeviceStatus> list = deviceStatusService.list(deviceStatusQueryWrapper);
  194. if (!list.isEmpty()) {
  195. for (DeviceStatus deviceStatus : list) {
  196. //deviceStatus.setInsertGunStatus(StatusConstant.INSERT_GUNS_NO);
  197. //deviceStatus.setGunStatus(StatusConstant.OFFLINE);
  198. deviceStatus.setOnlineStatus(DeviceOnlineStatus.OFFLINE);
  199. deviceStatus.setUpdateTime(System.currentTimeMillis());
  200. deviceStatusService.updateById(deviceStatus);
  201. if (socketHandle.existDeviceConnection(deviceStatus.getPileCode())) {
  202. String pilecode = deviceStatus.getPileCode();
  203. DeviceConnectionMsg deviceConnection = socketHandle.getDeviceConnection(pilecode);
  204. byte[] transactionNum = new byte[16]; //FrameDataSplicing.transactionNum(pilecode, deviceConnection.getMessageCount());
  205. if (deviceStatus.getGunStatus() == PortStatusConstant.EMERGENCY_STOP) {
  206. deviceStatus.setGunStatus(StatusConstant.FREE);
  207. }
  208. realTimeStatusPushFrame.deviceStatusPush(deviceConnection, transactionNum, pilecode, (byte) deviceStatus.getGunPort(), StatusConstant.OFFLINE, deviceStatus.getInsertGunStatus(), 0, 0, zero, zero, 0);
  209. socketHandle.removeDeviceConnection(deviceStatus.getPileCode());
  210. redisCache.deleteObject(RedisConstant.DEVICE_PORT_STATUS + imei);
  211. }
  212. }
  213. }
  214. }
  215. private void checkNoPowerAutoStop(int power, String imei, int portId) {
  216. try {
  217. String hkey = imei + "_" + portId;
  218. Integer lastPower0Times = 0;
  219. if (power > 0) {
  220. } else {
  221. lastPower0Times = redisCache.getCacheMapValue(RedisConstant.POWER_ZERO_TIMES, hkey);
  222. if (lastPower0Times == null) {
  223. lastPower0Times = 0;
  224. }
  225. lastPower0Times = lastPower0Times + 1;
  226. }
  227. redisCache.setCacheMapValue(RedisConstant.POWER_ZERO_TIMES, hkey, lastPower0Times);
  228. if (lastPower0Times < 5) {
  229. return;
  230. }
  231. //查找订单开始时间 如果开始时间过过2分钟 且连续power为0 就需要停止充电
  232. QueryWrapper<OrderStatus> orderStatusQueryWrapper = new QueryWrapper<>();
  233. orderStatusQueryWrapper.eq("device_imei", imei).eq("guns_code", portId).orderByDesc("create_time").last("limit 1");
  234. OrderStatus one = orderStatusService.getOne(orderStatusQueryWrapper);
  235. if (one.getNowOrderStatus() != StatusConstant.NOW_ORDER_STATUS_CHARGING) {
  236. return;
  237. }
  238. if ((System.currentTimeMillis() - one.getCreateTime()) < 120 * 1000) {
  239. return;
  240. }
  241. logger.info("{}-{}触发无功率自停{}", imei, portId, lastPower0Times);
  242. //连续3次功率0 就要停止充电
  243. RpcResult rpcResult = deviceControlerService.stopCharge(imei, imei, (int) portId);
  244. } catch (Exception e) {
  245. logger.error("无功率检测异常{}", e.getMessage());
  246. e.printStackTrace();
  247. }
  248. }
  249. public boolean checkConnection(String pileCode, String imei) throws IOException {
  250. boolean needLogin = false;
  251. if (!socketHandle.existDeviceConnection(pileCode)) {
  252. needLogin = true;
  253. } else {
  254. DeviceConnectionMsg deviceConnection = socketHandle.getDeviceConnection(pileCode);
  255. if (!deviceConnection.getSocket().isConnected()) {
  256. socketHandle.removeDeviceConnection(pileCode);
  257. needLogin = true;
  258. }
  259. if(deviceConnection.getLoginStatus()== 0 && deviceConnection.getLoginTime()>0 && (System.currentTimeMillis()-deviceConnection.getLoginTime())>60*1000){
  260. logger.info("check未应答重新登录{}",deviceConnection);
  261. needLogin = true;
  262. }
  263. }
  264. if (!needLogin) {
  265. return true;
  266. }
  267. logger.info("桩上线{}", imei);
  268. QueryWrapper<Device> deviceQueryWrapper = new QueryWrapper<>();
  269. deviceQueryWrapper.eq("pile_code", pileCode).eq("disabled", DeviceOnlineStatus.NORMAL);
  270. Device device = deviceService.getOne(deviceQueryWrapper);
  271. if (device == null) {
  272. logger.info("{}已禁用{}", imei, pileCode);
  273. return false;
  274. }
  275. boolean res = socketHandle.addDeviceConnection(device.getIp(), device.getPort(), device.getPileCode(), device.getDeviceImei(), device.getDeviceSn(), device.getCommProtocolVer(),device.getPileType());
  276. try{
  277. Thread.sleep(500);
  278. loginFrame.loginMsgSend(socketHandle.getDeviceConnection(device.getPileCode()), device);
  279. }catch (Exception e){
  280. }
  281. return false;
  282. }
  283. /**
  284. * 设备状态按照设备上报和设备心跳上送时间校验修改,这里就必须更新状态的修改时间;通过定时任务判断在线设备接收心跳包超10分钟改为离线
  285. *
  286. * @param jsonObject
  287. */
  288. private void handleDeviceMsg(JSONObject jsonObject, String pileCode) throws Exception {
  289. String imei = jsonObject.getString("imei");
  290. Integer cmd = jsonObject.getInteger("cmd");
  291. if (!jsonObject.containsKey("type")) {
  292. //TODO:离线判断:设备上报+?设备心跳时间校验?
  293. //没有type但是cmd指令是离线时37896=========
  294. if (cmd == 37896) {
  295. //处理离线消息
  296. handleOffline(imei);
  297. }
  298. return;
  299. }
  300. try {
  301. checkConnection(pileCode, imei);
  302. } catch (Exception e) {
  303. logger.info("桩{}连接异常", imei);
  304. }
  305. Integer type = jsonObject.getInteger("type");
  306. if (!NormalChargeConstant.CMD_SET_MAINBOARD.equals(cmd)) {
  307. // logger.error("不支持的命令");
  308. return;
  309. }
  310. if (NormalChargeConstant.KEY_PORT_DETAIL_EXTEND.equals(type)) {
  311. //163 解析
  312. handle163(jsonObject,imei,pileCode);
  313. return;
  314. }
  315. //端口状态
  316. if (NormalChargeConstant.KEY_PORT_DETAIL.equals(type)) {
  317. handle103(jsonObject, imei, type);
  318. return;
  319. }
  320. if (NormalChargeConstant.PORT_STATUS.equals(type)) {
  321. //116端口详情也会变化
  322. JSONArray data = jsonObject.getJSONArray("data");
  323. checkPort(data.getInteger(4), data.getInteger(3), imei, type);
  324. return;
  325. }
  326. //指定端口状态
  327. if (NormalChargeConstant.KEY_PORT_STATUS.equals(type)) {
  328. handle101(jsonObject, imei, type);
  329. return;
  330. }
  331. //104消息启动充电
  332. if (NormalChargeConstant.KEY_STARTCHARGE.equals(type)) {
  333. handle104(jsonObject, imei);
  334. return;
  335. }
  336. //结束充电
  337. if (NormalChargeConstant.KEY_END_NOTICE.equals(type)) {
  338. handle113(jsonObject, imei);
  339. return;
  340. }
  341. //TODO:设备状态的修改这里进行监听变化 ,??
  342. // 1.设备消息cmd:75960设备上报消息是的命令,只要设备报的不是离线当做设备在线
  343. // 2.设备上报指令后根据type类型来分类处理消息包括:设备设为在线 是否插枪状态 枪状态(端口状态)
  344. if (NormalChargeConstant.EMERGENCY_STOP_CHARGING.equals(type)) {
  345. handleEmergency(jsonObject, imei);
  346. return;
  347. }
  348. if (NormalChargeConstant.REPORT_PORT_STATUS.equals(type)) {
  349. //114设备主动上报
  350. JSONArray data = jsonObject.getJSONArray("data");
  351. Integer integer = data.getInteger(2);
  352. if (integer > 5) {
  353. //双枪
  354. checkPort(data.getInteger(7), 1, imei, type);
  355. checkPort(data.getInteger(8), 2, imei, type);
  356. } else {
  357. checkPort(data.getInteger(7), 1, imei, type);
  358. }
  359. }
  360. }
  361. //生产上根本进不来 不考虑 临时调试ykc上报急停状态
  362. private void handleEmergency(JSONObject jsonObject, String imei) throws Exception {
  363. //急停停充
  364. JSONArray data = jsonObject.getJSONArray("data");
  365. int port = data.getInteger(2);
  366. int status = data.getInteger(3);
  367. //关闭急停不处理
  368. if(status==0){
  369. logger.info("关闭急停不处理{}", imei);
  370. return;
  371. }
  372. QueryWrapper<OrderStatus> orderStatusQueryWrapper = new QueryWrapper<>();
  373. orderStatusQueryWrapper.eq("device_imei", imei)
  374. .eq("guns_code", port)
  375. .orderByDesc("create_time"
  376. ).last("limit 1");
  377. OrderStatus statusServiceOne = orderStatusService.getOne(orderStatusQueryWrapper);
  378. if (statusServiceOne == null) {
  379. logger.info("没有急停待处理订单{}", imei);
  380. deviceControlerService.sendImeiDetail(imei);
  381. return;
  382. }
  383. if (statusServiceOne.getTransactionOrderReplyStatus() == StatusConstant.TRANSACTION_ORDER_REPLY_STATUS_SUCC) {
  384. logger.info("订单状态已上报成功{},id:{}", imei, statusServiceOne.getId());
  385. deviceControlerService.sendImeiDetail(imei);
  386. return;
  387. }
  388. statusServiceOne.setReasonStopCharging(TransConstant.EMERGENCY_STOP_EXCEPTION_STOP);
  389. statusServiceOne.setEndTime(System.currentTimeMillis());
  390. orderStatusService.updateById(statusServiceOne);
  391. logger.info(imei+ ":急停停充关闭充电>>>");
  392. deviceControlerService.stopCharge(imei, imei, port);
  393. // //查询计费模板
  394. // QueryWrapper<BillingModel> billingModelQueryWrapper = new QueryWrapper<>();
  395. // billingModelQueryWrapper.eq("device_imei", imei);
  396. // BillingModel model = billingModelService.getOne(billingModelQueryWrapper);
  397. //
  398. // orderStatusQueryWrapper.eq("device_imei", imei)
  399. // .eq("guns_code", port)
  400. // .orderByDesc("create_time"
  401. // ).last("limit 1");
  402. // OrderStatus statusServiceOne = orderStatusService.getOne(orderStatusQueryWrapper);
  403. // statusServiceOne.setEndTime(System.currentTimeMillis());
  404. // DeviceConnectionMsg deviceConnection = socketHandle.getDeviceConnection(statusServiceOne.getPileCode());
  405. //
  406. // if (status == 1) {
  407. // logger.info(statusServiceOne.getPileCode() + ":急停停充>>>上报交易记录>>>");
  408. // byte[] encrypt = new byte[0];
  409. // if (port == 1) {
  410. // //急停停充:急停状态下:1.向设备发起结束充电,结算交易订单(交给结束充电处理;但是要考虑是急停的原因),2.上报的充电结束的订单式
  411. //
  412. // Map<String, BigDecimal> map = transMoney.compute(1, model, statusServiceOne.getCreateTime(), statusServiceOne.getEndTime());
  413. //
  414. // encrypt = transactionFlowPushFrame.sendTrans(deviceConnection, statusServiceOne.getTransOrder(), statusServiceOne.getPileCode(), (byte) 1, statusServiceOne.getCreateTime(), statusServiceOne.getEndTime(), model, statusServiceOne.getCard(), map, TransConstant.EMERGENCY_STOP_EXCEPTION_STOP);
  415. // } else if (port == 2) {
  416. // //TODO:这里还是模拟数据上报
  417. //
  418. // Map<String, BigDecimal> map = transMoney.compute(2, model, statusServiceOne.getCreateTime(), statusServiceOne.getEndTime());
  419. // //模拟3.5千瓦
  420. // encrypt = transactionFlowPushFrame.sendTrans(deviceConnection, statusServiceOne.getTransOrder(), statusServiceOne.getPileCode(), (byte) 2, statusServiceOne.getCreateTime(), statusServiceOne.getEndTime(), model, statusServiceOne.getCard(), map, TransConstant.EMERGENCY_STOP_EXCEPTION_STOP);
  421. // }
  422. // statusServiceOne.setOriginalText(encrypt);
  423. // statusServiceOne.setReasonStopCharging(TransConstant.EMERGENCY_STOP_EXCEPTION_STOP);
  424. // statusServiceOne.setStopChargingReply(StatusConstant.STOP_CHARGING_REPLY_OK);
  425. // statusServiceOne.setNowOrderStatus(StatusConstant.NOW_ORDER_STATUS_CHARGING_ENDING);
  426. // statusServiceOne.setTransactionOrderReportingActionStatus(StatusConstant.TRANSACTION_ORDER_REPORTING_ACTION_STATUS_OK);
  427. // orderStatusService.updateById(statusServiceOne);
  428. // }
  429. }
  430. //启动充电
  431. private void handle104(JSONObject jsonObject, String imei) {
  432. //开启充电设备上报结果
  433. JSONObject data = jsonObject.getJSONObject("real_data");
  434. Integer result = data.getInteger("result");
  435. Integer port = data.getInteger("port");
  436. QueryWrapper<OrderStatus> orderStatusQueryWrapper = new QueryWrapper<>();
  437. orderStatusQueryWrapper.eq("device_imei", imei).eq("guns_code", port).orderByDesc("create_time").last("limit 1");
  438. OrderStatus statusServiceOne = orderStatusService.getOne(orderStatusQueryWrapper);
  439. if(statusServiceOne==null){
  440. logger.info("没有充电记录 其他方式启动{}", imei);
  441. deviceControlerService.sendImeiDetail(imei);
  442. return;
  443. }
  444. if(statusServiceOne.getNowOrderStatus()== StatusConstant.NOW_ORDER_STATUS_CHARGING_ENDING){
  445. logger.info("订单已结束 无待上报订单{}", imei);
  446. deviceControlerService.sendImeiDetail(imei);
  447. return;
  448. }
  449. byte[] bytes = statusServiceOne.getTransOrder();
  450. logger.info(statusServiceOne.getPileCode() + ":设备开启充电流水号:" + DataConversion.bytesToHexString(bytes));
  451. DeviceConnectionMsg deviceConnection = socketHandle.getDeviceConnection(statusServiceOne.getPileCode());
  452. int reson = 0x00;
  453. if (result == 0x01) {
  454. //启充成功上报充电开启成功
  455. charngingPushFrame.startStatus(deviceConnection, bytes, port, result, 0x00);
  456. logger.info("上报启动充电成功{},{}", statusServiceOne.getId(), statusServiceOne.getPileCode());
  457. } else {
  458. //启机不成功,根据设备状态判断,并且要结束充电并上报订单
  459. String cacheKey;
  460. if (port == 1) {
  461. cacheKey = RedisConstant.ONLINE_DEVICE_ONE;
  462. } else {
  463. cacheKey = RedisConstant.ONLINE_DEVICE_TWO;
  464. }
  465. if (redisCache.hasKey(cacheKey)) {
  466. DeviceStatus oneStatus = redisCache.getCacheMapValue(cacheKey, statusServiceOne.getPileCode());
  467. if (StatusConstant.FAULT == oneStatus.getGunStatus()) {
  468. reson = 0x03;
  469. } else if (StatusConstant.OFFLINE == oneStatus.getGunStatus()) {
  470. reson = 0x04;
  471. } else if (StatusConstant.CHARGING == oneStatus.getGunStatus()) {
  472. reson = 0x02;
  473. }
  474. charngingPushFrame.startStatus(deviceConnection, bytes, port, result, reson);
  475. logger.info("上报启动充电失败{},{}", statusServiceOne.getId(), statusServiceOne.getPileCode());
  476. }
  477. }
  478. new Thread(() -> {
  479. try {
  480. Thread.sleep(4000); // 延迟 5 秒
  481. DeviceParam dataParam = new DeviceParam();
  482. dataParam.setDeviceId(imei);
  483. dataParam.setCcid(imei);
  484. deviceControlerService.sendPortDetailCmd(dataParam);
  485. logger.info(statusServiceOne.getPileCode() + ":延迟主动下发103消息" + imei);
  486. } catch (Exception e) {
  487. logger.info(statusServiceOne.getPileCode() + ":延迟主动下发103消息异常" + e.getMessage() + imei);
  488. }
  489. }).start();
  490. }
  491. //单个端口状态
  492. private void handle101(JSONObject jsonObject, String imei, int type) {
  493. try {
  494. //状态查询101
  495. JSONObject data = jsonObject.getJSONObject("real_data");
  496. Integer port_first_status = data.getInteger("port_first_status");
  497. Integer port_second_status = data.getInteger("port_second_status");
  498. if (port_first_status != null) {
  499. checkPort(port_first_status, 1, imei, type);
  500. }
  501. if (port_second_status != null) {
  502. checkPort(port_second_status, 2, imei, type);
  503. }
  504. } catch (Exception e) {
  505. logger.info("处理101失败{}", imei);
  506. }
  507. }
  508. //单个端口状态
  509. private void handle163(JSONObject jsonObject, String imei, String pileCode) {
  510. try {
  511. //状态查询101
  512. JSONArray dataArray = jsonObject.getJSONArray("data");
  513. //设置订单已停止充电和结束时间
  514. Integer port = (Integer) dataArray.get(3);
  515. redisCache.setCacheMapValue("device_last_163",imei+"_"+port,dataArray);
  516. } catch (Exception e) {
  517. logger.info("处理163失败{}", imei);
  518. }
  519. }
  520. private void handle103(JSONObject jsonObject, String imei, int type) throws Exception {
  521. //103状态是带电压功率等信息的,所以需要对该信息进行处理操作
  522. JSONObject data = jsonObject.getJSONObject("real_data");
  523. Integer port_first_status = data.getInteger("port_first_status");
  524. Integer port_second_status = data.getInteger("port_second_status");
  525. //功率为0时,还是充电中状态,将状态转换成空闲,结束充电
  526. // 20240608现场使用时出现充电状态第一次103上来就是power是0情况
  527. // if (port_first_status != null&&power==0&&port_first_status==PortStatusConstant.CHARGING){
  528. // port_first_status=PortStatusConstant.FREE;
  529. // }
  530. // if (port_second_status != null&&power==0&&port_second_status==PortStatusConstant.CHARGING){
  531. // port_second_status=PortStatusConstant.FREE;
  532. // }
  533. //判断连续无功率就自动停止
  534. redisCache.setCacheObject(RedisConstant.DEVICE_PORT_STATUS + imei, data, 60, TimeUnit.MINUTES);
  535. if (port_first_status != null) {
  536. checkPort(port_first_status, 1, imei, type);
  537. if (port_first_status == PortStatusConstant.CHARGING) {
  538. Integer power = data.getInteger("power");
  539. checkNoPowerAutoStop(power, imei, 1);
  540. }
  541. }
  542. if (port_second_status != null) {
  543. checkPort(port_second_status, 2, imei, type);
  544. if (port_second_status == PortStatusConstant.CHARGING) {
  545. Integer power = data.getInteger("power_1");
  546. checkNoPowerAutoStop(power, imei, 2);
  547. }
  548. }
  549. }
  550. //处理停止充电情况
  551. private void handle113(JSONObject jsonObject, String imei) {
  552. //停止充电通知触发情况:1.急停,收到停充时主动要去发停充,所以这里不能处理急停的交易订单;2.手动停充,正常的远程停止指令
  553. // 1.设备已经在接收到云快充指令的时候进行了停充操作,2.结算订单,上报云快充停止回复
  554. try {
  555. JSONObject data = jsonObject.getJSONObject("real_data");
  556. logger.info("{}接收到设备上送113停止充电msg>>" + jsonObject.toString(), imei);
  557. int port = data.getIntValue("port");
  558. byte reson = data.getByte("reason");
  559. QueryWrapper<OrderStatus> orderStatusQueryWrapper = new QueryWrapper<>();
  560. orderStatusQueryWrapper.eq("device_imei", imei).eq("guns_code", port).orderByDesc("create_time").last("limit 1");
  561. OrderStatus statusServiceOne = orderStatusService.getOne(orderStatusQueryWrapper);
  562. if (statusServiceOne == null) {
  563. logger.info("没有待处理订单{}", imei);
  564. deviceControlerService.sendImeiDetail(imei);
  565. return;
  566. }
  567. if (statusServiceOne.getTransactionOrderReplyStatus() == StatusConstant.TRANSACTION_ORDER_REPLY_STATUS_SUCC) {
  568. logger.info("订单状态已上报成功{},id:{}", imei, statusServiceOne.getId());
  569. deviceControlerService.sendImeiDetail(imei);
  570. return;
  571. }
  572. //如果是用户手动停止充电 则不处理状态
  573. if (statusServiceOne.getReasonStopCharging() == TransConstant.APP_REMOTE_STOP) {
  574. logger.info(statusServiceOne.getPileCode() + ":云快充>>>>>>远程停充>>>>");
  575. } else if(statusServiceOne.getReasonStopCharging()==TransConstant.EMERGENCY_STOP_EXCEPTION_STOP){
  576. logger.info(statusServiceOne.getPileCode() + ":云快充>>>>>>急停停止>>>>");
  577. } else if(statusServiceOne.getReasonStopCharging()==TransConstant.SOC_FULL_OF_STOP){
  578. logger.info(statusServiceOne.getPileCode() + ":云快充>>>>>>设备充电充满>>>>");
  579. } else if(statusServiceOne.getReasonStopCharging()==TransConstant.INSUFFICIENT_BALANCE_EXCEPTION_STOP){
  580. logger.info(statusServiceOne.getPileCode() + ":云快充>>>>>>设备充电充满>>>>");
  581. }else {
  582. if(statusServiceOne.getReasonStopCharging()==0){
  583. logger.info(statusServiceOne.getPileCode() + ":充满主动>>>>>>停充>>>>");
  584. statusServiceOne.setReasonStopCharging(TransConstant.MANUAL_STOP);
  585. }else{
  586. //不处理急停
  587. if (reson == 0x01) {
  588. logger.info(statusServiceOne.getPileCode() + ":用户主动停充>>>>>>停充>>>>");
  589. statusServiceOne.setReasonStopCharging(TransConstant.APP_REMOTE_STOP);
  590. } else if (reson == 0x00) {
  591. logger.info(statusServiceOne.getPileCode() + ":设备余额不足>>>>>>停充>>>>");
  592. statusServiceOne.setReasonStopCharging(TransConstant.INSUFFICIENT_BALANCE_EXCEPTION_STOP);
  593. } else if (reson == 0x03) {
  594. logger.info(statusServiceOne.getPileCode() + ":设备充电充满>>>>>>停充>>>>");
  595. statusServiceOne.setReasonStopCharging(TransConstant.SOC_FULL_OF_STOP);
  596. } else {
  597. logger.info(statusServiceOne.getPileCode() + ":设备充电停止>>>>其他>>>");
  598. statusServiceOne.setReasonStopCharging(TransConstant.OTHER_STOP);
  599. }
  600. }
  601. }
  602. //设置订单已停止充电和结束时间
  603. statusServiceOne.setEndTime(System.currentTimeMillis());
  604. statusServiceOne.setNowOrderStatus(StatusConstant.NOW_ORDER_STATUS_CHARGING_ENDING);
  605. DeviceConnectionMsg deviceConnection = socketHandle.getDeviceConnection(statusServiceOne.getPileCode());
  606. if (deviceConnection == null || deviceConnection.getLoginStatus() != 1) {
  607. //未上报
  608. statusServiceOne.setTransactionOrderReportingActionStatus(StatusConstant.TRANSACTION_ORDER_REPORTING_ACTION_STATUS_NO);
  609. logger.info("socket 未连接 需要重新上报异常上报{}", statusServiceOne.getPileCode());
  610. orderStatusService.updateById(statusServiceOne);
  611. return;
  612. }
  613. int endElec = data.getIntValue("elec");
  614. byte[] encrypt = new byte[0];
  615. //查询计费模板
  616. QueryWrapper<BillingModel> billingModelQueryWrapper = new QueryWrapper<>();
  617. billingModelQueryWrapper.eq("device_imei", imei);
  618. BillingModel model = billingModelService.getOne(billingModelQueryWrapper);
  619. Map<String, BigDecimal> map = transMoney.compute(port, model, statusServiceOne.getCreateTime(), statusServiceOne.getEndTime(),statusServiceOne,endElec);
  620. logger.info(statusServiceOne.getPileCode() + "计算电费,{},{}" + DataConversion.bytesToHexString(statusServiceOne.getTransOrder()),map.get("money"),map.get("elec"));
  621. encrypt = transactionFlowPushFrame.sendTrans(deviceConnection, statusServiceOne.getTransOrder(), statusServiceOne.getPileCode(), statusServiceOne.getGunsCode(), statusServiceOne.getCreateTime(), statusServiceOne.getEndTime(), model, statusServiceOne.getCard(), map, statusServiceOne.getReasonStopCharging());
  622. if (encrypt == null || encrypt.length <= 0) {
  623. logger.info("订单上送消息异常 需要重新上报{}", statusServiceOne.getPileCode());
  624. orderStatusService.updateById(statusServiceOne);
  625. return;
  626. } else {
  627. logger.info("订单上送成功{}", statusServiceOne.getPileCode());
  628. statusServiceOne.setTransactionOrderReportingActionStatus(StatusConstant.TRANSACTION_ORDER_REPORTING_ACTION_STATUS_OK);
  629. statusServiceOne.setOriginalText(encrypt);
  630. }
  631. boolean res = charngingPushFrame.endStatus(deviceConnection, port, 0x01, 0x00);
  632. if (res) {
  633. //更新远程停止充电
  634. logger.info("停止充电回复成功{}", imei);
  635. statusServiceOne.setStopChargingReply(StatusConstant.STOP_CHARGING_REPLY_OK);
  636. } else {
  637. logger.info("停止充电回复失败{}", imei);
  638. }
  639. orderStatusService.updateById(statusServiceOne);
  640. // //获取一设备状态
  641. // DeviceParam dataParam = new DeviceParam();
  642. // dataParam.setDeviceId(imei);
  643. // dataParam.setCcid(imei);
  644. // realTimeStatusPushFrame.deviceStatusPush(deviceConnection, FrameDataSplicing.transactionNum(deviceConnection.getDeviceId(), deviceConnection.getMessageCount()), deviceConnection.getDeviceId(), (byte) 1, StatusConstant.FREE, StatusConstant.CHARGING_INIT_STATUS_OK, 0, 0, zero, zero, 0);
  645. deviceControlerService.sendImeiDetail(deviceConnection.getImei());
  646. } catch (Exception e) {
  647. logger.info("{}处理113消息异常{}", imei, e.getMessage());
  648. // DeviceConnectionMsg deviceConnection = socketHandle.getDeviceConnection(imei);
  649. // realTimeStatusPushFrame.deviceStatusPush(deviceConnection, FrameDataSplicing.transactionNum(deviceConnection.getDeviceId(), deviceConnection.getMessageCount()), deviceConnection.getDeviceId(), (byte) 1, StatusConstant.FREE, StatusConstant.CHARGING_INIT_STATUS_OK, 0, 0, zero, zero, 0);
  650. e.printStackTrace();
  651. }
  652. }
  653. /**
  654. * 设备端口状态转成云快充识别状态
  655. *
  656. * @param portStatus
  657. * @param port
  658. * @param imei
  659. */
  660. private void checkPort(Integer portStatus, int port, String imei, int type) throws Exception {
  661. //交流桩101port_second_status解析不对忽略
  662. if(portStatus>20){
  663. return;
  664. }
  665. //端口可能干扰导致为错误的端口
  666. if(port>2){
  667. return;
  668. }
  669. if (portStatus.equals(PortStatusConstant.FREE)) {
  670. //处理特殊情况之后还要看枪状态变位上送
  671. deviceOnline(portStatus, imei, port, StatusConstant.FREE, StatusConstant.INSERT_GUNS_NO);
  672. return;
  673. }
  674. if (portStatus.equals(PortStatusConstant.CHARGING)) {
  675. deviceOnline(portStatus, imei, port, StatusConstant.CHARGING, StatusConstant.INSERT_GUNS_YES);
  676. return;
  677. }
  678. if (portStatus.equals(PortStatusConstant.DISABLED) || portStatus.equals(PortStatusConstant.FAULT)) {
  679. //禁用或故障上报云快充为故障信息
  680. deviceOnline(portStatus, imei, port, StatusConstant.FAULT, StatusConstant.NO);
  681. return;
  682. }
  683. if (portStatus.equals(PortStatusConstant.INSERT_GUN) || portStatus.equals(PortStatusConstant.BOOKED)) {
  684. deviceOnline(portStatus, imei, port, StatusConstant.FREE, StatusConstant.INSERT_GUNS_YES);
  685. return;
  686. }
  687. if (portStatus.equals(PortStatusConstant.CHARGING_END)) {
  688. //7状态的时候 充满停止以后 认为未插枪 不允许充电 因为启动不了,必须要重新拔枪
  689. deviceOnline(portStatus, imei, port, (byte) StatusConstant.FREE, StatusConstant.INSERT_GUNS_NO);
  690. return;
  691. }
  692. if (portStatus.equals(PortStatusConstant.EMERGENCY_STOP)) {
  693. //急停中按要求需要上报空闲状态;急停保存原始状态
  694. deviceOnline(portStatus, imei, port, (byte) StatusConstant.FAULT, StatusConstant.INSERT_GUNS_NO);
  695. }
  696. }
  697. /**
  698. * 1.这里接收到消息就是设备在线;2.对状态进行处理,不同类型消息的枪状态不同进行落库;3.并且状态变化的一个变位上送
  699. * 枪充满会变成状7 然后必须要拔了再插 才能启动充电
  700. * 但是拔了再插 会短暂的从1 变成5 所以在判断空闲的时候 要加上订单60秒的变位限制 6如果有订单60秒后才关闭
  701. * @param imei 设备imei码
  702. * @param port 设备port(枪号)
  703. * @param gunsStatus 枪状态
  704. */
  705. private void deviceOnline(int portStatus, String imei, int port, byte gunsStatus, byte insertGunStatus) throws Exception {
  706. QueryWrapper<DeviceStatus> deviceStatusQueryWrapper = new QueryWrapper<>();
  707. deviceStatusQueryWrapper.eq("device_imei", imei).eq("gun_port", port);
  708. DeviceStatus statusServiceOne = deviceStatusService.getOne(deviceStatusQueryWrapper);
  709. DeviceStatus statusServiceOneTemp = new DeviceStatus();
  710. if(statusServiceOne!=null && insertGunStatus == StatusConstant.INSERT_GUNS_YES){
  711. String waitingKey = RedisConstant.WAITING_INSERT_GUN+":"+statusServiceOne.getPileCode()+"_"+statusServiceOne.getGunPort();
  712. if (redisCache.hasKey(waitingKey)) {
  713. //未插枪启充的操作会保存订单,但是订单号不是因为断网中停充造成的订单结束原因是0,所以redis有当前设备的订单值,就不是结束充电
  714. int waitingId = redisCache.getCacheObject(waitingKey);
  715. //启动充电
  716. QueryWrapper<OrderStatus> orderStatusQueryWrapper = new QueryWrapper<>();
  717. orderStatusQueryWrapper.eq("device_imei", imei).eq("guns_code", port).orderByDesc("create_time").last("limit 1");
  718. OrderStatus waitingOrder = orderStatusService.getOne(orderStatusQueryWrapper);
  719. if(waitingOrder!= null && waitingOrder.getId()==waitingId && waitingOrder.getNowOrderStatus()==StatusConstant.NOW_ORDER_STATUS_CHARGING){
  720. logger.info("订单{}已就绪启动充电{}-{}",waitingOrder.getId(),waitingOrder.getPileCode(),waitingOrder.getGunsCode());
  721. deviceControlerService.startCharge(waitingOrder.getDeviceImei(), waitingOrder.getDeviceImei(), (int) waitingOrder.getGunsCode(),0);
  722. redisCache.deleteObject(waitingKey);
  723. return;
  724. }
  725. }
  726. }
  727. //创建设备端口号
  728. if (statusServiceOne != null) {
  729. BeanUtils.copyProperties(statusServiceOne, statusServiceOneTemp);
  730. } else {
  731. //禁用的设备不再上线,只看正常设备
  732. QueryWrapper<Device> deviceQueryWrapper = new QueryWrapper<>();
  733. QueryWrapper<Device> device_imei = deviceQueryWrapper.eq("device_imei", imei).eq("disabled", DeviceOnlineStatus.NORMAL);
  734. Device one = deviceService.getOne(device_imei);
  735. if (one == null) {
  736. logger.info("当前设备imei:" + imei + ",没有绑定ykc桩编码!!!!!!!!!!!!!!!!!!");
  737. return;
  738. }
  739. statusServiceOne = new DeviceStatus();
  740. statusServiceOne.setDeviceImei(imei);
  741. statusServiceOne.setDeviceSn(one.getDeviceSn());
  742. statusServiceOne.setPileCode(one.getPileCode());
  743. statusServiceOne.setGunPort((byte) port);
  744. statusServiceOne.setCreateTime(System.currentTimeMillis());
  745. statusServiceOne.setUpdateTime(System.currentTimeMillis());
  746. statusServiceOne.setOnlineStatus(DeviceOnlineStatus.ONLINE);
  747. statusServiceOne.setPortStatus(portStatus);
  748. deviceStatusService.saveOrUpdate(statusServiceOne);
  749. }
  750. statusServiceOne.setPortStatus(portStatus);
  751. statusServiceOne.setGunStatus(gunsStatus);
  752. statusServiceOne.setInsertGunStatus(insertGunStatus);
  753. statusServiceOne.setOnlineStatus(DeviceOnlineStatus.ONLINE);
  754. statusServiceOne.setUpdateTime(System.currentTimeMillis());
  755. deviceStatusService.updateById(statusServiceOne);
  756. logger.info("{}save>>>" + statusServiceOne.toString(), imei);
  757. redisCache.setCacheMapValue(port == 1 ? RedisConstant.ONLINE_DEVICE_ONE : RedisConstant.ONLINE_DEVICE_TWO, statusServiceOne.getPileCode(), statusServiceOne);
  758. //为啥要过期20分
  759. redisCache.expire(port == 1 ? RedisConstant.ONLINE_DEVICE_ONE : RedisConstant.ONLINE_DEVICE_TWO, 60 * 1001 * 60*24, TimeUnit.MILLISECONDS);
  760. DeviceConnectionMsg deviceConnectionMsg = socketHandle.getDeviceConnection(statusServiceOne.getPileCode());
  761. if (deviceConnectionMsg == null || deviceConnectionMsg.getLoginStatus() != Constant.DEVICE_LOGIN_STATUS) {
  762. //下线
  763. logger.info("设备{}未登录成功不上报", statusServiceOne.getDeviceImei());
  764. if(deviceConnectionMsg!=null && deviceConnectionMsg.getLoginTime()>0 && (System.currentTimeMillis()-deviceConnectionMsg.getLoginTime())>30*1000){
  765. //调用重启
  766. try{
  767. logger.info("超过30秒设备{}重新上线", statusServiceOne.getDeviceImei());
  768. String url = "http://127.0.0.1:8063/api/device/restLogin/"+statusServiceOne.getPileCode();
  769. HttpResponse execute = HttpRequest.post(url)
  770. .timeout(3000)
  771. .execute();
  772. String body = execute.body();
  773. System.out.println("reset login body:>>>"+body);
  774. } catch (Exception ex) {
  775. System.out.println("reset error :>>>"+ex.toString());
  776. }
  777. }
  778. return;
  779. }
  780. QueryWrapper<OrderStatus> orderStatusQueryWrapper = new QueryWrapper<>();
  781. orderStatusQueryWrapper.eq("device_imei", imei).eq("guns_code", port).orderByDesc("create_time").last("limit 1");
  782. OrderStatus one = orderStatusService.getOne(orderStatusQueryWrapper);
  783. //没有充电中的订单
  784. if (one == null || one.getNowOrderStatus() != StatusConstant.NOW_ORDER_STATUS_CHARGING) {
  785. logger.info("free{}", imei);
  786. realTimeStatusPushFrame.deviceStatusPush(deviceConnectionMsg, FrameDataSplicing.transactionNum(null, 0), statusServiceOne.getPileCode(), (byte) port, gunsStatus, insertGunStatus, 0, 0, zero, zero, 0);
  787. return;
  788. }
  789. //充电中
  790. if (portStatus == PortStatusConstant.CHARGING) {
  791. byte[] transactionNum = one.getTransOrder();
  792. if (one.getChargingInitStatus() == StatusConstant.CHARGING_INIT_STATUS_NO) {
  793. logger.info("{}变位为充电中且当前订单还没首次上报过初始状态:" + DataConversion.bytesToHexString(transactionNum), imei);
  794. realTimeStatusPushFrame.deviceStatusPush(deviceConnectionMsg, transactionNum, statusServiceOneTemp.getPileCode(), (byte) port, gunsStatus, insertGunStatus, 0, 0, zero, zero, 0);
  795. //这里上报开始充电初始化状态并记录已经上报首次状态
  796. one.setChargingInitStatus(StatusConstant.CHARGING_INIT_STATUS_OK);
  797. orderStatusService.updateById(one);
  798. }
  799. return;
  800. }
  801. //充电结束
  802. if (portStatus == PortStatusConstant.CHARGING_END) {
  803. //7状态小于30秒内且订单原因不是远程停充
  804. if (one.getNowOrderStatus() == StatusConstant.NOW_ORDER_STATUS_CHARGING) {
  805. if ((System.currentTimeMillis() - one.getCreateTime()) < 60 * 1000 && one.getReasonStopCharging() != TransConstant.APP_REMOTE_STOP) {
  806. logger.info("下订单60秒内{}不处理7状态", one.getPileCode());
  807. return;
  808. }
  809. //充电已完成
  810. //发送结束充电命令 顺利的话113会收到 状态还是7
  811. logger.info("下订单60秒后{}仍然处于7状态发送止充电指令", one.getPileCode());
  812. //标记订单为已停充 标记为未上送
  813. one.setNowOrderStatus(StatusConstant.NOW_ORDER_STATUS_CHARGING_ENDING);
  814. one.setEndTime(System.currentTimeMillis());
  815. one.setReasonStopCharging(TransConstant.SOC_FULL_OF_STOP);
  816. orderStatusService.updateById(one);
  817. RpcResult rpcResult = deviceControlerService.stopCharge(imei, imei, port);
  818. return;
  819. }
  820. return;
  821. }
  822. //先拔 再插
  823. //订单还在充电中 但是枪不在充电中状态 就结束订单
  824. // 但是拔了再插 会短暂的从1 变成5 所以在判断空闲的时候 要加上订单60秒的变位限制 6如果有订单60秒后才关闭
  825. if (one.getNowOrderStatus() == StatusConstant.NOW_ORDER_STATUS_CHARGING) {
  826. if ((System.currentTimeMillis() - one.getCreateTime()) < 60 * 1000 && one.getReasonStopCharging() != TransConstant.APP_REMOTE_STOP) {
  827. logger.info("下订单60秒内{}不处理空闲这个状态", one.getPileCode());
  828. return;
  829. }
  830. logger.info("{}枪非充电中状态,结束订单状态 等待任务重试上报订单", one.getPileCode());
  831. one.setNowOrderStatus(StatusConstant.NOW_ORDER_STATUS_CHARGING_ENDING);
  832. one.setEndTime(System.currentTimeMillis());
  833. one.setReasonStopCharging(TransConstant.OTHER_STOP);
  834. orderStatusService.updateById(one);
  835. //再发一次停止充电的指令 避免设备状态变位没有停掉
  836. deviceControlerService.stopCharge(imei, imei, port);
  837. }
  838. logger.info("上传空闲状态{}",imei);
  839. realTimeStatusPushFrame.deviceStatusPush(deviceConnectionMsg, FrameDataSplicing.transactionNum(null, 0), statusServiceOne.getPileCode(), (byte) port, gunsStatus, insertGunStatus, 0, 0, zero, zero, 0);
  840. }
  841. }