package com.tmzn.devicelinkykc.message; import cn.hutool.db.sql.Order; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.tmzn.devicelinkykc.constant.Constant; import com.tmzn.devicelinkykc.constant.DeviceOnlineStatus; import com.tmzn.devicelinkykc.constant.PortStatusConstant; import com.tmzn.devicelinkykc.constant.RedisConstant; import com.tmzn.devicelinkykc.constant.ykc.BillingModelConst; import com.tmzn.devicelinkykc.constant.ykc.StatusConstant; import com.tmzn.devicelinkykc.constant.ykc.TransConstant; import com.tmzn.devicelinkykc.entity.*; import com.tmzn.devicelinkykc.frameMsg.DataConversion; import com.tmzn.devicelinkykc.frameMsg.FrameDataSplicing; import com.tmzn.devicelinkykc.frameMsg.TransMoney; import com.tmzn.devicelinkykc.frameMsg.frameType.*; import com.tmzn.devicelinkykc.mapstruct.TransMapping; import com.tmzn.devicelinkykc.msgEnum.YkcSendDevice; import com.tmzn.devicelinkykc.openfeign.MsgService; import com.tmzn.devicelinkykc.openfeign.transdata.DataParam; import com.tmzn.devicelinkykc.openfeign.transdata.RpcResult; import com.tmzn.devicelinkykc.redis.RedisCache; import com.tmzn.devicelinkykc.service.*; import com.tmzn.devicelinkykc.socket.DeviceConnectionMsg; import com.tmzn.devicelinkykc.socket.SocketHandle; //import com.tmzn.devicelinkykc.test.SendMsgToDevice; import com.tmzn.devicelinkykc.transdata.entity.DeviceParam; import com.tmzn.devicelinkykc.transdata.entity.MainBoard; import com.tmzn.devicelinkykc.transdata.entity.opertype.OperEnum; import com.tmzn.devicelinkykc.util.Encrytion; import com.tmzn.devicelinkykc.util.ResultUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.IOException; import java.math.BigDecimal; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * @author xp * @date 2024/3/13 * @explain " " */ @Component public class YkcMsgHandle { private static final Logger logger = LoggerFactory.getLogger(YkcMsgHandle.class); private static final BigDecimal zero = new BigDecimal("0"); @Autowired private RedisCache redisCache; @Autowired private OrderStatusService orderStatusService; @Autowired private DeviceStatusService deviceStatusService; @Autowired private DeviceControlerService deviceControlerService; @Autowired private CheckTime checkTime; @Autowired private BillingModelFrame billingModelFrame; @Autowired private MsgService msgService; @Autowired private BillingModelService billingModelService; @Autowired private RealTimeStatusPushFrame realTimeStatusPushFrame; @Autowired private CharngingPushFrame charngingPushFrame; @Autowired private RemoteBalanceUpdatePushFrame remoteBalanceUpdatePushFrame; @Autowired private TransMoney transMoney; @Autowired private TransactionFlowPushFrame transactionFlowPushFrame; @Autowired private OtherFrame otherFrame; @Autowired private TransOrderService transOrderService; @Autowired private TransMapping transMapping; @Autowired private DeviceService deviceService; public void startListening(DeviceConnectionMsg deviceConnectionMsg) { Runnable listener = () -> { boolean temp = true; while (temp) { // 接收数据帧 byte[] receiveData = new byte[1024]; int length = 0; try { if (deviceConnectionMsg.getSocket().isConnected()) { length = deviceConnectionMsg.getSocket().getInputStream().read(receiveData); } else { logger.info("receiveYKCData socket no>>>>"); } if (length < 0) { return; } } catch (IOException e) { //e.printStackTrace(); String message = e.getMessage(); logger.info(deviceConnectionMsg.getDeviceId() + ":Receive YKC dataMsg IOException !!!!!!!:" + message + "!!!!!!!!" + message + "!!!!!!!!" + message + "!!!!!!!!" + message + "!!!!!!!!"); //异常后操作删除所有的缓存,重新获取 DataParam dataParam = new DataParam(); dataParam.setDeviceId(deviceConnectionMsg.getImei()); dataParam.setCcid(deviceConnectionMsg.getImei()); JSONObject object1 = new JSONObject(); dataParam.setData(object1); dataParam.setType(OperEnum.PortDetail.getType()); msgService.sendMsg(dataParam); temp = false; continue; } byte[] response = new byte[length]; //将接收到的消息类型拿到进行判断 System.arraycopy(receiveData, 0, response, 0, response.length); //String s = Integer.toHexString(response[5] & 0xFF); byte[] fromMsgSeq = {response[2],response[3]}; int framType = response[5] & 0xFF;//Integer.parseInt(s); int encry = response[4] & 0xFF; //消息体 byte[] respone_msg = Arrays.copyOfRange(response, 6, response.length - 2); if (encry == 0) { if(framType!=4){ logger.info("{},un_encry_msg,frame:{},data:{}",deviceConnectionMsg.getDeviceId(),framType, DataConversion.bytesToHexString(response)); } } else { try { String key = redisCache.getCacheMapValue(RedisConstant.YKC_KEY_MAP,deviceConnectionMsg.getDeviceId()); // String key = redisCache.getCacheObject(RedisConstant.KEYS + deviceConnectionMsg.getDeviceId()); respone_msg = Encrytion.decrypt(respone_msg, key.getBytes()); logger.info("{},encry_msg,frame:{},data:{}",deviceConnectionMsg.getDeviceId(),framType, DataConversion.bytesToHexString(respone_msg)); } catch (Exception e) { logger.info("{},ykc->msg decrypt Exception",deviceConnectionMsg.getDeviceId()); e.printStackTrace(); } } if (framType == YkcSendDevice.LOGIN_RESPONSE.getFrameType()) { logger.info("↓↓↓↓↓"+deviceConnectionMsg.getDeviceId()+"登录认证应答"+framType); //处理登录成功与否 boolean res = loginResponse(deviceConnectionMsg, respone_msg); //计费模型请求 if(res){ logger.info("↓↓↓↓↓"+deviceConnectionMsg.getDeviceId()+"请求计费模型"); billingModelFrame.checkBillingModel(deviceConnectionMsg); } } else if (framType == YkcSendDevice.HEART_RESPONSE.getFrameType()) { //TODO:个人理解,枪不管故障还是正常都会有心跳,心跳应答正常说明设备是正常的状态,所以这里不管是同一设备的几号枪心跳都缓存下来心跳应答时间 // logger.info("ykc->dev"+deviceConnectionMsg.getDeviceId()+"↓↓↓↓↓↓↓↓↓↓↓↓↓心跳包应答消息↓↓↓↓↓↓↓↓↓↓↓↓↓"+framType); deviceConnectionMsg.setHeartTime(System.currentTimeMillis()); // logger.info("===========心跳包应答============over"); } else if (framType == YkcSendDevice.BILLING_MODEL_VALIDATE_RESPONSE.getFrameType()) { billingModelHandle(deviceConnectionMsg, respone_msg); } else if (framType == YkcSendDevice.BILLING_MODEL_RESPONSE.getFrameType()) { logger.info("↓↓↓↓↓" + deviceConnectionMsg.getDeviceId() + "计费模型请求应答" + framType); try { billingModelFrame.setBillingModel(deviceConnectionMsg, respone_msg); } catch (Exception e) { e.printStackTrace(); } } else if (framType == YkcSendDevice.BILLING_MODEL_VALIDATE_RESPONSE_SG.getFrameType()) { logger.info("↓↓↓↓↓" + deviceConnectionMsg.getDeviceId() + "深谷计费模型请求应答" + framType); try { billingModelFrame.setSgBillingModel(deviceConnectionMsg, respone_msg); } catch (Exception e) { e.printStackTrace(); } } else if (framType == YkcSendDevice.TRANSACTION_RECORDS_RESPONSE.getFrameType()) { logger.info("↓↓↓↓↓" + deviceConnectionMsg.getDeviceId() + "交易记录确认"); byte[] trans = Arrays.copyOfRange(respone_msg, 0, 16); byte[] reason = Arrays.copyOfRange(respone_msg, 16, 17); QueryWrapper orderStatusQueryWrapper = new QueryWrapper<>(); orderStatusQueryWrapper.eq("trans_order", trans); OrderStatus one = orderStatusService.getOne(orderStatusQueryWrapper); if(one!=null){ QueryWrapper transOrderQueryWrapper = new QueryWrapper<>(); transOrderQueryWrapper.eq("trans_order", trans); TransOrder transOrderServiceOne = transOrderService.getOne(transOrderQueryWrapper); if (reason[0] == 0x00) { one.setTransactionOrderReplyStatus(StatusConstant.TRANSACTION_ORDER_REPLY_STATUS_SUCC); transOrderServiceOne.setFlage(StatusConstant.TRANSACTION_ORDER_REPLY_STATUS_SUCC); } else if (reason[0] == 0x01) { one.setTransactionOrderReplyStatus(StatusConstant.TRANSACTION_ORDER_REPLY_STATUS_FAIL); } else if (reason[0] == 0x02) { one.setTransactionOrderReplyStatus(StatusConstant.TRANSACTION_ORDER_REPLY_STATUS_ILLEGAL); } //接收到后将订单校验从redis剔除 orderStatusService.updateById(one); transOrderService.updateById(transOrderServiceOne); } } else if (framType == YkcSendDevice.DEVICE_STATUS_REQUEST.getFrameType()) { logger.info("↓↓↓↓↓{}读取实时监测数据",deviceConnectionMsg.getDeviceId()); handleRealTimeReport(deviceConnectionMsg,respone_msg,fromMsgSeq); } else if (framType == YkcSendDevice.START_CHARNGING_REQUEST.getFrameType() || framType == YkcSendDevice.START_CHARNGING_REQUEST_16.getFrameType()) { logger.info("↓↓↓↓↓{}运营平台远程控制启机" + framType,deviceConnectionMsg.getDeviceId()); startChargingRequest(deviceConnectionMsg, respone_msg,fromMsgSeq); } else if (framType == YkcSendDevice.STOP_CHARNGING_REQUEST.getFrameType()) { logger.info("↓↓↓↓↓{}运营平台远程停机",deviceConnectionMsg.getDeviceId()); stopChargingRequest(deviceConnectionMsg, respone_msg,fromMsgSeq); } else if (framType == YkcSendDevice.UPDATE_BALANCE.getFrameType()) { logger.info("↓↓↓↓↓{}远程更新余额",deviceConnectionMsg.getDeviceId()); try { remoteBalanceUpdate(deviceConnectionMsg, respone_msg,fromMsgSeq); } catch (Exception e) { e.printStackTrace(); } } else if (framType == YkcSendDevice.CHECKTIME.getFrameType()) { logger.info("↓↓↓↓↓{}对时设置" + framType,deviceConnectionMsg.getDeviceId()); checkTime.checkTimeSend(deviceConnectionMsg,fromMsgSeq); } else if (framType == YkcSendDevice.BILLING_MODEL_SETTING_SG.getFrameType()) { logger.info("↓↓↓↓↓{}深谷计费模型设置",deviceConnectionMsg.getDeviceId()); try { //有异常就是失败 billingModelFrame.setSgBillingModel(deviceConnectionMsg, respone_msg); billingModelFrame.resp(deviceConnectionMsg, (byte) 1,fromMsgSeq); } catch (Exception e) { billingModelFrame.resp(deviceConnectionMsg, (byte) 0,fromMsgSeq); e.printStackTrace(); } } else if(framType == YkcSendDevice.CONFIG_SETTING.getFrameType()){ logger.info("↓↓↓↓↓{}工作参数设置",deviceConnectionMsg.getDeviceId()); otherFrame.configSettingSend(deviceConnectionMsg,respone_msg,fromMsgSeq); } else if (framType == YkcSendDevice.BILLING_MODEL_SETTING.getFrameType()) { logger.info("↓↓↓↓↓{}计费模型设置",deviceConnectionMsg.getDeviceId()); try { //有异常就是失败 billingModelFrame.setBillingModel(deviceConnectionMsg, respone_msg); billingModelFrame.resp(deviceConnectionMsg, (byte) 1,fromMsgSeq); } catch (Exception e) { billingModelFrame.resp(deviceConnectionMsg, (byte) 0,fromMsgSeq); e.printStackTrace(); } } else if (framType == YkcSendDevice.REMOTE_REBOOT.getFrameType()) { logger.info("↓↓↓↓↓{}远程重启",deviceConnectionMsg.getDeviceId()); otherFrame.remoteRebootSend(deviceConnectionMsg,fromMsgSeq); } else if (framType == YkcSendDevice.UPLOAD_FILE_UPDATE.getFrameType()) { logger.info("↓↓↓↓↓{}远程更新",deviceConnectionMsg.getDeviceId()); otherFrame.remoteUpdateSend(deviceConnectionMsg,fromMsgSeq); } } }; Thread thread = new Thread(listener); thread.start(); } /** * 登录回复消息处理 * * @param deviceConnectionMsg * @param respone_msg */ private boolean loginResponse(DeviceConnectionMsg deviceConnectionMsg, byte[] respone_msg) { int login_result = respone_msg[7] & 0xFF; if (ResultUtil.isSuccess(login_result)) { //登录成功,相当于初始化心跳包接收时间更新,初始化心跳包时间相当于登录成功,心跳包能正常上传 deviceConnectionMsg.setHeartTime(System.currentTimeMillis()); deviceConnectionMsg.setLoginStatus(Constant.DEVICE_LOGIN_STATUS); logger.info("{}login successfully", deviceConnectionMsg.getDeviceId()); return true; } else { logger.info("{}login failed ,waitting for retry", deviceConnectionMsg.getDeviceId()); //登录失败等心跳包10秒后进行重试 return false; } } //读取时实数据 private void handleRealTimeReport(DeviceConnectionMsg deviceConnectionMsg, byte[] respone_msg,byte[] fromMsgSeq){ String pileCode = deviceConnectionMsg.getDeviceId(); int port = respone_msg[7] & 0xFF; //0正常 1禁用 //请求获取实时数据 //获取枪状态 QueryWrapper deviceStatusQueryWrapper = new QueryWrapper<>(); deviceStatusQueryWrapper.eq("pile_code", deviceConnectionMsg.getDeviceId()); deviceStatusQueryWrapper.eq("gun_port", port); DeviceStatus deviceStatus = deviceStatusService.getOne(deviceStatusQueryWrapper); if(deviceStatus==null){ logger.info("实时无端口信息"); return; } //不是充电中 就上报空闲 if(deviceStatus.getGunStatus()!=StatusConstant.CHARGING){ realTimeStatusPushFrame.deviceStatusPush(fromMsgSeq,deviceConnectionMsg, FrameDataSplicing. transactionNum(deviceStatus.getPileCode(), deviceConnectionMsg.getMessageCount()) , deviceStatus.getPileCode(), deviceStatus.getGunPort(), deviceStatus.getGunStatus(), deviceStatus.getInsertGunStatus(), 0, 0, zero, zero, 0); return; } //上报充电中的实时状态 //上送充电状态 JSONObject statusJSON = redisCache.getCacheObject(RedisConstant.DEVICE_PORT_STATUS + deviceStatus.getDeviceImei()); if(statusJSON==null){ logger.info("实时无最近103数据{}",pileCode); return; } //拿当前的订单去更新余额 QueryWrapper orderStatusQueryWrapper = new QueryWrapper<>(); orderStatusQueryWrapper.eq("pile_code", pileCode).eq("guns_code", port).orderByDesc("create_time").last("limit 1"); OrderStatus orderStatus = orderStatusService.getOne(orderStatusQueryWrapper); if(orderStatus==null){ logger.info("实时无订单{}",pileCode); return; } Integer voltage; Integer power; Integer endElec=0; if(port==1){ voltage = statusJSON.getInteger("voltage"); }else{ voltage = statusJSON.getInteger("voltage_1"); if(voltage==null){ voltage = statusJSON.getInteger("voltage"); } } if(port == 1){ power = statusJSON.getInteger("power"); endElec = statusJSON.getInteger("elec"); }else{ power = statusJSON.getInteger("power_1"); endElec = statusJSON.getInteger("elec_1"); } if(power==null){ power = 0; } if(voltage==null){ voltage = 0; } //计算实时数据 long endTime = System.currentTimeMillis(); //算电量 Map start = new ConcurrentHashMap<>(); String transCacheKey = "ChargingTrans:"+orderStatus.getId(); if(redisCache.hasKey(transCacheKey)){ start = redisCache.getCacheObject(transCacheKey); }else{ //缓存120秒避免重复计算电量 try { QueryWrapper billWapper = new QueryWrapper<>(); billWapper.in("pile_code", pileCode); BillingModel billingModel = billingModelService.getOne(billWapper); start = transMoney.compute(port, billingModel, orderStatus.getCreateTime(), endTime,orderStatus,endElec); } catch (Exception e) { e.printStackTrace(); logger.error("计算订单异常{},{}",orderStatus.getPileCode(),e.getMessage()); return; } redisCache.setCacheObject(transCacheKey, start, 90, TimeUnit.SECONDS); } BigDecimal elec = start.get("elec"); BigDecimal money = start.get("money"); if (elec.equals(new BigDecimal("0.0000"))) { elec = elec.add(new BigDecimal("0.0001").setScale(4, BigDecimal.ROUND_DOWN)); } logger.info("{}-{}-{}充电中=>实时elec:{}>>>实时金额>>>{}=>p:{},v:{}" ,orderStatus.getPileCode(),port,elec,orderStatus.getGunsCode(),money,power,voltage); int mi = (int) (System.currentTimeMillis() - orderStatus.getCreateTime()) / 1000 / 60; realTimeStatusPushFrame.deviceStatusPush(fromMsgSeq,deviceConnectionMsg, orderStatus.getTransOrder(), deviceStatus.getPileCode(), deviceStatus.getGunPort(), deviceStatus.getGunStatus(), deviceStatus.getInsertGunStatus(), voltage, power, elec, money, mi); logger.info("↑↑↑{},{},{}充电中实时状态上报 ",orderStatus.getPileCode(),orderStatus.getGunsCode(),orderStatus.getId()); } /** * 接收到云快充启机指令的处理 * * @param deviceConnectionMsg * @param respone_msg */ private void startChargingRequest(DeviceConnectionMsg deviceConnectionMsg, byte[] respone_msg,byte[] fromMsgSeq) { try { //1.解析出启动充电流水号 //查询设备sn和imie deviceConnectionMsg.setStartChargeReq(fromMsgSeq); //切出订单号,保存在连接的该设备中 byte[] transOrder = Arrays.copyOfRange(respone_msg, 0, 16); //测试 t = transOrder; byte[] guns = Arrays.copyOfRange(respone_msg, 23, 24); byte[] card = Arrays.copyOfRange(respone_msg, 32, 40); byte[] logCard = Arrays.copyOfRange(respone_msg, 24, 32); byte[] startMoney = Arrays.copyOfRange(respone_msg, respone_msg.length - 6, respone_msg.length - 2); if(!deviceConnectionMsg.getIs18()){ startMoney = Arrays.copyOfRange(respone_msg, respone_msg.length - 4, respone_msg.length); } boolean temp = false; int result = 0x00; //失败 int reason = 0x00; //无 String cacheKey; int portId = guns[0]; QueryWrapper deviceStatusQueryWrapper = new QueryWrapper<>(); deviceStatusQueryWrapper.eq("pile_code", deviceConnectionMsg.getDeviceId()); deviceStatusQueryWrapper.eq("gun_port", portId); DeviceStatus deviceStatus = deviceStatusService.getOne(deviceStatusQueryWrapper); if(deviceStatus==null){ //不存在 reason = 0x04; temp = true; }else { if (deviceStatus.getOnlineStatus()==StatusConstant.OFFLINE||StatusConstant.OFFLINE==deviceStatus.getGunStatus()){ //离线上报 reason=0x04; temp=true; logger.info("reson>"+reason); }else if (StatusConstant.CHARGING==deviceStatus.getGunStatus()){ //枪已在充电中 reason=0x02; temp=true; logger.info("reson>"+reason); }else if (StatusConstant.FAULT==deviceStatus.getGunStatus()){ //枪故障 reason=0x03; temp=true; logger.info("reson>"+reason); }else if (StatusConstant.INSERT_GUNS_NO==deviceStatus.getInsertGunStatus()){ //未插枪 reason=0x05; temp=false; logger.info("reson>"+reason); }else if (PortStatusConstant.EMERGENCY_STOP==deviceStatus.getGunStatus()){ //急停没复位,也是启充失败 reason=0x03; temp=true; } } //检查桩是否禁用 if(!temp){ QueryWrapper deviceQueryWrapper = new QueryWrapper<>(); deviceQueryWrapper.eq("pile_code", deviceConnectionMsg.getDeviceId()); Device device = deviceService.getOne(deviceQueryWrapper); if(device!=null && device.getPileStatus()==1){ temp = true; reason=0x03; logger.info("枪禁用{}",device.getPileCode()); } QueryWrapper billWapper = new QueryWrapper<>(); billWapper.eq("pile_code", deviceConnectionMsg.getDeviceId()); billWapper.eq("device_imei", deviceConnectionMsg.getImei()); BillingModel b = billingModelService.getOne(billWapper); if (b == null) { temp = true; reason=0x00; logger.info("未配置计费模型{}",deviceConnectionMsg.getDeviceId()); } } if (temp) { logger.info("启动失败{}:reason:{}" ,deviceConnectionMsg.getDeviceId(), reason); charngingPushFrame.startStatus(deviceConnectionMsg, transOrder, guns[0], result, reason); Map compute = transMoney.getTransData(); transactionFlowPushFrame.sendTrans(deviceConnectionMsg, transOrder, deviceConnectionMsg.getDeviceId(), guns[0], System.currentTimeMillis(), System.currentTimeMillis(), new BillingModel(), card, compute, TransConstant.START_FAIL); return; } BigDecimal bigDecimalmoney = DataConversion.arrToBigDec(startMoney, 2, 2).setScale(2, BigDecimal.ROUND_UP); logger.info("{}开始充电,startMoney" + bigDecimalmoney + "sbyt+" + DataConversion.bytesToHexString(startMoney),deviceConnectionMsg.getDeviceId()); OrderStatus orderStatus = new OrderStatus(); orderStatus.setDeviceSn(deviceStatus.getDeviceSn()); orderStatus.setDeviceImei(deviceConnectionMsg.getImei()); orderStatus.setPileCode(deviceStatus.getPileCode()); orderStatus.setGunsCode(guns[0]); orderStatus.setStartMoney(bigDecimalmoney); orderStatus.setCard(card); orderStatus.setTransOrder(transOrder); orderStatus.setCreateTime(System.currentTimeMillis()); //2.保存交易流水号并记录本次交易流水状态 orderStatusService.save(orderStatus); saveTransOrder(orderStatus); String gunCode = String.valueOf(guns[0]); if (reason==0x05){ //未插枪不启充设备,但是返回未插枪 logger.info("未插枪等待插枪充电订单{}-{}",orderStatus.getPileCode(),orderStatus.getGunsCode()); charngingPushFrame.startStatus(deviceConnectionMsg,transOrder,guns[0],result,reason ); redisCache.setCacheObject(RedisConstant.WAITING_INSERT_GUN+":"+orderStatus.getPileCode()+'_'+orderStatus.getGunsCode(),orderStatus.getId(),55*1000, TimeUnit.MILLISECONDS); }else { logger.info("已就绪启动充电{}-{}",orderStatus.getPileCode(),orderStatus.getGunsCode()); deviceControlerService.startCharge(deviceStatus.getDeviceImei(), orderStatus.getDeviceImei(), (int) guns[0],0); } //标记最后订单时间 5分钟内不上报空闲状态 避免刚下单状态还没更新就被freeTask任务给顶掉了 redisCache.setCacheMapValue(RedisConstant.PILE_GUN_PAY_TIME, orderStatus.getPileCode() + "_" + gunCode, System.currentTimeMillis()); } catch (Exception e) { logger.info("{}启动充电异常,{}",deviceConnectionMsg.getDeviceId(),e.getMessage()); realTimeStatusPushFrame.deviceStatusPush(deviceConnectionMsg, t, deviceConnectionMsg.getDeviceId(), (byte) 1, (byte) 2, (byte) 1, 0, 0, zero, zero, 0); e.printStackTrace(); } } private static byte[] t = new byte[16]; /** * 计费模型校验应答处理 * * @param deviceConnectionMsg * @param respone_msg */ private void billingModelHandle(DeviceConnectionMsg deviceConnectionMsg, byte[] respone_msg) { byte[] modelNum = Arrays.copyOfRange(respone_msg, 7, 9); byte[] result = Arrays.copyOfRange(respone_msg, 9, 10); logger.info("计费模型验证应答" + deviceConnectionMsg.getDeviceId() + ">>modelNum:" + DataConversion.bytesToHexString(modelNum) + ";result:" + DataConversion.bytesToHexString(result)); if (result[0] == BillingModelConst.DIFFERENT) { logger.info("获取计费模型{}", deviceConnectionMsg.getDeviceId()); //不一致请求计费模型,再向平台请求计费模型0x09 billingModelFrame.getBillingModel(deviceConnectionMsg); } } /** * 停机指令处理 * * @param deviceConnectionMsg * @param respone_msg */ private void stopChargingRequest(DeviceConnectionMsg deviceConnectionMsg, byte[] respone_msg,byte[] fromMsgSeq) { deviceConnectionMsg.setStopChargeReq(fromMsgSeq); byte[] guns = Arrays.copyOfRange(respone_msg, 7, 8); //查询设备sn和imie QueryWrapper deviceStatusQueryWrapper = new QueryWrapper<>(); deviceStatusQueryWrapper.eq("pile_code", deviceConnectionMsg.getDeviceId()); List list = deviceStatusService.list(deviceStatusQueryWrapper); DeviceStatus deviceStatus = list.get(0); try { TimeUnit.MILLISECONDS.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } try{ //先发送一次获取103 //获取端口状态 DeviceParam deviceParam = new DeviceParam(); deviceParam.setDeviceId(deviceStatus.getDeviceImei()); deviceParam.setCcid(deviceStatus.getDeviceImei()); deviceControlerService.sendPortDetailCmd(deviceParam); }catch (Exception e){ } RpcResult rpcResult = deviceControlerService.stopCharge(deviceStatus.getDeviceImei(), deviceStatus.getDeviceImei(), (int) guns[0]); if (rpcResult.isOk()) { //发送停充成功,一般没有指令发送成功设备不执行 /* //deviceStatus.setGunStatus((byte) PortStatusConstant.INSERT_GUN); deviceStatus.setOnlineStatus(DeviceOnlineStatus.ONLINE); deviceStatus.setUpdateTime(System.currentTimeMillis()); deviceStatusService.updateById(deviceStatus);*/ QueryWrapper orderStatusQueryWrapper = new QueryWrapper<>(); orderStatusQueryWrapper.eq("device_imei", deviceStatus.getDeviceImei()).eq("guns_code", guns[0]).orderByDesc("create_time").last("limit 1"); OrderStatus statusServiceOne = orderStatusService.getOne(orderStatusQueryWrapper); statusServiceOne.setEndTime(System.currentTimeMillis()); statusServiceOne.setReasonStopCharging(TransConstant.APP_REMOTE_STOP); orderStatusService.updateById(statusServiceOne); redisCache.setCacheMapValue(guns[0] == 1 ? RedisConstant.ONLINE_DEVICE_ONE : RedisConstant.ONLINE_DEVICE_TWO, deviceStatus.getPileCode(), deviceStatus); } else { logger.info("stop charging device:" + deviceStatus.getDeviceSn() + ";port:" + guns[0] + "stop charnging fail"); } } /*** * 远程余额更新 * @param deviceConnectionMsg * @param respone_msg */ private void remoteBalanceUpdate(DeviceConnectionMsg deviceConnectionMsg, byte[] respone_msg,byte[] fromMsgSeq) throws Exception { byte[] pileCode = Arrays.copyOfRange(respone_msg, 0, 7); byte[] guns = Arrays.copyOfRange(respone_msg, 7, 8); byte[] card = Arrays.copyOfRange(respone_msg, 8, 16); byte[] balance = Arrays.copyOfRange(respone_msg, 16, 20); BigDecimal bigDecimal = DataConversion.arrToBigDec(balance, 2, 2); String pile = DataConversion.bytesToHexString(pileCode); logger.info("更新余额>>" + bigDecimal + ";pileCode:" + pile+"port:{}",guns[0]); //TODO:1.这里更新的余额需要针对充电桩使用的人员进行修改;(考虑后台计费);2.更新操作完成时候响应云快充更新结果 //拿当前的订单去更新余额 QueryWrapper orderStatusQueryWrapper = new QueryWrapper<>(); orderStatusQueryWrapper.eq("pile_code", pile).eq("guns_code", guns[0]).eq("card", card).orderByDesc("create_time").last("limit 1"); OrderStatus statusServiceOne = orderStatusService.getOne(orderStatusQueryWrapper); QueryWrapper billingModelQueryWrapper = new QueryWrapper<>(); billingModelQueryWrapper.eq("pile_code", pile); BillingModel model = billingModelService.getOne(billingModelQueryWrapper); int port = (int) guns[0]; //后台计费 // Map map = transMoney.compute(port, model, statusServiceOne.getCreateTime(), System.currentTimeMillis()); //BigDecimal money = statusServiceOne.getStartMoney().subtract(map.get("money")).setScale(4, BigDecimal.ROUND_DOWN); //BigDecimal add = money.add(bigDecimal); statusServiceOne.setStartMoney(bigDecimal); logger.info("更新余额>>{};pileCode:{}port:{}--before:{}",bigDecimal,pileCode,guns[0],statusServiceOne.getStartMoney()); // statusServiceOne.setStartMoney(bigDecimal); orderStatusService.updateById(statusServiceOne); //这里测试默认更新成功 remoteBalanceUpdatePushFrame.updateBalance(deviceConnectionMsg, card, (byte) 0x00,fromMsgSeq); } //保存订单开始状态,记录充电的交易流水 private void saveTransOrder(OrderStatus orderStatus) { TransOrder transOrder = transMapping.orderStatusToTransOrder(orderStatus); // byte[] transOrders = new byte[8]; // System.arraycopy(orderStatus.getTransOrder(), 8, transOrders, 0, transOrders.length); //为了云快充app显示的订单号一致,将订单号格式转化一下 transOrder.setTrans(DataConversion.bytesToHexString(orderStatus.getTransOrder())); boolean b = transOrderService.saveOrUpdate(transOrder); logger.info("保存订单>>>>>" + DataConversion.bytesToHexString(orderStatus.getTransOrder()) + "结果:" + b); } //余额不足解决办法,将下发的余额和尖峰平谷中最贵的价格发送到主板参数中,配合主板参数进行余额不足判定 private void setMoney(OrderStatus orderStatus) { QueryWrapper orderStatusQueryWrapper = new QueryWrapper<>(); orderStatusQueryWrapper.eq("pile_code", orderStatus.getPileCode()); BillingModel billingModel = billingModelService.getOne(orderStatusQueryWrapper); MainBoard mainBoard = new MainBoard(); mainBoard.setBottomPrice(billingModel.getSharpPrice().add(billingModel.getSharpServiceFee()).intValue()); mainBoard.setBottomServicePrice(0); mainBoard.setPeakPrice(billingModel.getSharpPrice().add(billingModel.getSharpServiceFee()).intValue()); mainBoard.setPeakServicePrice(0); mainBoard.setBottomStart(0); mainBoard.setBottomEnd(24); mainBoard.setFeeType(0x00); //设置主板参数 deviceControlerService.setMainBoard(orderStatus.getDeviceImei(), orderStatus.getDeviceImei(), mainBoard); } }