DeviceMsgHandle.java 54 KB

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