diff --git a/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/JumpController.java b/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/JumpController.java index 5287ee555..b41360b0d 100644 --- a/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/JumpController.java +++ b/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/JumpController.java @@ -10,6 +10,7 @@ import com.jsowell.common.enums.ykc.ReturnCodeEnum; import com.jsowell.common.exception.BusinessException; import com.jsowell.common.response.RestApiResponse; import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.YKCUtils; import com.jsowell.common.util.file.AliyunOssUploadUtils; import com.jsowell.common.util.file.FileUtils; import com.jsowell.pile.domain.PileBasicInfo; @@ -53,12 +54,11 @@ public class JumpController extends BaseController { /** * 查询充电桩详情 - * http://localhost:8080/app-xcx-h5/pile/pileDetail/{pileSn} */ @GetMapping("/pile/pileDetail/{pileSn}") public RestApiResponse getPileDetail(HttpServletRequest request, @PathVariable("pileSn") String pileSn) { // logger.info("app-xcx-h5查询充电桩详情 param:{}", pileSn); - logger.info("User-Agent:{}", request.getHeader("user-agent")); + logger.debug("User-Agent:{}", request.getHeader("user-agent")); RestApiResponse response = null; try { // 如果对接了类似华为平台的第三方平台,先修改一下枪口状态 @@ -111,10 +111,11 @@ public class JumpController extends BaseController { public RestApiResponse getConnectorDetail(HttpServletRequest request, @PathVariable("pileConnectorCode") String pileConnectorCode) { // logger.info("app-xcx-h5查询充电枪口详情 param:{}", pileConnectorCode); String requestSource = UserAgentUtils.determineRequestSource(request); - logger.info("查询充电枪口详情-User-Agent:{}, 请求来源:{}", request.getHeader("user-agent"), requestSource); + logger.debug("查询充电枪口详情-User-Agent:{}, 请求来源:{}", request.getHeader("user-agent"), requestSource); RestApiResponse response = null; // 截取桩号 - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); try { // 如果对接了类似华为平台的第三方平台,先修改一下枪口状态 diff --git a/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/OrderController.java b/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/OrderController.java index ba17f1c30..3212ff18d 100644 --- a/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/OrderController.java +++ b/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/OrderController.java @@ -153,7 +153,7 @@ public class OrderController extends BaseController { logger.error("查询订单信息 error", e); response = new RestApiResponse<>(ReturnCodeEnum.CODE_GET_ORDER_INFO_BY_MEMBER_ID_ERROR); } - logger.info("查询订单信息, param:{}, result:{}", JSON.toJSONString(dto), JSON.toJSONString(response)); + logger.debug("查询订单信息, param:{}, result:{}", JSON.toJSONString(dto), JSON.toJSONString(response)); return response; } @@ -182,7 +182,7 @@ public class OrderController extends BaseController { logger.error("小程序获取订单详情 error", e); response = new RestApiResponse<>(ReturnCodeEnum.CODE_GET_ORDER_DETAIL_ERROR); } - logger.info("小程序获取订单详情, orderCode:{}, result:{}", dto.getOrderCode(), JSON.toJSONString(response)); + // logger.info("小程序获取订单详情, orderCode:{}, result:{}", dto.getOrderCode(), JSON.toJSONString(response)); return response; } diff --git a/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/PileController.java b/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/PileController.java index 9196d1949..3380b2549 100644 --- a/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/PileController.java +++ b/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/PileController.java @@ -119,7 +119,7 @@ public class PileController extends BaseController { */ @PostMapping("/selectConnectorListByParams") public RestApiResponse selectConnectorListByParams(HttpServletRequest request, @RequestBody QueryConnectorListDTO dto) { - logger.info("查询充电枪口列表 params:{}", JSON.toJSONString(dto)); + logger.debug("查询充电枪口列表 params:{}", JSON.toJSONString(dto)); RestApiResponse response = null; try { PageResponse pageResponse = pileConnectorInfoService.getUniAppConnectorInfoListByParams(dto); @@ -128,7 +128,7 @@ public class PileController extends BaseController { logger.error("查询充电枪口列表异常", e); response = new RestApiResponse<>(ReturnCodeEnum.CODE_GET_CONNECTOR_INFO_BY_STATION_ID_ERROR); } - logger.info("查询充电枪口列表 result:{}", response); + logger.debug("查询充电枪口列表 result:{}", response); return response; } @@ -141,15 +141,8 @@ public class PileController extends BaseController { */ @PostMapping("/selectStationConnectorList") public RestApiResponse selectStationConnectorList(HttpServletRequest request, @RequestBody QueryConnectorListDTO dto) { - logger.info("查询充电枪口列表 params:{}", JSON.toJSONString(dto)); + logger.debug("查询充电枪口列表 params:{}", JSON.toJSONString(dto)); RestApiResponse response = null; - // try { - // // 查询对接第三方平台的枪口状态 - // selectThirdPartyConnectorStatus(dto); - // } catch (Exception e) { - // logger.error("修改对接第三方平台的枪口状态 error"); - // } - try { PageResponse pageResponse = pileConnectorInfoService.selectStationConnectorList(dto); response = new RestApiResponse<>(pageResponse); @@ -157,7 +150,7 @@ public class PileController extends BaseController { logger.error("查询充电枪口列表异常", e); response = new RestApiResponse<>(ReturnCodeEnum.CODE_GET_CONNECTOR_INFO_BY_STATION_ID_ERROR); } - logger.info("查询充电枪口列表 result:{}", response); + logger.debug("查询充电枪口列表, params:{}, result:{}", JSON.toJSONString(dto), response); return response; } diff --git a/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/TempController.java b/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/TempController.java index bd112af4c..dce523302 100644 --- a/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/TempController.java +++ b/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/TempController.java @@ -14,6 +14,7 @@ import com.jsowell.pile.domain.AdapayMemberAccount; import com.jsowell.pile.domain.MemberPlateNumberRelation; import com.jsowell.pile.domain.OrderBasicInfo; import com.jsowell.pile.domain.ykcCommond.ReservationChargingCommand; +import com.jsowell.pile.domain.ykcCommond.StartChargingCommand; import com.jsowell.pile.dto.*; import com.jsowell.pile.service.*; import com.jsowell.pile.service.programlogic.AbstractProgramLogic; @@ -72,6 +73,30 @@ public class TempController extends BaseController { @Autowired private PileRemoteService pileRemoteService; + @Autowired + private EBikeSendCommandService eBikeSendCommandService; + + /** + * 电单车开始充电 + * http://localhost:8080/temp/tempStartCharging + */ + @PostMapping("/tempStartCharging") + public RestApiResponse tempStartCharging(@RequestBody QueryOrderDTO dto) { + RestApiResponse response = null; + try { + StartChargingCommand command = StartChargingCommand.builder() + .pileSn(dto.getPileSn()) + .connectorCode(dto.getConnectorCode()) + .build(); + eBikeSendCommandService.sendStartChargingCommand(command); + response = new RestApiResponse<>(); + } catch (Exception e) { + logger.error("电单车开始充电 error", e); + response = new RestApiResponse<>(ReturnCodeEnum.CODE_FAILED); + } + return response; + } + /** * 对时 * http://localhost:8080/temp/proofreadTimeTest diff --git a/jsowell-admin/src/main/java/com/jsowell/service/OrderService.java b/jsowell-admin/src/main/java/com/jsowell/service/OrderService.java index 5f88ee3fb..e0f06b04f 100644 --- a/jsowell-admin/src/main/java/com/jsowell/service/OrderService.java +++ b/jsowell-admin/src/main/java/com/jsowell/service/OrderService.java @@ -55,6 +55,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; @@ -1093,7 +1094,8 @@ public class OrderService { * @param data * @throws JsonProcessingException */ - private void paymentSucceeded(String data) throws JsonProcessingException { + @Transactional(rollbackFor = Exception.class) + public void paymentSucceeded(String data) throws JsonProcessingException { // 验签成功 保存到回调记录表中 JSONObject jsonObject = JSON.parseObject(data); log.info("adapay支付成功回调:{}", jsonObject.toJSONString()); @@ -1162,10 +1164,16 @@ public class OrderService { paymentInfo.setPaymentId(paymentId); paymentInfo.setAmount(amount.toString()); + String payModel = OrderPayRecordEnum.WECHATPAY_PAYMENT.getValue(); + String payChannel = jsonObject.getString("pay_channel"); + if (StringUtils.isNotEmpty(payChannel) && AdapayPayChannelEnum.ALIPAY_LITE.getValue().equals(payChannel)) { + payModel = OrderPayRecordEnum.ALIPAY_PAYMENT.getValue(); + } + // 记录订单支付流水 OrderPayRecord orderPayRecord = OrderPayRecord.builder() .orderCode(orderCode) - .payMode(OrderPayRecordEnum.WECHATPAY_PAYMENT.getValue()) + .payMode(payModel) .paymentId(paymentId) .payAmount(amount) .acquirer(AcquirerEnum.ADAPAY.getValue()) diff --git a/jsowell-admin/src/main/java/com/jsowell/service/PileService.java b/jsowell-admin/src/main/java/com/jsowell/service/PileService.java index 62200a433..6e1c85319 100644 --- a/jsowell-admin/src/main/java/com/jsowell/service/PileService.java +++ b/jsowell-admin/src/main/java/com/jsowell/service/PileService.java @@ -12,24 +12,17 @@ import com.jsowell.common.exception.BusinessException; import com.jsowell.common.util.*; import com.jsowell.pile.domain.*; import com.jsowell.pile.dto.*; -import com.jsowell.pile.util.SnUtils; import com.jsowell.pile.service.*; import com.jsowell.pile.transaction.dto.PileTransactionDTO; import com.jsowell.pile.transaction.service.TransactionService; import com.jsowell.pile.vo.base.ConnectorInfoVO; import com.jsowell.pile.vo.base.MerchantInfoVO; import com.jsowell.pile.vo.base.PileInfoVO; -import com.jsowell.pile.vo.uniapp.customer.BillingPriceVO; -import com.jsowell.pile.vo.uniapp.customer.PersonPileConnectorSumInfoVO; -import com.jsowell.pile.vo.uniapp.customer.PersonPileRealTimeVO; -import com.jsowell.pile.vo.uniapp.customer.PileConnectorDetailVO; -import com.jsowell.pile.vo.uniapp.customer.AppletPileDetailVO; +import com.jsowell.pile.vo.uniapp.customer.*; import com.jsowell.pile.vo.web.PileDetailVO; import com.jsowell.pile.vo.web.PileStationVO; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.RandomStringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -42,13 +35,12 @@ import java.util.stream.Collectors; @Service public class PileService { - private final Logger log = LoggerFactory.getLogger(this.getClass()); @Autowired private TransactionService pileTransactionService; @Resource - private SnUtils snUtils; + private PileSnGenerateService snUtils; @Autowired private PileBasicInfoService pileBasicInfoService; @@ -163,23 +155,23 @@ public class PileService { if (StringUtils.isBlank(param)) { throw new BusinessException(ReturnCodeEnum.CODE_PARAM_NOT_NULL_ERROR); } - String pileSn; + String pileSn = YKCUtils.getPileSn(param); // param长度大于10是汽车桩, 否则是电单车桩 - if (param.length() > 10) { - // 汽车桩, 桩编号14位, 枪口号2位 - if (param.length() == 16) { - pileSn = StringUtils.substring(param, 0, param.length() - 2); - } else { - pileSn = param; - } - } else { - // 电单车桩, 桩编号8位, 枪口号2位 - if (param.length() == 10) { - pileSn = StringUtils.substring(param, 0, param.length() - 2); - } else { - pileSn = param; - } - } + // if (param.length() > 10) { + // // 汽车桩, 桩编号14位, 枪口号2位 + // if (param.length() == 16) { + // pileSn = StringUtils.substring(param, 0, param.length() - 2); + // } else { + // pileSn = param; + // } + // } else { + // // 电单车桩, 桩编号8位, 枪口号2位 + // if (param.length() == 10) { + // pileSn = StringUtils.substring(param, 0, param.length() - 2); + // } else { + // pileSn = param; + // } + // } // 查询充电桩信息 PileInfoVO pileInfoVO = pileBasicInfoService.selectPileInfoBySn(pileSn); diff --git a/jsowell-admin/src/test/java/SpringBootTestController.java b/jsowell-admin/src/test/java/SpringBootTestController.java index c54888c83..2fda1f684 100644 --- a/jsowell-admin/src/test/java/SpringBootTestController.java +++ b/jsowell-admin/src/test/java/SpringBootTestController.java @@ -61,7 +61,7 @@ import com.jsowell.pile.service.programlogic.ProgramLogicFactory; import com.jsowell.pile.thirdparty.CommonParamsDTO; import com.jsowell.pile.transaction.dto.OrderTransactionDTO; import com.jsowell.pile.transaction.service.TransactionService; -import com.jsowell.pile.util.SnUtils; +import com.jsowell.pile.service.PileSnGenerateService; import com.jsowell.pile.vo.base.MemberWalletVO; import com.jsowell.pile.vo.base.PileInfoVO; import com.jsowell.pile.vo.uniapp.customer.CurrentTimePriceDetails; @@ -121,7 +121,7 @@ public class SpringBootTestController { String wechatAppId2 = "wx20abc5210391649c"; // 嘉佳充电 @Autowired - private SnUtils snUtils; + private PileSnGenerateService snUtils; @Autowired private PileService pileService; @@ -627,7 +627,7 @@ public class SpringBootTestController { // 查询充电桩的计费模板 BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(dto.getPileSn()); dto.setBillingTemplate(billingTemplateVO); - OrderBasicInfo orderBasicInfo = orderBasicInfoService.saveOrder2Database(dto); + OrderBasicInfo orderBasicInfo = orderBasicInfoService.saveOrderForEV(dto); return orderBasicInfo; } diff --git a/jsowell-common/src/main/java/com/jsowell/common/YouDianUtils.java b/jsowell-common/src/main/java/com/jsowell/common/YouDianUtils.java index 691409d04..52c0e6a73 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/YouDianUtils.java +++ b/jsowell-common/src/main/java/com/jsowell/common/YouDianUtils.java @@ -1,5 +1,7 @@ package com.jsowell.common; +import com.google.common.primitives.Bytes; +import com.jsowell.common.enums.ebike.EBikeTypeEnum; import com.jsowell.common.util.BytesUtil; import lombok.extern.slf4j.Slf4j; @@ -87,4 +89,48 @@ public class YouDianUtils { int calculatedChecksum = calculateCheckField(bytes); return BytesUtil.intToBytesLittle(calculatedChecksum); } + + /** + * 获取物理IDbyte数组 + * @param deviceNumber + * @return + */ + public static byte[] getPhysicalIdBytes(int deviceNumber) { + byte[] physicalIdBytes = BytesUtil.intToBytes(deviceNumber, 3); + // 拼接识别码, 12路插座 + byte[] concat = Bytes.concat(EBikeTypeEnum.socket_12way.getBytes(), physicalIdBytes); + return BytesUtil.reverse(concat); + } + + // public static String convertPortNumberToHex(int portNumber) { + // if (portNumber < 1 || portNumber > 16) { + // throw new IllegalArgumentException("Port number must be between 1 and 16."); + // } + // + // // 端口号从1开始,因此需要减去1 + // int hexValue = portNumber - 1; + // + // // 转换为16进制字符串,并确保长度为2位 + // String hexString = String.format("0x%02X", hexValue); + // + // return hexString; + // } + + /** + * 端口号转换 + * 指充电桩的插口号,端口号从0开始,如0x00-0x0F则代表第1路-第16路,0x00=第1路,0x09=第十路,0x0A=第十一路,FF=设备智能选择端口(服务器下发); + * @param portNumber + * @return + */ + public static byte[] convertPortNumberToBytes(int portNumber) { + if (portNumber < 1 || portNumber > 16) { + throw new IllegalArgumentException("Port number must be between 1 and 16."); + } + + // 端口号从1开始,因此需要减去1 + int hexValue = portNumber - 1; + + // 转换为字节数组 + return BytesUtil.intToBytesLittle(hexValue, 1); + } } diff --git a/jsowell-common/src/main/java/com/jsowell/common/constant/Constants.java b/jsowell-common/src/main/java/com/jsowell/common/constant/Constants.java index 03ab3501b..42be0aa5f 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/constant/Constants.java +++ b/jsowell-common/src/main/java/com/jsowell/common/constant/Constants.java @@ -10,6 +10,8 @@ import java.math.BigDecimal; * @author jsowell */ public class Constants { + // 电单车协议包头 + public static final String EBIKE_HEADER = "DNY"; // 十六进制前缀 public static final String HEX_PREFIX = "0x"; @@ -31,17 +33,27 @@ public class Constants { // 非法交易流水号 由充电桩启动的订单会传全是0的交易流水号 public static final String ILLEGAL_TRANSACTION_CODE = "00000000000000000000000000000000"; - // 充电桩sn号长度 - public static final int PILE_SN_LENGTH = 14; + // 电动汽车充电桩sn号长度 + public static final int PILE_SN_LENGTH_FOR_EV = 14; - // 充电桩枪口号长度 - public static final int CONNECTOR_CODE_LENGTH = 2; + // 电动汽车充电桩枪口号长度 + public static final int CONNECTOR_CODE_LENGTH_FOR_EV = 2; + + // 电动汽车充电桩枪口编号长度 + public static final int PILE_CONNECTOR_CODE_LENGTH_FOR_EV = PILE_SN_LENGTH_FOR_EV + CONNECTOR_CODE_LENGTH_FOR_EV; + + // 电单车充电桩sn号长度 + public static final int PILE_SN_LENGTH_FOR_EBIKE = 8; + + // 电单车充电桩枪口号长度 + public static final int CONNECTOR_CODE_LENGTH_FOR_EBIKE = 2; + + // 电单车充电桩枪口编号长度 + public static final int PILE_CONNECTOR_CODE_LENGTH_FOR_EBIKE = PILE_SN_LENGTH_FOR_EBIKE + CONNECTOR_CODE_LENGTH_FOR_EBIKE; // 汇付手续费费率 public static final String FEE_RATES = "0.0055"; - // 充电桩枪口编号长度 - public static final int PILE_CONNECTOR_CODE_LENGTH = PILE_SN_LENGTH + CONNECTOR_CODE_LENGTH; public static final String SOCKET_IP = "127.0.0.1"; diff --git a/jsowell-common/src/main/java/com/jsowell/common/enums/ebike/EBikeTypeEnum.java b/jsowell-common/src/main/java/com/jsowell/common/enums/ebike/EBikeTypeEnum.java new file mode 100644 index 000000000..3cfb31705 --- /dev/null +++ b/jsowell-common/src/main/java/com/jsowell/common/enums/ebike/EBikeTypeEnum.java @@ -0,0 +1,36 @@ +package com.jsowell.common.enums.ebike; + +import com.jsowell.common.util.BytesUtil; + +public enum EBikeTypeEnum { + + socket_1way(0x03, "单路插座"), + socket_2way(0x04, "双路插座"), + socket_10way(0x05, "10路充电桩"), + socket_16way(0x06, "16路充电桩"), + socket_12way(0x07, "12路充电桩"), + host(0x09, "主机"), + Leakage_protection_host(0x0A, "漏保主机"), + + ; + + private final int value; + private final String desc; + + public int getValue() { + return value; + } + + public String getDesc() { + return desc; + } + + public byte[] getBytes() { + return BytesUtil.intToBytesLittle(value, 1); + } + + EBikeTypeEnum(int value, String desc) { + this.value = value; + this.desc = desc; + } +} diff --git a/jsowell-common/src/main/java/com/jsowell/common/enums/ebike/PortStatusEnum.java b/jsowell-common/src/main/java/com/jsowell/common/enums/ebike/PortStatusEnum.java index c1a3c3cd3..b254d0200 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/enums/ebike/PortStatusEnum.java +++ b/jsowell-common/src/main/java/com/jsowell/common/enums/ebike/PortStatusEnum.java @@ -19,7 +19,8 @@ public enum PortStatusEnum { PRE_INSPECTION_LOAD_SHORT_CIRCUIT(13, "预检-负载短路", "255"), FILTERED_PRE_INSPECTION_RELAY_GLUE(14, "过滤性预检-继电器粘连", "255"), CARD_CHIP_DAMAGE(15, "刷卡芯片损坏故障", "255"), - DETECTION_CIRCUIT_FAULT(16, "检测电路故障", "255"); + DETECTION_CIRCUIT_FAULT(16, "检测电路故障", "255"), + ; private final int value; private final String description; diff --git a/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/EBikeChargingStopReasonEnum.java b/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/EBikeChargingStopReasonEnum.java new file mode 100644 index 000000000..61991843b --- /dev/null +++ b/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/EBikeChargingStopReasonEnum.java @@ -0,0 +1,88 @@ +package com.jsowell.common.enums.ykc; + +import com.jsowell.common.util.BytesUtil; + +/** + * 电单车充电停止原因enum + */ +public enum EBikeChargingStopReasonEnum { + + FULL_AUTO_STOP(0x01, "充满自停"), + TIME_AUTO_STOP(0x02, "达到最大充电时间"), + PRESET_TIME_AUTO_STOP(0x03, "达到预设时间"), + PRESET_ELECTRICITY_AUTO_STOP(0x04, "达到预设电量"), + USER_PULL_OUT(0x05, "用户拔出"), + LOAD_TOO_LARGE(0x06, "负载过大"), + SERVER_FORCE_STOP(0x07, "服务器控制停止"), + DYNAMIC_OVERLOAD(0x08, "动态过载"), + POWER_TOO_SMALL(0x09, "功率过小"), + ENVIRONMENT_TEMPERATURE_TOO_HIGH(0x0A, "环境温度过高"), + PORT_TEMPERATURE_TOO_HIGH(0x0B, "端口温度过高"), + OVER_CURRENT(0x0C, "过流"), + USER_PULL_OUT_1(0x0D, "用户拔出-1,可能是插座弹片卡住"), + NO_CONTACT(0x0E, "无功率停止,可能是接触不良或保险丝烧断故障"), + RELAY_BAD(0x0F, "预检-继电器坏或保险丝断"), + WATER_INTRUSION(0x10, "水浸断电"), + FIRE_SETTLEMENT_LOCAL_PORT(0x11, "灭火结算(本端口)"), + FIRE_SETTLEMENT_NON_LOCAL_PORT(0x12, "灭火结算(非本端口)"), + USER_PASSWORD_OPEN_DOOR_SHUTDOWN(0x13, "用户密码开柜断电"), + NOT_CLOSE_DOOR(0x14, "未关好柜门"), + USER_OPERATION_STOP(0x15, "外部操作停止"), + SWIPE_OPERATION_STOP(0x16, "刷卡操作停止"), + SERVER_FORCE_STOP_2(0x17, "服务器强制停止(主要用于充电柜强制开柜门)"), + FIRE_SYSTEM_TRIGGER_STOP(0x18, "消防系统触发停止"), + STORAGE_ERROR(0x19, "存储器错误"), + OVER_VOLTAGE(0x1A, "过压"), + UNDER_VOLTAGE(0x1B, "欠压"), + + ; + + private int code; + private String msg; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + EBikeChargingStopReasonEnum(int code, String msg) { + this.code = code; + this.msg = msg; + } + + /** + * 根据code获取停止原因描述 + * + * @param code 编码 + * @return 停止原因描述 + */ + public static String getMsgByCode(int code) { + for (EBikeChargingStopReasonEnum item : EBikeChargingStopReasonEnum.values()) { + if (item.getCode() == code) { + return item.getMsg(); + } + } + return null; + } + + public static void main(String[] args) { + String stopReason = "6B"; + byte[] stopReasonByteArr = new byte[]{0x6B}; + String s = BytesUtil.bin2HexStr(stopReasonByteArr); + + int i = Integer.parseInt(stopReason, 16); + String stopReasonMsg = EBikeChargingStopReasonEnum.getMsgByCode(i); + System.out.println(stopReasonMsg); + } +} diff --git a/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/PileChannelEntity.java b/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/PileChannelEntity.java index 3010be375..8e81d95ef 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/PileChannelEntity.java +++ b/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/PileChannelEntity.java @@ -55,6 +55,7 @@ public class PileChannelEntity { * @return */ public static ChannelHandlerContext getChannelByPileSn(String pileSn) { + output(); return manager.get(pileSn); } @@ -78,7 +79,7 @@ public class PileChannelEntity { public static void output() { for (HashMap.Entry entry : manager.entrySet()) { System.out.println("pileSn:" + entry.getKey() + - ",ChannelId:" + entry.getValue().channel().id().asLongText()); + ",ChannelId:" + entry.getValue().channel().id().asShortText()); } } diff --git a/jsowell-common/src/main/java/com/jsowell/common/util/BytesUtil.java b/jsowell-common/src/main/java/com/jsowell/common/util/BytesUtil.java index 099dc078e..bde1b7224 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/util/BytesUtil.java +++ b/jsowell-common/src/main/java/com/jsowell/common/util/BytesUtil.java @@ -272,6 +272,55 @@ public class BytesUtil { return stringBuilder.toString(); } + /** + * 将字符串转换为指定长度的16进制字节数组。 + * + * @param str 需要转换的字符串 + * @param targetLength 目标字节数组的长度 + * @return 对应的16进制字节数组 + */ + public static byte[] stringToHexBytes(String str, int targetLength) { + if (str == null) { + throw new IllegalArgumentException("字符串不能为null"); + } + + int strLength = str.length(); + if (targetLength < strLength) { + throw new IllegalArgumentException("目标字节数组长度必须大于等于字符串长度"); + } + + byte[] hexBytes = new byte[targetLength]; + for (int i = 0; i < strLength; i++) { + char c = str.charAt(i); + hexBytes[i] = (byte) c; + } + + // 剩余部分用0填充 + for (int i = strLength; i < targetLength; i++) { + hexBytes[i] = 0; + } + + return hexBytes; + } + + /** + * 将字节数组转换为十六进制字符串,用于打印查看。 + * + * @param bytes 字节数组 + * @return 十六进制字符串 + */ + private static String bytesToHex(byte[] bytes) { + StringBuilder hexString = new StringBuilder(); + for (byte b : bytes) { + String hex = Integer.toHexString(0xFF & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } + /** * @函数功能: 10进制串转为BCD码 * @输入参数: 10进制串 @@ -323,15 +372,17 @@ public class BytesUtil { */ public static byte[] str2BcdLittle(String asc) { byte[] temp = str2Bcd(asc); - return revert(temp); + return reverse(temp); } - - public static void main(String[] args) { - byte[] length = new byte[] {0x09, 0x00}; - int i = BytesUtil.bytesToIntLittle(length); - System.out.println(i); + // byte[] length = new byte[] {0x09, 0x00}; + // int i = BytesUtil.bytesToIntLittle(length); + // System.out.println(i); + + String testStr = Constants.EBIKE_HEADER; + byte[] hexBytes = stringToHexBytes(testStr, 3); + System.out.println("Hex Bytes: " + bytesToHex(hexBytes)); } /** @@ -443,7 +494,7 @@ public class BytesUtil { * @return */ public static String ascii2StrLittle(byte[] ascs) { - byte[] data = revert(ascs); + byte[] data = reverse(ascs); String asciiStr = null; try { asciiStr = new String(data, "ISO8859-1"); @@ -475,7 +526,7 @@ public class BytesUtil { * @return */ public static byte[] str2AscLittle(String str) { - return revert(str2Asc(str)); + return reverse(str2Asc(str)); } /** @@ -499,7 +550,7 @@ public class BytesUtil { * @param temp * @return */ - public static byte[] revert(byte[] temp) { + public static byte[] reverse(byte[] temp) { byte[] ret = new byte[temp.length]; for (int i = 0; i < temp.length; i++) { ret[temp.length - i - 1] = temp[i]; diff --git a/jsowell-common/src/main/java/com/jsowell/common/util/RandomUtil.java b/jsowell-common/src/main/java/com/jsowell/common/util/RandomUtil.java index 4c7a56ab4..b7e5dc469 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/util/RandomUtil.java +++ b/jsowell-common/src/main/java/com/jsowell/common/util/RandomUtil.java @@ -14,7 +14,7 @@ import java.util.Set; public class RandomUtil { private static final String SYMBOLS_NUM = "0123456789"; // 纯数字 //如果需加入字母就改成0123456789abcdefg........... - private static final String SYMBOLS_NUM_ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789"; + // private static final String SYMBOLS_NUM_ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789"; private static final Random RANDOM = new SecureRandom(); @@ -24,7 +24,7 @@ public class RandomUtil { * @return 随机数字 */ public static String getSMSVerificationCode() { - return getRandomNumber(6); + return getRandomNumberStr(6); } /** @@ -33,7 +33,7 @@ public class RandomUtil { * @param length 需要的长度 * @return 随机数 */ - public static String getRandomNumber(int length) { + public static String getRandomNumberStr(int length) { char[] nonceChars = new char[length]; //指定长度,自己可以设置 for (int index = 0; index < nonceChars.length; ++index) { nonceChars[index] = SYMBOLS_NUM.charAt(RANDOM.nextInt(SYMBOLS_NUM.length())); @@ -41,6 +41,10 @@ public class RandomUtil { return new String(nonceChars); } + public static int getRandomNumber(int length) { + return Integer.parseInt(getRandomNumberStr(length)); + } + /** * 获取一组不重复的6位数随机数 * diff --git a/jsowell-common/src/main/java/com/jsowell/common/util/YKCUtils.java b/jsowell-common/src/main/java/com/jsowell/common/util/YKCUtils.java index 9cd038c4c..28e63161b 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/util/YKCUtils.java +++ b/jsowell-common/src/main/java/com/jsowell/common/util/YKCUtils.java @@ -1,12 +1,16 @@ package com.jsowell.common.util; +import com.google.common.collect.ImmutableMap; import com.google.common.primitives.Bytes; import com.jsowell.common.constant.Constants; import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; +import com.jsowell.common.enums.ykc.ReturnCodeEnum; +import com.jsowell.common.exception.BusinessException; import lombok.extern.slf4j.Slf4j; import java.math.BigDecimal; import java.util.Arrays; +import java.util.Map; @Slf4j public class YKCUtils { @@ -67,11 +71,6 @@ public class YKCUtils { return false; } - public static void main(String[] args) { - byte[] length = new byte[]{0x22}; - System.out.println(BytesUtil.bytesToIntLittle(length)); - } - /** * 转换电压电流以及起始soc * 精确到小数点后一位;待机置零 @@ -152,4 +151,81 @@ public class YKCUtils { public static String parseVin(byte[] vinCodeByteArr) { return BytesUtil.ascii2Str(vinCodeByteArr); } + + /** + * 解析充电桩连接器编号 + * + * @param pileConnectorCode 充电桩连接器编号 + * @param totalLength 总长度 + * @param connectorOffset 连接器编号的偏移量 + * @return 包含桩编号和连接器编号的映射 + */ + private static Map parsePileConnector(String pileConnectorCode, int totalLength, int connectorOffset) { + String pileSn = StringUtils.substring(pileConnectorCode, 0, totalLength - 2); + String connectorCode = StringUtils.substring(pileConnectorCode, connectorOffset); + + return ImmutableMap.of("pileSn", pileSn, "connectorCode", connectorCode); + } + + /** + * 解析充电桩编号 + * + * @param pileConnectorCode 充电桩连接器编号 + * @return 包含桩编号和连接器编号的映射 + */ + public static Map parsePileConnectorCode(String pileConnectorCode) { + int length = pileConnectorCode.length(); + + // 如果length不等于14, 16, 8, 10, 2, 判断为错误的长度 + if (length != Constants.PILE_CONNECTOR_CODE_LENGTH_FOR_EV + && length != Constants.PILE_SN_LENGTH_FOR_EV + && length != Constants.PILE_CONNECTOR_CODE_LENGTH_FOR_EBIKE + && length != Constants.PILE_SN_LENGTH_FOR_EBIKE + && length != 2) { + throw new BusinessException(ReturnCodeEnum.CODE_DATA_LENGTH_ERROR.getValue(), "Invalid pile connector code length: " + length); + } + + if (length == Constants.PILE_CONNECTOR_CODE_LENGTH_FOR_EV) { + // 汽车桩 + return parsePileConnector(pileConnectorCode, Constants.PILE_CONNECTOR_CODE_LENGTH_FOR_EV, pileConnectorCode.length() - 2); + } else if (length == Constants.PILE_CONNECTOR_CODE_LENGTH_FOR_EBIKE) { + // 电单车 + return parsePileConnector(pileConnectorCode, Constants.PILE_CONNECTOR_CODE_LENGTH_FOR_EBIKE, pileConnectorCode.length() - 2); + } else if (length == Constants.PILE_SN_LENGTH_FOR_EV || length == Constants.PILE_SN_LENGTH_FOR_EBIKE) { + // 充电桩编号 + return ImmutableMap.of("pileSn", pileConnectorCode, "connectorCode", ""); + } else { + // 枪口号 + return ImmutableMap.of("pileSn", "", "connectorCode", pileConnectorCode); + } + } + + /** + * 获取pileSn + * @param pileConnectorCode 充电桩枪口编号 + * @return + */ + public static String getPileSn(String pileConnectorCode) { + Map map = parsePileConnectorCode(pileConnectorCode); + return map.get("pileSn"); + } + + /** + * 获取枪口号 + * @param pileConnectorCode 充电桩枪口编号 + * @return + */ + public static String getConnectorCode(String pileConnectorCode) { + Map map = parsePileConnectorCode(pileConnectorCode); + return map.get("connectorCode"); + } + + public static void main(String[] args) { + String pileConnectorCode = "8800000000000201"; + // pileConnectorCode = "1327388103"; + String pileSn = YKCUtils.getPileSn(pileConnectorCode); + System.out.println(pileSn); + String connectorCode = YKCUtils.getConnectorCode(pileConnectorCode); + System.out.println(connectorCode); + } } diff --git a/jsowell-common/src/main/java/com/jsowell/common/util/id/IdUtils.java b/jsowell-common/src/main/java/com/jsowell/common/util/id/IdUtils.java index 35489dd26..56f13ea4e 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/util/id/IdUtils.java +++ b/jsowell-common/src/main/java/com/jsowell/common/util/id/IdUtils.java @@ -87,7 +87,7 @@ public class IdUtils { public static String generateTransactionCode(String pileConnectorCode) { String timeNow = DateUtils.dateTimeNow(DateUtils.YYMMDDHHMMSS); // 随机生成一个四位整数 - String randomNumber = RandomUtil.getRandomNumber(4); + String randomNumber = RandomUtil.getRandomNumberStr(4); return pileConnectorCode + timeNow + randomNumber; } diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/decoder/StartAndLengthFieldFrameDecoder.java b/jsowell-netty/src/main/java/com/jsowell/netty/decoder/StartAndLengthFieldFrameDecoder.java index d53155360..ff1643411 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/decoder/StartAndLengthFieldFrameDecoder.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/decoder/StartAndLengthFieldFrameDecoder.java @@ -1,5 +1,6 @@ package com.jsowell.netty.decoder; +import com.jsowell.common.constant.Constants; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; @@ -47,7 +48,7 @@ public class StartAndLengthFieldFrameDecoder extends ByteToMessageDecoder { buffer.getBytes(beginReader, headerBytes, 0, HEADER_LENGTH_DNY); String header = new String(headerBytes, StandardCharsets.UTF_8); // log.info("检查包头是否是DNY, header:{}", header); - if ("DNY".equals(header)) { + if (Constants.EBIKE_HEADER.equals(header)) { // 处理 DNY 协议 decodeDnyMessage(buffer, out, beginReader); return; @@ -73,7 +74,7 @@ public class StartAndLengthFieldFrameDecoder extends ByteToMessageDecoder { byte[] headerBytes = new byte[HEADER_LENGTH_DNY]; buffer.getBytes(beginReader, headerBytes, 0, HEADER_LENGTH_DNY); String header = new String(headerBytes, StandardCharsets.UTF_8); - return "DNY".equals(header); + return Constants.EBIKE_HEADER.equals(header); } return false; } diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/DeviceGetServerTimeHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/DeviceGetServerTimeHandler.java index 2afe0e5ba..2b42144d1 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/DeviceGetServerTimeHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/DeviceGetServerTimeHandler.java @@ -3,6 +3,7 @@ package com.jsowell.netty.handler.electricbicycles; import com.alibaba.fastjson2.JSON; import com.jsowell.common.core.domain.ebike.EBikeDataProtocol; import com.jsowell.common.util.BytesUtil; +import com.jsowell.common.util.YKCUtils; import com.jsowell.netty.factory.EBikeOperateFactory; import com.jsowell.pile.domain.ebike.AbsEBikeMessage; import com.jsowell.pile.domain.ebike.EBikeCommandEnum; @@ -17,7 +18,8 @@ import org.springframework.stereotype.Component; @Slf4j @Component public class DeviceGetServerTimeHandler extends AbstractEBikeHandler { - private final String type = EBikeCommandEnum.DEVICE_GET_SERVER_TIME.getCode(); + // private final String type = EBikeCommandEnum.DEVICE_GET_SERVER_TIME.getCode(); + private final String type = YKCUtils.frameType2Str(EBikeCommandEnum.DEVICE_GET_SERVER_TIME.getBytes()); @Override public void afterPropertiesSet() throws Exception { diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/HeartbeatHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/HeartbeatHandler.java index c191d449a..3c57fa995 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/HeartbeatHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/HeartbeatHandler.java @@ -5,6 +5,7 @@ import com.jsowell.common.constant.Constants; import com.jsowell.common.core.domain.ebike.EBikeDataProtocol; import com.jsowell.common.enums.ebike.PortStatusEnum; import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.YKCUtils; import com.jsowell.netty.factory.EBikeOperateFactory; import com.jsowell.pile.domain.ebike.AbsEBikeMessage; import com.jsowell.pile.domain.ebike.EBikeCommandEnum; @@ -24,7 +25,7 @@ import java.util.List; @Slf4j @Component public class HeartbeatHandler extends AbstractEBikeHandler { - private final String type = EBikeCommandEnum.HEARTBEAT_2.getCode(); + private final String type = YKCUtils.frameType2Str(EBikeCommandEnum.HEARTBEAT_2.getBytes()); @Autowired private PileBasicInfoService pileBasicInfoService; diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/HostGetServerTimeHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/HostGetServerTimeHandler.java index 0d9bf4eee..add8ced5a 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/HostGetServerTimeHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/HostGetServerTimeHandler.java @@ -3,6 +3,7 @@ package com.jsowell.netty.handler.electricbicycles; import com.alibaba.fastjson2.JSON; import com.jsowell.common.core.domain.ebike.EBikeDataProtocol; import com.jsowell.common.util.BytesUtil; +import com.jsowell.common.util.YKCUtils; import com.jsowell.netty.factory.EBikeOperateFactory; import com.jsowell.pile.domain.ebike.AbsEBikeMessage; import com.jsowell.pile.domain.ebike.EBikeCommandEnum; @@ -17,7 +18,8 @@ import org.springframework.stereotype.Component; @Slf4j @Component public class HostGetServerTimeHandler extends AbstractEBikeHandler { - private final String type = EBikeCommandEnum.HOST_GET_SERVER_TIME.getCode(); + // private final String type = EBikeCommandEnum.HOST_GET_SERVER_TIME.getCode(); + private final String type = YKCUtils.frameType2Str(EBikeCommandEnum.HOST_GET_SERVER_TIME.getBytes()); @Override public void afterPropertiesSet() throws Exception { diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/PowerHeartbeatHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/PowerHeartbeatHandler.java new file mode 100644 index 000000000..35d4d942e --- /dev/null +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/PowerHeartbeatHandler.java @@ -0,0 +1,94 @@ +package com.jsowell.netty.handler.electricbicycles; + +import com.alibaba.fastjson2.JSON; +import com.jsowell.common.constant.Constants; +import com.jsowell.common.core.domain.ebike.EBikeDataProtocol; +import com.jsowell.common.enums.ebike.PortStatusEnum; +import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.YKCUtils; +import com.jsowell.netty.factory.EBikeOperateFactory; +import com.jsowell.pile.domain.ebike.AbsEBikeMessage; +import com.jsowell.pile.domain.ebike.EBikeCommandEnum; +import com.jsowell.pile.domain.ebike.deviceupload.EBikeMessageCmd06; +import com.jsowell.pile.domain.ebike.deviceupload.EBikeMessageCmd21; +import com.jsowell.pile.service.PileConnectorInfoService; +import io.netty.channel.ChannelHandlerContext; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 端口充电时功率心跳包 + */ +@Slf4j +@Component +public class PowerHeartbeatHandler extends AbstractEBikeHandler { + private final String type = YKCUtils.frameType2Str(EBikeCommandEnum.POWER_HEARTBEAT.getBytes()); + + @Autowired + private PileConnectorInfoService pileConnectorInfoService; + + @Override + public void afterPropertiesSet() throws Exception { + EBikeOperateFactory.register(type, this); + } + + /** + * 执行逻辑 + * 有应答 + * + * @param dataProtocol + * @param ctx + */ + @Override + public byte[] supplyProcess(EBikeDataProtocol dataProtocol, ChannelHandlerContext ctx) { + // 解析字节数组 + EBikeMessageCmd06 message = (EBikeMessageCmd06) AbsEBikeMessage.parseMessage(dataProtocol.getBytes()); + // 保存时间 + saveLastTimeAndCheckChannel(message.getPhysicalId() + "", ctx); + + EBikeMessageCmd06.PowerHeartbeat powerHeartbeat = message.getPowerHeartbeat(); + log.debug("端口充电时功率心跳包:{}", JSON.toJSONString(message)); + + // updatePileStatus(message); + + return getResult(dataProtocol, Constants.zeroByteArray); + } + + /** + * 更新充电桩状态 + * @param message + */ + private void updatePileStatus(EBikeMessageCmd21 message) { + String pileSn = message.getPhysicalId() + ""; + EBikeMessageCmd21.DeviceHeartbeat deviceHeartbeat = message.getDeviceHeartbeat(); + int portNumber = deviceHeartbeat.getPortNumber(); + List portStatus = deviceHeartbeat.getPortStatus(); + for (int i = 0; i < portNumber; i++) { + // 组装pile_connector_info表数据 + String connectorCode = String.format("%1$02d", i + 1); + String pileConnectorCode = pileSn + connectorCode; + // 电单车协议状态 + String eBikeStatus = portStatus.get(i); + pileConnectorInfoService.updateConnectorStatus(pileConnectorCode, eBikeStatusTransformDBStatus(eBikeStatus)); + } + } + + /** + * 电单车协议状态转换为数据库状态 + * @param eBikeStatus + * @return + */ + private String eBikeStatusTransformDBStatus(String eBikeStatus) { + String dbStatus = Constants.ZERO; // 默认0-离网 + if (StringUtils.isNotBlank(eBikeStatus)) { + PortStatusEnum enumByValue = PortStatusEnum.getEnumByValue(Integer.parseInt(eBikeStatus)); + if (enumByValue != null) { + dbStatus = enumByValue.getDbStatus(); + } + } + return dbStatus; + } +} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/RegistrationHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/RegistrationHandler.java index a9a6ebb7c..f0ce4eb2a 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/RegistrationHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/RegistrationHandler.java @@ -3,6 +3,7 @@ package com.jsowell.netty.handler.electricbicycles; import com.alibaba.fastjson2.JSON; import com.jsowell.common.constant.Constants; import com.jsowell.common.core.domain.ebike.EBikeDataProtocol; +import com.jsowell.common.util.YKCUtils; import com.jsowell.netty.factory.EBikeOperateFactory; import com.jsowell.pile.domain.ebike.AbsEBikeMessage; import com.jsowell.pile.domain.ebike.EBikeCommandEnum; @@ -19,7 +20,8 @@ import org.springframework.stereotype.Component; @Slf4j @Component public class RegistrationHandler extends AbstractEBikeHandler { - private final String type = EBikeCommandEnum.REGISTRATION.getCode(); + // private final String type = EBikeCommandEnum.REGISTRATION.getCode(); + private final String type = YKCUtils.frameType2Str(EBikeCommandEnum.REGISTRATION.getBytes()); @Autowired private PileBasicInfoService pileBasicInfoService; diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/SettlementUploadHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/SettlementUploadHandler.java index 85d9cb3ba..2cb4dba1d 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/SettlementUploadHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/electricbicycles/SettlementUploadHandler.java @@ -1,22 +1,59 @@ package com.jsowell.netty.handler.electricbicycles; import com.alibaba.fastjson2.JSON; +import com.jsowell.common.constant.Constants; import com.jsowell.common.core.domain.ebike.EBikeDataProtocol; +import com.jsowell.common.core.redis.RedisCache; +import com.jsowell.common.enums.ykc.EBikeChargingStopReasonEnum; +import com.jsowell.common.enums.ykc.OrderStatusEnum; +import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.YKCUtils; +import com.jsowell.common.util.id.IdUtils; import com.jsowell.netty.factory.EBikeOperateFactory; +import com.jsowell.pile.domain.OrderBasicInfo; import com.jsowell.pile.domain.ebike.AbsEBikeMessage; import com.jsowell.pile.domain.ebike.EBikeCommandEnum; import com.jsowell.pile.domain.ebike.deviceupload.EBikeMessageCmd03; +import com.jsowell.pile.service.OrderBasicInfoService; +import com.jsowell.pile.service.PersonalChargingRecordService; +import com.jsowell.pile.service.PileBasicInfoService; +import com.jsowell.pile.service.PileMerchantInfoService; +import com.jsowell.pile.service.programlogic.AbstractProgramLogic; +import com.jsowell.pile.service.programlogic.ProgramLogicFactory; +import com.jsowell.thirdparty.common.CommonService; import io.netty.channel.ChannelHandlerContext; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.Date; + /** * 结算消费信息上传 */ @Slf4j @Component public class SettlementUploadHandler extends AbstractEBikeHandler { - private final String type = EBikeCommandEnum.SETTLEMENT_UPLOAD.getCode(); + // private final String type = EBikeCommandEnum.SETTLEMENT_UPLOAD.getCode(); + private final String type = YKCUtils.frameType2Str(EBikeCommandEnum.SETTLEMENT_UPLOAD.getBytes()); + + @Autowired + private RedisCache redisCache; + + @Autowired + private OrderBasicInfoService orderBasicInfoService; + + @Autowired + private PileMerchantInfoService pileMerchantInfoService; + + @Autowired + private CommonService commonService; + + @Autowired + private PileBasicInfoService pileBasicInfoService; + + @Autowired + private PersonalChargingRecordService personalChargingRecordService; @Override public void afterPropertiesSet() throws Exception { @@ -38,7 +75,65 @@ public class SettlementUploadHandler extends AbstractEBikeHandler { saveLastTimeAndCheckChannel(message.getPhysicalId() + "", ctx); EBikeMessageCmd03.SettlementInfo settlementInfo = message.getSettlementInfo(); log.info("结算消费信息上传:{}", JSON.toJSONString(message)); - return null; + + int transactionCode = settlementInfo.getOrderNumber(); + // 处理订单加锁/结算电单车订单 + String lockKey = "settle_order_" + transactionCode; + String uuid = IdUtils.fastUUID(); + try { + // redis锁 + Boolean isLock = redisCache.lock(lockKey, uuid, 1500); + if (isLock) { + // processOrder(message); + } + } catch (Exception e) { + log.error("处理订单transactionCode:{}, 发生异常", transactionCode, e); + } finally { + if (uuid.equals(redisCache.getCacheObject(lockKey).toString())) { + redisCache.unLock(lockKey); + } + } + + // 返回结果 + return getResult(dataProtocol, Constants.zeroByteArray); } + /** + * 收到交易记录 处理订单 + */ + private void processOrder(EBikeMessageCmd03 message) { + EBikeMessageCmd03.SettlementInfo settlementInfo = message.getSettlementInfo(); + String transactionCode = settlementInfo.getOrderNumber() + ""; + // 根据交易流水号查询订单信息 + OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByTransactionCode(transactionCode); + if (orderBasicInfo != null) { + // 平台存在订单 + int stopReason = settlementInfo.getStopReason(); + orderBasicInfo.setReason(EBikeChargingStopReasonEnum.getMsgByCode(stopReason)); + // 如果订单状态为 异常,则改为 待结算 + if (StringUtils.equals(OrderStatusEnum.ABNORMAL.getValue(), orderBasicInfo.getOrderStatus())) { + orderBasicInfo.setOrderStatus(OrderStatusEnum.STAY_SETTLEMENT.getValue()); + } + + // 校验结束时间 + if (orderBasicInfo.getChargeEndTime().before(orderBasicInfo.getChargeStartTime())) { + orderBasicInfo.setChargeEndTime(new Date()); + } + + orderBasicInfoService.updateOrderBasicInfo(orderBasicInfo); + + // 重新查询订单信息 + orderBasicInfo = orderBasicInfoService.getOrderInfoByTransactionCode(transactionCode); + + // 结算订单操作 + try { + // 新逻辑 + String mode = pileMerchantInfoService.getDelayModeByMerchantId(orderBasicInfo.getMerchantId()); + AbstractProgramLogic orderLogic = ProgramLogicFactory.getProgramLogic(mode); + orderLogic.settleOrderForEBike(message, orderBasicInfo); + } catch (Exception e) { + log.error("结算订单发生异常 orderCode:{}", orderBasicInfo.getOrderCode(), e); + } + } + } } diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/server/electricbicycles/ElectricBicyclesServerHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/server/electricbicycles/ElectricBicyclesServerHandler.java index 2cd48363c..bc89f24d8 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/server/electricbicycles/ElectricBicyclesServerHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/server/electricbicycles/ElectricBicyclesServerHandler.java @@ -64,7 +64,7 @@ public class ElectricBicyclesServerHandler extends ChannelInboundHandlerAdapter // 处理数据 byte[] response = eBikeService.process(msg, ctx); if (Objects.nonNull(response)) { - log.info("[响应数据]:{}", BytesUtil.binary(response, 16)); + log.info("[电单车===>响应数据]:{}", BytesUtil.binary(response, 16)); // 响应客户端 ByteBuf buffer = ctx.alloc().buffer().writeBytes(response); // this.channelWrite(channel.id(), buffer); diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/service/electricbicycles/impl/EBikeBusinessServiceImpl.java b/jsowell-netty/src/main/java/com/jsowell/netty/service/electricbicycles/impl/EBikeBusinessServiceImpl.java index 92c260183..690666cd4 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/service/electricbicycles/impl/EBikeBusinessServiceImpl.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/service/electricbicycles/impl/EBikeBusinessServiceImpl.java @@ -6,9 +6,11 @@ import com.jsowell.common.enums.ykc.PileChannelEntity; import com.jsowell.common.enums.ykc.PileConnectorDataBaseStatusEnum; import com.jsowell.common.util.BytesUtil; import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.YKCUtils; import com.jsowell.netty.factory.EBikeOperateFactory; import com.jsowell.netty.handler.electricbicycles.AbstractEBikeHandler; import com.jsowell.netty.service.electricbicycles.EBikeBusinessService; +import com.jsowell.pile.domain.ebike.EBikeCommandEnum; import com.jsowell.pile.service.OrderBasicInfoService; import com.jsowell.pile.service.PileConnectorInfoService; import com.jsowell.pile.service.PileMsgRecordService; @@ -35,8 +37,9 @@ public class EBikeBusinessServiceImpl implements EBikeBusinessService { public byte[] process(byte[] msg, ChannelHandlerContext ctx) { EBikeDataProtocol eBikeDataProtocol = new EBikeDataProtocol(msg); // 获取帧类型 - String command = BytesUtil.bin2HexStr(eBikeDataProtocol.getCommand()); - log.info("收到消息, channelId:{}, 指令:{}, msg:{}", ctx.channel().id().toString(), command, BytesUtil.binary(msg, 16)); + String command = YKCUtils.frameType2Str(eBikeDataProtocol.getCommand()); + log.info("电单车===>收到消息, channelId:{}, 指令:{}, 指令名称:{}, msg:{}", ctx.channel().id().toString(), command, + EBikeCommandEnum.getDescByCode(BytesUtil.bytesToIntLittle(eBikeDataProtocol.getCommand())), BytesUtil.binary(msg, 16)); // 获取业务处理handler AbstractEBikeHandler invokeStrategy = EBikeOperateFactory.getInvokeStrategy(command); if (invokeStrategy != null) { diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/AbsEBikeMessage.java b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/AbsEBikeMessage.java index 0546ba61d..693179245 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/AbsEBikeMessage.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/AbsEBikeMessage.java @@ -3,34 +3,28 @@ package com.jsowell.pile.domain.ebike; import com.jsowell.common.YouDianUtils; import com.jsowell.common.util.BytesUtil; import com.jsowell.pile.domain.ebike.deviceupload.*; -import lombok.Getter; -import lombok.Setter; +import lombok.*; import java.nio.charset.StandardCharsets; import java.util.Arrays; @Getter @Setter -public abstract class AbsEBikeMessage { - private String header; // 包头 (3字节) - private int length; // 长度 (2字节) - private int physicalId; // 物理ID (4字节) - private int messageId; // 消息ID (2字节) - private String command; // 命令 (1字节) - private Object payload; // 数据 (n字节) - private int checksum; // 校验 (2字节) +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AbsEBikeMessage { + protected String header; // 包头 (3字节) + protected int length; // 长度 (2字节) + protected int physicalId; // 物理ID (4字节) + protected int messageId; // 消息ID (2字节) + protected String command; // 命令 (1字节) + protected Object payload; // 数据 (n字节) + protected int checksum; // 校验 (2字节) - public AbsEBikeMessage(String header, int length, int physicalId, int messageId, String command, Object payload, int checksum) { - this.header = header; - this.length = length; - this.physicalId = physicalId; - this.messageId = messageId; - this.command = command; - this.payload = payload; - this.checksum = checksum; - } + public void parsePayload(byte[] dataBytes) { - public abstract void parsePayload(byte[] dataBytes); + }; private static AbsEBikeMessage createMessageInstance(String command, String header, int length, int physicalId, int messageId, int checksum, byte[] dataBytes) { switch (command) { @@ -103,35 +97,50 @@ public abstract class AbsEBikeMessage { } } - public abstract byte[] getMessageBytes(); + public byte[] getMessageBytes() { + return null; + }; public static void main(String[] args) { - String s = "44 4e 59 00 0d 3b 37 ab 04 b9 00 22 54 33 cc 66 03 7b".replace(" ", ""); + String s = "444e592300198bca00a6158233300000000031300013273881012409031435319214300030002107"; + String msg82 = "44 4E 59 26 00 3B 37 AB 04 02 00 82 00 64 01 00 00 01 01 00 00 12 34 56 78 12 34 56 78 12 34 56 78 12 34 56 78 80 70 88 13 F8 08"; + s = s.replace(" ", ""); byte[] messageBytes = BytesUtil.hexStringToByteArray(s); // 读取包头 byte[] headerBytes = Arrays.copyOfRange(messageBytes, 0, 3); String header = new String(headerBytes, StandardCharsets.UTF_8); System.out.println("header: " + header); + // byte[] header2 = header.getBytes(); + // System.out.println("反序列header: " + header2); + // 读取长度 byte[] lengthBytes = Arrays.copyOfRange(messageBytes, 3, 5); int length = BytesUtil.bytesToIntLittle(lengthBytes); System.out.println("length: " + length); + // byte[] length2 = BytesUtil.intToBytesLittle(length); + // System.out.println("反序列length: " + length2); // 读取物理ID byte[] physicalIdBytes = Arrays.copyOfRange(messageBytes, 5, 9); int physicalId = BytesUtil.bytesToIntLittle(physicalIdBytes); System.out.println("physicalId: " + physicalId); + // byte[] physicalId2 = BytesUtil.intToBytesLittle(physicalId, 4); + // System.out.println("反序列physicalId: " + physicalId2); // 读取消息ID byte[] messageIdBytes = Arrays.copyOfRange(messageBytes, 9, 11); int messageId = BytesUtil.bytesToIntLittle(messageIdBytes); System.out.println("messageId: " + messageId); + // byte[] messageId2 = BytesUtil.intToBytesLittle(messageId); + // System.out.println("反序列messageId: " + messageId2); // 读取命令 byte commandByte = messageBytes[11]; String command = BytesUtil.bcd2StrLittle(new byte[]{commandByte}); System.out.println("command: " + command); + // byte[] command2 = BytesUtil.str2Bcd(command); + // System.out.println("反序列command: " + command2); // 读取数据 byte[] dataBytes = Arrays.copyOfRange(messageBytes, 12, messageBytes.length - 2); @@ -142,6 +151,9 @@ public abstract class AbsEBikeMessage { byte[] checksumBytes = Arrays.copyOfRange(messageBytes, messageBytes.length - 2, messageBytes.length); int checksum = BytesUtil.bytesToIntLittle(checksumBytes); System.out.println("checksum: " + checksum); + + // byte[] concat = Bytes.concat(header2, length2, physicalId2, messageId2, command2); + // System.out.println("concat: " + BytesUtil.printHexBinary(concat)); } } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/EBikeCommandEnum.java b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/EBikeCommandEnum.java index 36196b3ef..abcb99812 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/EBikeCommandEnum.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/EBikeCommandEnum.java @@ -1,6 +1,8 @@ package com.jsowell.pile.domain.ebike; +import com.jsowell.common.util.BytesUtil; import com.jsowell.pile.domain.ebike.deviceupload.*; +import com.jsowell.pile.domain.ebike.serversend.EBikeMessageCmd82; import lombok.extern.slf4j.Slf4j; /** @@ -9,32 +11,28 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public enum EBikeCommandEnum { // HEARTBEAT("01", "设备心跳包"), - HOST_GET_SERVER_TIME("12", "主机获取服务器时间", EBikeMessageCmd12.class), - REGISTRATION("20", "设备注册包", EBikeMessageCmd20.class), - DEVICE_GET_SERVER_TIME("22", "设备获取服务器时间", EBikeMessageCmd22.class), - HEARTBEAT_2("21", "设备心跳包", EBikeMessageCmd21.class), - CARD_OPERATION("02", "刷卡操作", EBikeMessageCmd02.class), - SETTLEMENT_UPLOAD("03", "结算消费信息上传", EBikeMessageCmd03.class), - CHARGE_PORT_CONFIRMATION("04", "充电端口订单确认", EBikeMessageCmd04.class), - POWER_HEARTBEAT("06", "端口充电时功率心跳包", EBikeMessageCmd06.class), - // CHARGER_HEARTBEAT("41", "充电柜专有心跳包", EBikeMessageCmd41.class), - // ALARM_PUSH("42", "报警推送指令", EBikeMessageCmd20.class), - // CHARGE_COMPLETE("43", "充电完成通知,但不结算", EBikeMessageCmd20.class), - // PORT_PUSH("44", "端口推送指令", EBikeMessageCmd20.class); - + HOST_GET_SERVER_TIME(0x12, "主机获取服务器时间", EBikeMessageCmd12.class), + REGISTRATION(0x20, "设备注册包", EBikeMessageCmd20.class), + DEVICE_GET_SERVER_TIME(0x22, "设备获取服务器时间", EBikeMessageCmd22.class), + HEARTBEAT_2(0x21, "设备心跳包", EBikeMessageCmd21.class), + CARD_OPERATION(0x02, "刷卡操作", EBikeMessageCmd02.class), + SETTLEMENT_UPLOAD(0x03, "结算消费信息上传", EBikeMessageCmd03.class), + CHARGE_PORT_CONFIRMATION(0x04, "充电端口订单确认", EBikeMessageCmd04.class), + POWER_HEARTBEAT(0x06, "端口充电时功率心跳包", EBikeMessageCmd06.class), + REMOTE_CONTROL_COMMAND(0x82, "服务器开始、停止充电操作", EBikeMessageCmd82.class), ; - EBikeCommandEnum(String code, String desc, Class msgClass) { + EBikeCommandEnum(int code, String desc, Class msgClass) { this.code = code; this.desc = desc; this.msgClass = msgClass; } - private final String code; // 帧类型code + private final int code; // 帧类型code private final String desc; // 帧类型名称 private final Class msgClass; - public String getCode() { + public int getCode() { return code; } @@ -46,10 +44,15 @@ public enum EBikeCommandEnum { return msgClass; } - public static Class getMsgClassByCode(String code) { + public byte[] getBytes() { + return BytesUtil.intToBytesLittle(code, 1); + } + + // 根据code获取desc + public static String getDescByCode(int code) { for (EBikeCommandEnum e : EBikeCommandEnum.values()) { - if (e.getCode().equals(code)) { - return e.getMsgClass(); + if (e.getCode() == code) { + return e.getDesc(); } } return null; diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/deviceupload/EBikeMessageCmd03.java b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/deviceupload/EBikeMessageCmd03.java index 351f0d836..8b7d40a3a 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/deviceupload/EBikeMessageCmd03.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/deviceupload/EBikeMessageCmd03.java @@ -34,28 +34,28 @@ public class EBikeMessageCmd03 extends AbsEBikeMessage { @Data public static class SettlementInfo { - private String chargingDuration; // 充电时长, 单位:"秒" - private String maxPower; // 最大功率, 单位:"0.1W" - private String consumedEnergy; // 耗电量, 单位:"0.01度" - private String portNumber; // 端口号 - private String startMode; // 在线/离线启动/验证码 - private String cardNumberOrVerificationCode; // 卡号/验证码 - private String stopReason; // 停止原因 - private String orderNumber; // 订单编号 - private String secondMaxPower; // 第二最大功率 + private int chargingDuration; // 充电时长, 单位:"秒" + private int maxPower; // 最大功率, 单位:"0.1W" + private int consumedEnergy; // 耗电量, 单位:"0.01度" + private int portNumber; // 端口号 + private int startMode; // 在线/离线启动/验证码 + private int cardNumberOrVerificationCode; // 卡号/验证码 + private int stopReason; // 停止原因 + private int orderNumber; // 订单编号 + private int secondMaxPower; // 第二最大功率 // private String timestamp; // 时间戳 上发指令当时的时间,有时候不准确,该字段属于调试使用,服务器无需关心此字段 // private String placeholderDuration; // 占位时长 充电柜专用,其他设备忽略此字段 表示充满后占用设备的时长,单位为分钟 public SettlementInfo(byte[] dataBytes) { - this.chargingDuration = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 0, 2)) + ""; - this.maxPower = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 2, 4)) + ""; - this.consumedEnergy = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 4, 6)) + ""; - this.portNumber = BytesUtil.bcd2StrLittle(new byte[]{dataBytes[6]}); - this.startMode = BytesUtil.bcd2StrLittle(new byte[]{dataBytes[7]}); - this.cardNumberOrVerificationCode = BytesUtil.bcd2StrLittle(Arrays.copyOfRange(dataBytes, 8, 12)); - this.stopReason = BytesUtil.bcd2StrLittle(new byte[]{dataBytes[12]}); - this.orderNumber = BytesUtil.bcd2StrLittle(Arrays.copyOfRange(dataBytes, 13, 29)); - this.secondMaxPower = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 29, 31)) + ""; + this.chargingDuration = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 0, 2)); + this.maxPower = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 2, 4)); + this.consumedEnergy = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 4, 6)); + this.portNumber = BytesUtil.bytesToIntLittle(new byte[]{dataBytes[6]}); + this.startMode = BytesUtil.bytesToIntLittle(new byte[]{dataBytes[7]}); + this.cardNumberOrVerificationCode = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 8, 12)); + this.stopReason = BytesUtil.bytesToIntLittle(new byte[]{dataBytes[12]}); + this.orderNumber = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 13, 29)); + this.secondMaxPower = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 29, 31)); // this.timestamp = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 31, 35)) + ""; // this.placeholderDuration = BytesUtil.bytesToIntLittle(Arrays.copyOfRange(dataBytes, 35, 37)) + ""; } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/serversend/EBikeMessageCmd81.java b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/serversend/EBikeMessageCmd81.java index ef04ece8f..a74265f9f 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/serversend/EBikeMessageCmd81.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/serversend/EBikeMessageCmd81.java @@ -9,10 +9,6 @@ import com.jsowell.pile.domain.ebike.AbsEBikeMessage; */ public class EBikeMessageCmd81 extends AbsEBikeMessage { - public EBikeMessageCmd81(String header, int length, int physicalId, int messageId, String command, Object payload, int checksum) { - super(header, length, physicalId, messageId, command, payload, checksum); - } - @Override public void parsePayload(byte[] dataBytes) { diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/serversend/EBikeMessageCmd82.java b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/serversend/EBikeMessageCmd82.java index 671f8a513..b82c28e5d 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/serversend/EBikeMessageCmd82.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ebike/serversend/EBikeMessageCmd82.java @@ -1,106 +1,194 @@ package com.jsowell.pile.domain.ebike.serversend; +import com.google.common.primitives.Bytes; +import com.jsowell.common.YouDianUtils; +import com.jsowell.common.constant.Constants; import com.jsowell.common.util.BytesUtil; import com.jsowell.pile.domain.ebike.AbsEBikeMessage; -import lombok.Getter; -import lombok.Setter; +import lombok.*; import java.util.Arrays; /** * 服务器开始、停止充电操作(82指令) */ +@Data +@NoArgsConstructor +@AllArgsConstructor public class EBikeMessageCmd82 extends AbsEBikeMessage { - private SpecificData specificData; - - public EBikeMessageCmd82(String header, int length, int physicalId, int messageId, String command, Object payload, int checksum, SpecificData specificData) { - super(header, length, physicalId, messageId, command, payload, checksum); - this.specificData = specificData; - } + private SpecificData data; @Override public void parsePayload(byte[] dataBytes) { - this.specificData = new SpecificData(dataBytes); + this.data = new SpecificData(dataBytes); + } + + public static void main(String[] args) { + int i = 0x82; + byte[] commandBytes = new byte[]{(byte) i}; + System.out.println(BytesUtil.bcd2StrLittle(commandBytes)); + int i2 = 82; + byte[] commandBytes2 = new byte[]{(byte) i2}; + System.out.println(BytesUtil.bcd2StrLittle(commandBytes2)); } @Override public byte[] getMessageBytes() { - return new byte[0]; + // 包头 + byte[] headerBytes = BytesUtil.stringToHexBytes(Constants.EBIKE_HEADER, 3); + // 物理ID + byte[] physicalIdBytes = YouDianUtils.getPhysicalIdBytes(physicalId); + // 消息ID + byte[] messageIdBytes = BytesUtil.intToBytesLittle(messageId, 2); + // 命令 + // byte[] commandBytes = BytesUtil.intToBytesLittle(Integer.parseInt(command), 1); + byte[] commandBytes = new byte[]{(byte) 0x82}; + // 数据 + byte[] payloadBytes = data.getBytes(); + // 长度 物理ID+消息ID+命令+数据(n) +校验(2),每包最多256字节 + byte[] lengthBytes = BytesUtil.intToBytesLittle(9 + payloadBytes.length); + // 拼接 + byte[] concat = Bytes.concat(headerBytes, lengthBytes, physicalIdBytes, messageIdBytes, commandBytes, payloadBytes); + // 校验和 + byte[] checksumBytes = YouDianUtils.getCheckFieldBytes(concat); + return Bytes.concat(concat, checksumBytes); } - public SpecificData getSpecificData() { - return specificData; + public SpecificData getData() { + return data; } @Getter @Setter + @NoArgsConstructor public static class SpecificData { - private String rateMode; // 费率模式 (1字节) - private String balanceOrValidity; // 余额/有效期 (4字节) - private String portNumber; // 端口号 (1字节) - private String chargeCommand; // 充电命令 (1字节) - private String chargeDurationOrPower; // 充电时长/电量 (2字节) - private String orderNumber; // 订单编号 (16字节) - private String maxChargeDuration; // 最大充电时长 (2字节) - private String overloadPower; // 过载功率 (2字节) - private String qrCodeLight; // 二维码灯 (1字节) - private String longChargeMode; // 长充模式 (1字节) - private String extraFloatChargeTime; // 额外浮充时间 (2字节) - private String skipShortCircuitDetection; // 是否跳过短路检测 (1字节) - private String noUserPullOutCheck; // 不判断用户拔出 (1字节) - private String forceAutoStopWhenFull; // 强制带充满自停 (1字节) - private String fullChargePower; // 充满功率 (1字节) - private String maxFullChargePowerCheckTime; // 充满功率最长判断时间 (1字节) + // 费率模式:=0计时,=1包月,=2计量,=3计次。包月、计次默认充满自停,计时、计量可手动设置时长和电量 + private int rateMode; // 费率模式 (1字节) + + // 余额/有效期:设备仅仅用于语音播报作用,当费率模式为计时、计量、计次时,数据为余额;当费率模式为包月时,数据为有效期(时间戳), 大于100000000这个值会当成时间报有效期 + private int balanceOrValidity; // 余额/有效期 (4字节) + + // 端口号:指充电桩的插口号,端口号从0开始,如0x00-0x0F则代表第1路-第16路,0x00=第1路,0x09=第十路,0x0A=第十一路,FF=设备智能选择端口(服务器下发) + private int portNumber; // 端口号 (指实际端口号, 发指令的时候自动转换为桩能识别的byte字节) + + // 充电命令=0(停止充电)(远程停止充电需要下发对当前正在充电的订单号,如果订单号对不上则无法远程停止),=1(开始充电)设备充电与否依据此字段 + private int chargeCommand; // 充电命令 (1字节) + + // 告知设备的充电时长/电量, 如是0x0000则说明是充满自停, 其他数值则按照时长/电量充电, 且充满不会自停, + private int chargeTimeOrPower; // 充电时长/电量 (2字节) + + // 生成给桩的交易流水号, 桩协议叫订单编号 + private String transactionCode; // 订单编号 (16字节) + + // 最大充电时长、过载功率:(只对当前端口当前订单有效,不影响其他端口)动态设置此参数,如果参数为0表示不修改,会使用设备的设置值,默认10小时 + private int maxChargeTime; // 最大充电时长 (2字节) + private int overloadPower; // 过载功率 (2字节) + + // 二维码灯:0=打开,1=关闭,针对部分有二维码灯的设备有效。此设置是针对下一次插头插入时是否点亮二维码背光灯,保存在内存中,断电重启后就会失效 + private int qrCodeLight; // 二维码灯 (1字节) + + // 长充模式:(特殊需求,正常情况不需开启,传0 即可) + private int longChargeMode; // 长充模式 (1字节) + + // 额外浮充时间:(特殊需求,正常情况不需开启,传0 即可),即额外增加的浮充时间,单位秒,如果下发的是0xFFFF,则为取消浮充,且检测绿灯统一改为5分钟 + private int extraFloatChargeTime; // 额外浮充时间 (2字节) + private int skipShortCircuitDetection; // 是否跳过短路检测 (1字节) + private int noUserPullOutCheck; // 不判断用户拔出 (1字节) + private int forceAutoStopWhenFull; // 强制带充满自停 (1字节) + private int fullChargePower; // 充满功率 (1字节) + private int maxFullChargePowerCheckTime; // 充满功率最长判断时间 (1字节) public SpecificData(byte[] dataBytes) { byte rateModeBytes = dataBytes[0]; - this.rateMode = BytesUtil.bcd2StrLittle(new byte[]{rateModeBytes}); + this.rateMode = BytesUtil.bytesToIntLittle(new byte[]{rateModeBytes}); byte[] balanceOrValidityBytes = Arrays.copyOfRange(dataBytes, 1, 5); - this.balanceOrValidity = BytesUtil.bcd2StrLittle(balanceOrValidityBytes); + this.balanceOrValidity = BytesUtil.bytesToIntLittle(balanceOrValidityBytes); byte portNumberBytes = dataBytes[5]; - this.portNumber = BytesUtil.bcd2StrLittle(new byte[]{portNumberBytes}); + this.portNumber = BytesUtil.bytesToIntLittle(new byte[]{portNumberBytes}); byte chargeCommandBytes = dataBytes[6]; - this.chargeCommand = BytesUtil.bcd2StrLittle(new byte[]{chargeCommandBytes}); + this.chargeCommand = BytesUtil.bytesToIntLittle(new byte[]{chargeCommandBytes}); byte[] chargeDurationOrPowerBytes = Arrays.copyOfRange(dataBytes, 7, 9); - this.chargeDurationOrPower = BytesUtil.bcd2StrLittle(chargeDurationOrPowerBytes); + this.chargeTimeOrPower = BytesUtil.bytesToIntLittle(chargeDurationOrPowerBytes); byte[] orderNumberBytes = Arrays.copyOfRange(dataBytes, 9, 25); - this.orderNumber = BytesUtil.bcd2StrLittle(orderNumberBytes); + this.transactionCode = BytesUtil.bcd2StrLittle(orderNumberBytes); byte[] maxChargeDurationBytes = Arrays.copyOfRange(dataBytes, 25, 27); - this.maxChargeDuration = BytesUtil.bcd2StrLittle(maxChargeDurationBytes); + this.maxChargeTime = BytesUtil.bytesToIntLittle(maxChargeDurationBytes); byte[] overloadPowerBytes = Arrays.copyOfRange(dataBytes, 27, 29); - this.overloadPower = BytesUtil.bcd2StrLittle(overloadPowerBytes); + this.overloadPower = BytesUtil.bytesToIntLittle(overloadPowerBytes); byte qrCodeLightBytes = dataBytes[29]; - this.qrCodeLight = BytesUtil.bcd2StrLittle(new byte[]{qrCodeLightBytes}); + this.qrCodeLight = BytesUtil.bytesToIntLittle(new byte[]{qrCodeLightBytes}); byte longChargeModeBytes = dataBytes[30]; - this.longChargeMode = BytesUtil.bcd2StrLittle(new byte[]{longChargeModeBytes}); + this.longChargeMode = BytesUtil.bytesToIntLittle(new byte[]{longChargeModeBytes}); byte[] extraFloatChargeTimeBytes = Arrays.copyOfRange(dataBytes, 31, 33); - this.extraFloatChargeTime = BytesUtil.bcd2StrLittle(extraFloatChargeTimeBytes); + this.extraFloatChargeTime = BytesUtil.bytesToIntLittle(extraFloatChargeTimeBytes); byte skipShortCircuitDetectionBytes = dataBytes[33]; - this.skipShortCircuitDetection = BytesUtil.bcd2StrLittle(new byte[]{skipShortCircuitDetectionBytes}); + this.skipShortCircuitDetection = BytesUtil.bytesToIntLittle(new byte[]{skipShortCircuitDetectionBytes}); byte noUserPullOutCheckBytes = dataBytes[34]; - this.noUserPullOutCheck = BytesUtil.bcd2StrLittle(new byte[]{noUserPullOutCheckBytes}); + this.noUserPullOutCheck = BytesUtil.bytesToIntLittle(new byte[]{noUserPullOutCheckBytes}); byte forceAutoStopWhenFullByte = dataBytes[35]; - this.forceAutoStopWhenFull = BytesUtil.bcd2StrLittle(new byte[]{forceAutoStopWhenFullByte}); + this.forceAutoStopWhenFull = BytesUtil.bytesToIntLittle(new byte[]{forceAutoStopWhenFullByte}); byte fullChargePowerBytes = dataBytes[36]; - this.fullChargePower = BytesUtil.bcd2StrLittle(new byte[]{fullChargePowerBytes}); + this.fullChargePower = BytesUtil.bytesToIntLittle(new byte[]{fullChargePowerBytes}); byte maxFullChargePowerCheckTimeBytes = dataBytes[37]; - this.maxFullChargePowerCheckTime = BytesUtil.bcd2StrLittle(new byte[]{maxFullChargePowerCheckTimeBytes}); + this.maxFullChargePowerCheckTime = BytesUtil.bytesToIntLittle(new byte[]{maxFullChargePowerCheckTimeBytes}); + } + + // 获取字节数组 + public byte[] getBytes() { + // 费率模式 + byte[] rateModeBytes = BytesUtil.intToBytesLittle(rateMode, 1); + // 余额/有效期 + byte[] balanceOrValidityBytes = BytesUtil.intToBytesLittle(balanceOrValidity, 4); + // 端口号 + byte[] portNumberBytes = YouDianUtils.convertPortNumberToBytes(portNumber); + // 充电命令 + byte[] chargeCommandBytes = BytesUtil.intToBytesLittle(chargeCommand, 1); + // 充电时长/电量 + byte[] chargeDurationOrPowerBytes = BytesUtil.intToBytesLittle(chargeTimeOrPower, 2); + // 订单编号 + byte[] orderNumberBytes = BytesUtil.ensureLength(BytesUtil.str2Bcd(transactionCode), 16); + // 最大充电时长 + byte[] maxChargeDurationBytes = BytesUtil.intToBytesLittle(maxChargeTime, 2); + // 过载功率 + byte[] overloadPowerBytes = BytesUtil.intToBytesLittle(overloadPower, 2); + // 二维码灯 + byte[] qrCodeLightBytes = BytesUtil.intToBytesLittle(qrCodeLight, 1); + // 长充模式 + // byte[] longChargeModeBytes = BytesUtil.stringToHexBytes(longChargeMode, 1); + // 额外浮充时间 + // byte[] extraFloatChargeTimeBytes = BytesUtil.stringToHexBytes(extraFloatChargeTime, 2); + // 是否跳过短路检测 + // byte[] skipShortCircuitDetectionBytes = BytesUtil.stringToHexBytes(skipShortCircuitDetection, 1); + // 不判断用户拔出 + // byte[] noUserPullOutCheckBytes = BytesUtil.stringToHexBytes(noUserPullOutCheck, 1); + // 强制带充满自停 + // byte[] forceAutoStopWhenFullBytes = BytesUtil.stringToHexBytes(forceAutoStopWhenFull, 1); + // 充满功率 + // byte[] fullChargePowerBytes = BytesUtil.stringToHexBytes(fullChargePower, 1); + // 最大充满功率最长判断时间 + // byte[] maxFullChargePowerCheckTimeBytes = BytesUtil.stringToHexBytes(maxFullChargePowerCheckTime, 1); + return Bytes.concat(rateModeBytes, balanceOrValidityBytes, portNumberBytes, chargeCommandBytes, + chargeDurationOrPowerBytes, orderNumberBytes, maxChargeDurationBytes, overloadPowerBytes + // , qrCodeLightBytes, longChargeModeBytes, extraFloatChargeTimeBytes + // , skipShortCircuitDetectionBytes, noUserPullOutCheckBytes, forceAutoStopWhenFullBytes + // , fullChargePowerBytes, maxFullChargePowerCheckTimeBytes + ); } } } \ No newline at end of file diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ykcCommond/StopChargingCommand.java b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ykcCommond/StopChargingCommand.java index c683765f8..f6c97fefa 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/domain/ykcCommond/StopChargingCommand.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/domain/ykcCommond/StopChargingCommand.java @@ -15,4 +15,9 @@ import lombok.NoArgsConstructor; public class StopChargingCommand { private String pileSn; private String connectorCode; + + /** + * 交易流水号 + */ + private String transactionCode; } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/dto/GenerateOrderDTO.java b/jsowell-pile/src/main/java/com/jsowell/pile/dto/GenerateOrderDTO.java index 263c84c22..21c50f5fa 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/dto/GenerateOrderDTO.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/dto/GenerateOrderDTO.java @@ -58,6 +58,7 @@ public class GenerateOrderDTO extends BasicPileDTO{ /** * 计费模板相关信息 + * 电动汽车桩专用 */ private BillingTemplateVO billingTemplate; diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/mapper/PileBillingTemplateMapper.java b/jsowell-pile/src/main/java/com/jsowell/pile/mapper/PileBillingTemplateMapper.java index 69140c585..5efa0cf7c 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/mapper/PileBillingTemplateMapper.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/mapper/PileBillingTemplateMapper.java @@ -166,10 +166,12 @@ public interface PileBillingTemplateMapper { /** * 根据站点id修改状态 + * * @param stationId * @param status + * @param deviceType */ - void updateStatusByStationId(@Param("stationId") String stationId, @Param("status") String status); + void updateStatusByStationId(@Param("stationId") String stationId, @Param("status") String status, @Param("deviceType")String deviceType); void updateStatusByTemplateId(@Param("templateId") String templateId, @Param("status") String status); diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/EBikeSendCommandService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/EBikeSendCommandService.java index b1402bc90..901f46515 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/EBikeSendCommandService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/EBikeSendCommandService.java @@ -1,10 +1,23 @@ package com.jsowell.pile.service; -import com.jsowell.pile.domain.ebike.AbsEBikeMessage; +import com.jsowell.pile.domain.ykcCommond.StartChargingCommand; +import com.jsowell.pile.domain.ykcCommond.StopChargingCommand; /** * 电单车发送命令服务 */ public interface EBikeSendCommandService { - void send(String pileSn, AbsEBikeMessage msg); + + /** + * 启动充电 + * @param command + */ + void sendStartChargingCommand(StartChargingCommand command); + + /** + * 停止充电 + * @param command + */ + void sendStopChargingCommand(StopChargingCommand command); + } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java index 14ede4f70..dcc374a8f 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java @@ -91,7 +91,9 @@ public interface OrderBasicInfoService{ * 【公共方法】 * @param dto */ - void checkPileInfo(GenerateOrderDTO dto); + void checkPileInfoForEV(GenerateOrderDTO dto); + + void checkPileInfoForEBike(GenerateOrderDTO dto); /** * 保存订单到数据库 saveOrder2Database @@ -100,7 +102,9 @@ public interface OrderBasicInfoService{ * @return * @throws ParseException */ - OrderBasicInfo saveOrder2Database(GenerateOrderDTO dto) throws ParseException; + OrderBasicInfo saveOrderForEV(GenerateOrderDTO dto) throws ParseException; + + OrderBasicInfo saveOrderForEBike(GenerateOrderDTO dto) throws ParseException; /** * 修改订单 diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/PileBillingTemplateService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/PileBillingTemplateService.java index aa1c8e7c3..0c28c8a59 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/PileBillingTemplateService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/PileBillingTemplateService.java @@ -177,9 +177,12 @@ public interface PileBillingTemplateService { /** * 修改站点计费模板状态并下发最新模板 + * @param stationId 充电站id + * @param templateId 模板id + * @param deviceType 设备类型 * @return */ - int changeStationTemplate(String stationId, String templateId); + int changeStationTemplate(String stationId, String templateId, String deviceType); /** * 创建优惠计费模板 diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/PileRemoteService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/PileRemoteService.java index 37b0d8318..890a68da9 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/PileRemoteService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/PileRemoteService.java @@ -173,7 +173,6 @@ public class PileRemoteService { * @return */ public boolean publishBillingTemplate(PublishBillingTemplateDTO dto) { - // 获取计费模板信息 BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateByTemplateId(dto.getTemplateId()); if (billingTemplateVO == null) { @@ -186,33 +185,19 @@ public class PileRemoteService { pileBillingTemplate.setPublishTime(new Date()); pileBillingTemplateService.updatePileBillingTemplate(pileBillingTemplate); - // 获取到站点下所有的桩 - List pileList = pileBasicInfoService.selectPileListByStationIds(Lists.newArrayList(Long.valueOf(dto.getStationId()))); - if (CollectionUtils.isEmpty(pileList)) { - log.warn("获取到站点下所有的桩, 通过站点id:{}查询充电桩列表为空", dto.getStationId()); - return false; + // 获取到站点下所有的桩, 下发计费模板, 电单车不支持 + if (StringUtils.equals(billingTemplateVO.getDeviceType(), "1")) { + List pileList = pileBasicInfoService.selectPileListByStationIds(Lists.newArrayList(Long.valueOf(dto.getStationId()))); + if (CollectionUtils.isNotEmpty(pileList)) { + for (PileDetailVO pileInfoVO : pileList) { + // 下发计费模板 + publishPileBillingTemplate(pileInfoVO.getPileSn(), billingTemplateVO); + } + } } - // 保存计费模板和桩的关系 - // List relationList = Lists.newArrayList(); - for (PileDetailVO pileInfoVO : pileList) { - // push - publishPileBillingTemplate(pileInfoVO.getPileSn(), billingTemplateVO); - - // 入库 - // relationList.add(PileBillingRelation.builder() - // .pileSn(pileInfoVO.getPileSn()) - // .billingTemplateCode(billingTemplateVO.getTemplateCode()) - // .stationId(dto.getStationId()) - // .build()); - } - - // if (CollectionUtils.isNotEmpty(relationList)) { - // pileBillingTemplateService.insertPileBillingRelation(relationList); - // } - // 修改计费模板状态 - pileBillingTemplateService.changeStationTemplate(dto.getStationId(), dto.getTemplateId()); + pileBillingTemplateService.changeStationTemplate(dto.getStationId(), dto.getTemplateId(), billingTemplateVO.getDeviceType()); return true; } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/util/SnUtils.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/PileSnGenerateService.java similarity index 83% rename from jsowell-pile/src/main/java/com/jsowell/pile/util/SnUtils.java rename to jsowell-pile/src/main/java/com/jsowell/pile/service/PileSnGenerateService.java index 51f3a30ea..6d5386316 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/util/SnUtils.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/PileSnGenerateService.java @@ -1,11 +1,10 @@ -package com.jsowell.pile.util; +package com.jsowell.pile.service; import com.google.common.collect.Lists; import com.jsowell.common.constant.CacheConstants; import com.jsowell.common.core.redis.RedisCache; import com.jsowell.common.util.StringUtils; import com.jsowell.pile.domain.PileBasicInfo; -import com.jsowell.pile.service.PileBasicInfoService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -18,9 +17,9 @@ import java.util.List; * 生成sn号Util */ @Component -public class SnUtils { +public class PileSnGenerateService { - private static Logger logger = LoggerFactory.getLogger(SnUtils.class); + private static Logger logger = LoggerFactory.getLogger(PileSnGenerateService.class); @Autowired private RedisCache redisCache; @@ -65,16 +64,6 @@ public class SnUtils { return increResult; } - public static void main(String[] args) { - // String pileSn = "88230000002060"; - // String substring = StringUtils.substring(pileSn, 4, pileSn.length()); - // long l = Long.parseLong(substring); - // System.out.println(substring); - // System.out.println(l); - - Long a = 3147483647L; - } - /** * 生成sn号 * diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/EBikeSendCommandService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/EBikeSendCommandService.java deleted file mode 100644 index d89f84da0..000000000 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/EBikeSendCommandService.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.jsowell.pile.service.impl; - -import com.jsowell.common.enums.ykc.PileChannelEntity; -import com.jsowell.pile.domain.ebike.AbsEBikeMessage; -import io.netty.channel.ChannelHandlerContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.Objects; -import java.util.concurrent.TimeUnit; - -/** - * 电单车发送指令service - */ -@Slf4j -@Service -public class EBikeSendCommandService { - - /** - * 公共方法发送指令 - * @param pileSn 装编号 - * @param msg 消息 - * @param timeout 超时时间 - * @param unit 时间单位 - */ - private void sendCommand(String pileSn, Class msg, long timeout, TimeUnit unit) { - // 通过桩编号获取channel - ChannelHandlerContext ctx = PileChannelEntity.getChannelByPileSn(pileSn); - if (Objects.isNull(ctx)) { - log.error("push命令[{}]失败, 桩号:{}无法获取到长连接, 请检查充电桩连接状态!", "value", pileSn); - throw new NullPointerException("channel"); - } - } -} diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/EBikeSendCommandServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/EBikeSendCommandServiceImpl.java index 1d0b6c4c2..cb7ed5bd6 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/EBikeSendCommandServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/EBikeSendCommandServiceImpl.java @@ -1,13 +1,159 @@ package com.jsowell.pile.service.impl; +import com.jsowell.common.enums.ykc.PileChannelEntity; +import com.jsowell.common.util.BytesUtil; +import com.jsowell.common.util.RandomUtil; +import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.id.IdUtils; import com.jsowell.pile.domain.ebike.AbsEBikeMessage; +import com.jsowell.pile.domain.ebike.serversend.EBikeMessageCmd82; +import com.jsowell.pile.domain.ykcCommond.StartChargingCommand; +import com.jsowell.pile.domain.ykcCommond.StopChargingCommand; import com.jsowell.pile.service.EBikeSendCommandService; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.Objects; + +@Slf4j @Service public class EBikeSendCommandServiceImpl implements EBikeSendCommandService { - @Override - public void send(String pileSn, AbsEBikeMessage msg) { + // 过载功率, 单位0.1W, 2450 * 0.1 = 2450W + private final int OVER_LOAD_POWER = 2450; + + /** + * 电单车发送启动充电指令 + */ + @Override + public void sendStartChargingCommand(StartChargingCommand command) { + String pileSn = command.getPileSn(); + String connectorCode = command.getConnectorCode(); + String transactionCode = command.getTransactionCode(); + if (StringUtils.isBlank(transactionCode)) { + transactionCode = IdUtils.generateTransactionCode(pileSn, connectorCode); + } + + // 组装参数 + EBikeMessageCmd82 message = new EBikeMessageCmd82(); + message.setPhysicalId(Integer.parseInt(pileSn)); + message.setMessageId(RandomUtil.getRandomNumber(4)); + message.setCommand("82"); + + EBikeMessageCmd82.SpecificData data = new EBikeMessageCmd82.SpecificData(); + // 充电模式 + data.setRateMode(3); + // 余额或有效期 + data.setBalanceOrValidity(1234); + // 端口号 + data.setPortNumber(Integer.parseInt(connectorCode)); + // 充电命令 + data.setChargeCommand(1); + // 充电时长/功率 + int chargeDurationOrPower = 0; + data.setChargeTimeOrPower(chargeDurationOrPower); + + // 订单编号 + data.setTransactionCode(transactionCode); + + // 最大充电时长 + data.setMaxChargeTime(0); + // 过载功率 + data.setOverloadPower(OVER_LOAD_POWER); + data.setQrCodeLight(0); + data.setLongChargeMode(0); + data.setExtraFloatChargeTime(0); + data.setSkipShortCircuitDetection(0); + data.setNoUserPullOutCheck(0); + data.setForceAutoStopWhenFull(0); + data.setFullChargePower(0); + data.setMaxFullChargePowerCheckTime(0); + message.setData(data); + this.send(message); } + + /** + * 发送停止充电指令 + * @param command + */ + @Override + public void sendStopChargingCommand(StopChargingCommand command) { + String pileSn = command.getPileSn(); + String connectorCode = command.getConnectorCode(); + String transactionCode = command.getTransactionCode(); + + // 组装参数 + EBikeMessageCmd82 message = new EBikeMessageCmd82(); + message.setPhysicalId(Integer.parseInt(pileSn)); + message.setMessageId(RandomUtil.getRandomNumber(4)); + message.setCommand("82"); + + EBikeMessageCmd82.SpecificData data = new EBikeMessageCmd82.SpecificData(); + // 充电模式 + data.setRateMode(3); + // 余额或有效期 + data.setBalanceOrValidity(1234); + // 端口号 + data.setPortNumber(Integer.parseInt(connectorCode)); + // 充电命令 + data.setChargeCommand(0); + // 充电时长/功率 + int chargeDurationOrPower = 0; + data.setChargeTimeOrPower(chargeDurationOrPower); + + // 订单编号 + data.setTransactionCode(transactionCode); + + // 最大充电时长 + data.setMaxChargeTime(0); + // 过载功率 + data.setOverloadPower(OVER_LOAD_POWER); + data.setQrCodeLight(0); + data.setLongChargeMode(0); + data.setExtraFloatChargeTime(0); + data.setSkipShortCircuitDetection(0); + data.setNoUserPullOutCheck(0); + data.setForceAutoStopWhenFull(0); + data.setFullChargePower(0); + data.setMaxFullChargePowerCheckTime(0); + message.setData(data); + this.send(message); + } + + /** + * 公共方法, 发送指令 + * @param msg + */ + private void send(AbsEBikeMessage msg) { + String pileSn = msg.getPhysicalId() + ""; + byte[] messageBytes = msg.getMessageBytes(); + // PileChannelEntity.output(); + log.info("发送电单车send命令, pileSn:{}, messageBytes:{}", pileSn, BytesUtil.binary(messageBytes, 16)); + // 获取桩的channel + ChannelHandlerContext ctx = PileChannelEntity.getChannelByPileSn(pileSn); + if (Objects.isNull(ctx)) { + log.error("电单车send命令失败, 桩号:{}无法获取到长连接, 请检查充电桩连接状态!", pileSn); + throw new NullPointerException("channel"); + } + ByteBuf byteBuf = ctx.channel().alloc().buffer().writeBytes(messageBytes); + ChannelFuture channelFuture = ctx.channel().writeAndFlush(byteBuf); + channelFuture.addListener((ChannelFutureListener) channelFutureListener -> { + // 检查操作的状态 + if (channelFutureListener.isSuccess()) { + log.info("【电单车send结果===>成功】, pileSn:{}, remoteAddress:{}, channelId:{}, 帧类型:{}, 报文:{}", + pileSn, ctx.channel().remoteAddress(), ctx.channel().id(), msg.getCommand(), BytesUtil.binary(messageBytes, 16)); + } else { + // 如果发生错误,则访问描述原因的Throwable + Throwable cause = channelFutureListener.cause(); + log.info("【电单车send结果===>失败】, pileSn:{}, remoteAddress:{}, channelId:{}, 帧类型:{}, 报文:{}", + pileSn, ctx.channel().remoteAddress(), ctx.channel().id(), msg.getCommand(), BytesUtil.binary(messageBytes, 16)); + log.error("电单车send发送命令失败, pileSn:{}", pileSn, cause); + } + }); + } + } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java index 1127c98c2..843360bf5 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java @@ -32,6 +32,7 @@ import com.jsowell.common.exception.BusinessException; import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.PageUtils; import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.YKCUtils; import com.jsowell.common.util.bean.BeanUtils; import com.jsowell.common.util.id.IdUtils; import com.jsowell.common.util.id.SnowflakeIdWorker; @@ -73,7 +74,6 @@ import javax.annotation.Resource; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.ParseException; -import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.util.*; import java.util.concurrent.CompletableFuture; @@ -573,21 +573,6 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { } } - public static void main(String[] args) { - long currentTimeMillis = System.currentTimeMillis(); - String str1 = "2024-08-12 09:41:02"; - // Date time = Date.parse(); - SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - Date parse = null; - try { - parse = sdf1.parse(str1); - } catch (ParseException e) { - throw new RuntimeException(e); - } - - System.out.println(currentTimeMillis - parse.getTime()); - } - /** * 查询充电中的订单,没有数据权限校验,后管不要用 * @@ -2543,8 +2528,10 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { // 生成订单 String orderCode = dto.getStartChargeSeq(); String pileConnectorCode = dto.getConnectorID(); - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); - String connectorCode = StringUtils.substring(pileConnectorCode, 14, 16); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); + // String connectorCode = StringUtils.substring(pileConnectorCode, 14, 16); + String connectorCode = YKCUtils.getConnectorCode(pileConnectorCode); String transactionCode = IdUtils.generateTransactionCode(pileSn, connectorCode); @@ -2554,7 +2541,7 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { generateOrderDTO.setConnectorCode(connectorCode); generateOrderDTO.setStartMode(StartModeEnum.THIRD_PARTY_PLATFORM.getValue()); - checkPileInfo(generateOrderDTO); + checkPileInfoForEV(generateOrderDTO); // 通过桩号查询所属站点 PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); Long stationId = pileBasicInfo.getStationId(); @@ -2968,10 +2955,10 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { analysisPileParameter(dto); // 校验充电桩相关的信息 - checkPileInfo(dto); + checkPileInfoForEV(dto); // 保存订单到数据库 saveOrder2Database - return saveOrder2Database(dto); + return saveOrderForEV(dto); } /** @@ -2980,23 +2967,46 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { * * @param dto */ + // @Override + // public void analysisPileParameter(BasicPileDTO dto) { + // if (StringUtils.isBlank(dto.getPileSn()) || StringUtils.isBlank(dto.getConnectorCode())) { + // // 从pileConnectorCode解析 + // String pileConnectorCode = dto.getPileConnectorCode(); + // // dto.setPileSn(StringUtils.substring(pileConnectorCode, 0, pileConnectorCode.length() - 2)); + // // dto.setConnectorCode(StringUtils.substring(pileConnectorCode, pileConnectorCode.length() - 2, pileConnectorCode.length())); + // dto.setPileSn(YKCUtils.getPileSn(pileConnectorCode)); + // dto.setConnectorCode(YKCUtils.getConnectorCode(pileConnectorCode)); + // } else { + // // 说明pileSn 和 connectorCode前端传了,那就校验一下长度 + // if (dto.getPileSn().length() != Constants.PILE_SN_LENGTH_FOR_EV || dto.getConnectorCode().length() != Constants.CONNECTOR_CODE_LENGTH_FOR_EV + // || dto.getPileSn().length() != Constants.PILE_SN_LENGTH_FOR_EBIKE || dto.getConnectorCode().length() != Constants.CONNECTOR_CODE_LENGTH_FOR_EBIKE) { + // throw new BusinessException(ReturnCodeEnum.CODE_DATA_LENGTH_ERROR); + // } + // } + // } + @Override public void analysisPileParameter(BasicPileDTO dto) { - if (StringUtils.isBlank(dto.getPileSn()) || StringUtils.isBlank(dto.getConnectorCode())) { - // 从pileConnectorCode解析 - String pileConnectorCode = dto.getPileConnectorCode(); - if (StringUtils.isNotEmpty(pileConnectorCode) && pileConnectorCode.length() == Constants.PILE_CONNECTOR_CODE_LENGTH) { - dto.setPileSn(StringUtils.substring(pileConnectorCode, 0, pileConnectorCode.length() - 2)); - dto.setConnectorCode(StringUtils.substring(pileConnectorCode, pileConnectorCode.length() - 2, pileConnectorCode.length())); + String pileSn = dto.getPileSn(); + String connectorCode = dto.getConnectorCode(); + String pileConnectorCode = dto.getPileConnectorCode(); + if (StringUtils.isBlank(pileSn) || StringUtils.isBlank(connectorCode)) { + if (StringUtils.isBlank(pileConnectorCode)) { + throw new BusinessException(ReturnCodeEnum.CODE_PARAM_NOT_NULL_ERROR); } else { - throw new BusinessException(ReturnCodeEnum.CODE_DATA_LENGTH_ERROR); - } - } else { - // 说明pileSn 和 connectorCode前端传了,那就校验一下长度 - if (dto.getPileSn().length() != Constants.PILE_SN_LENGTH || dto.getConnectorCode().length() != Constants.CONNECTOR_CODE_LENGTH) { - throw new BusinessException(ReturnCodeEnum.CODE_DATA_LENGTH_ERROR); + // 从pileConnectorCode解析 + pileSn = YKCUtils.getPileSn(pileConnectorCode); + connectorCode = YKCUtils.getConnectorCode(pileConnectorCode); } } + if (StringUtils.isBlank(pileConnectorCode)) { + if (StringUtils.isNotBlank(pileSn) && StringUtils.isNotBlank(connectorCode)) { + pileConnectorCode = pileSn + connectorCode; + } + } + dto.setPileConnectorCode(pileConnectorCode); + dto.setPileSn(pileSn); + dto.setConnectorCode(connectorCode); } /** @@ -3499,7 +3509,7 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { * @param dto */ @Override - public void checkPileInfo(GenerateOrderDTO dto) { + public void checkPileInfoForEV(GenerateOrderDTO dto) { // 查询充电桩状态 是否空闲 枪口是否占用 PileConnectorDetailVO pileConnector = pileBasicInfoService.queryPileConnectorDetail(dto.getPileSn() + dto.getConnectorCode()); if (pileConnector == null) { @@ -3549,6 +3559,46 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { dto.setBillingTemplate(billingTemplateVO); } + @Override + public void checkPileInfoForEBike(GenerateOrderDTO dto) { + // 查询充电桩状态 是否空闲 枪口是否占用 + PileConnectorDetailVO pileConnector = pileBasicInfoService.queryPileConnectorDetail(dto.getPileConnectorCode()); + if (pileConnector == null) { + logger.error("checkPileInfo充电枪口为空 pileSn:{}, connectorCode:{}", dto.getPileSn(), dto.getConnectorCode()); + throw new BusinessException(ReturnCodeEnum.CODE_CONNECTOR_INFO_NULL_ERROR); + } + + // 查询站点状态 + PileStationVO stationInfo = pileStationInfoService.getStationInfo(pileConnector.getStationId()); + if (stationInfo == null || StringUtils.equals(stationInfo.getOpenFlag(), Constants.ZERO)) { + throw new BusinessException(ReturnCodeEnum.CODE_STATION_IS_NOT_OPEN); + } + + // 校验启动桩使用的小程序,和充电桩所属一级运营商是否一致 + if (StringUtils.isNotBlank(dto.getAppId())) { + String merchantIdByAppId = ""; + if (StringUtils.equals(dto.getRequestSource(), AdapayPayChannelEnum.ALIPAY_LITE.getValue())) { + // 支付宝小程序 + merchantIdByAppId = pileMerchantInfoService.getDelayModeByAlipayAppId(dto.getAppId()); + }else { + // 微信小程序 + merchantIdByAppId = pileMerchantInfoService.getFirstLevelMerchantIdByWxAppId(dto.getAppId()); + } + String merchantIdByMerchantId = pileMerchantInfoService.getFirstLevelMerchantIdByMerchantId(stationInfo.getMerchantId()); + if (!StringUtils.equals(merchantIdByAppId, merchantIdByMerchantId)) { + throw new BusinessException("", "当前桩运营商与小程序所属运营商不一致"); + } + } + + // 查询充电桩的计费模板 + BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(dto.getPileSn()); + if (billingTemplateVO == null) { + throw new BusinessException(ReturnCodeEnum.CODE_BILLING_TEMPLATE_NULL_ERROR); + } + dto.setPileConnector(pileConnector); + dto.setBillingTemplate(billingTemplateVO); + } + /** * 保存订单信息到数据库 * @@ -3556,7 +3606,7 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { * @return */ @Override - public OrderBasicInfo saveOrder2Database(GenerateOrderDTO dto) throws ParseException { + public OrderBasicInfo saveOrderForEV(GenerateOrderDTO dto) throws ParseException { String orderCode = generateNewOrderCode(); String transactionCode = dto.getTransactionCode(); if (StringUtils.isBlank(transactionCode)) { @@ -3641,7 +3691,111 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { flatServicePrice = billingTemplate.getFlatServicePrice() != null ? billingTemplate.getFlatServicePrice() : BigDecimal.ZERO; valleyElectricityPrice = billingTemplate.getValleyElectricityPrice() != null ? billingTemplate.getValleyElectricityPrice() : BigDecimal.ZERO; valleyServicePrice = billingTemplate.getValleyServicePrice() != null ? billingTemplate.getValleyServicePrice() : BigDecimal.ZERO; + } + OrderDetail orderDetail = OrderDetail.builder() + .orderCode(orderCode) + .sharpPrice(sharpElectricityPrice.add(sharpServicePrice)) + .sharpElectricityPrice(sharpElectricityPrice) + .sharpServicePrice(sharpServicePrice) + .peakPrice(peakElectricityPrice.add(peakServicePrice)) + .peakElectricityPrice(peakElectricityPrice) + .peakServicePrice(peakServicePrice) + .flatPrice(flatElectricityPrice.add(flatServicePrice)) + .flatElectricityPrice(flatElectricityPrice) + .flatServicePrice(flatServicePrice) + .valleyPrice(valleyElectricityPrice.add(valleyServicePrice)) + .valleyElectricityPrice(valleyElectricityPrice) + .valleyServicePrice(valleyServicePrice) + .build(); + // 保存到数据库 + OrderTransactionDTO createOrderTransactionDTO = OrderTransactionDTO.builder() + .orderBasicInfo(orderBasicInfo) + .orderDetail(orderDetail) + .build(); + pileTransactionService.doCreateOrder(createOrderTransactionDTO); + return orderBasicInfo; + } + + /** + * 保存电单车订单信息 + * @param dto + * @return + * @throws ParseException + */ + @Override + public OrderBasicInfo saveOrderForEBike(GenerateOrderDTO dto) throws ParseException { + String orderCode = generateNewOrderCode(); + String transactionCode = dto.getTransactionCode(); + if (StringUtils.isBlank(transactionCode)) { + transactionCode = IdUtils.generateTransactionCode(dto.getPileSn(), dto.getConnectorCode()); + } + + // 启动类型, 默认立即启动 + if (StringUtils.isBlank(dto.getStartType())) { + dto.setStartType(StartTypeEnum.NOW.getValue()); + } + + String stationId = dto.getPileConnector().getStationId(); + String merchantId = dto.getPileConnector().getMerchantId(); + + // 订单基本信息 + OrderBasicInfo orderBasicInfo = OrderBasicInfo.builder() + .orderCode(orderCode) + .transactionCode(transactionCode) + .orderStatus(OrderStatusEnum.NOT_START.getValue()) + .memberId(dto.getMemberId()) + .stationId(stationId) + .merchantId(merchantId) + .pileSn(dto.getPileSn()) + .connectorCode(dto.getConnectorCode()) + .pileConnectorCode(dto.getPileConnectorCode()) + .startMode(dto.getStartMode()) + .payStatus(Constants.ZERO) + // .payAmount(dto.getChargeAmount()) // 支付完成后填入支付金额 + .payMode(dto.getPayMode()) + .orderAmount(BigDecimal.ZERO) + .virtualAmount(BigDecimal.ZERO) + .settleAmount(BigDecimal.ZERO) + .startType(dto.getStartType()) + .build(); + + // 订单详情 + BillingTemplateVO billingTemplate = dto.getBillingTemplate(); + logger.info("订单使用的计费模板-orderCode:{}, billingTemplate:{}", orderCode, JSON.toJSONString(billingTemplate)); + BigDecimal sharpElectricityPrice = BigDecimal.ZERO; // 尖时段电费单价 + BigDecimal sharpServicePrice = BigDecimal.ZERO; // 尖时段服务费单价 + BigDecimal peakElectricityPrice = BigDecimal.ZERO; // 峰时段电费单价 + BigDecimal peakServicePrice = BigDecimal.ZERO; // 峰时段服务费单价 + BigDecimal flatElectricityPrice = BigDecimal.ZERO; // 平时段电费单价 + BigDecimal flatServicePrice = BigDecimal.ZERO; // 平时段服务费单价 + BigDecimal valleyElectricityPrice = BigDecimal.ZERO; // 谷时段电费单价 + BigDecimal valleyServicePrice = BigDecimal.ZERO; // 谷时段服务费单价 + if (billingTemplate != null) { + sharpElectricityPrice = billingTemplate.getSharpElectricityPrice() != null + ? billingTemplate.getSharpElectricityPrice() + : BigDecimal.ZERO; + sharpServicePrice = billingTemplate.getSharpServicePrice() != null + ? billingTemplate.getSharpServicePrice() + : BigDecimal.ZERO; + peakElectricityPrice = billingTemplate.getPeakElectricityPrice() != null + ? billingTemplate.getPeakElectricityPrice() + : BigDecimal.ZERO; + peakServicePrice = billingTemplate.getPeakServicePrice() != null + ? billingTemplate.getPeakServicePrice() + : BigDecimal.ZERO; + flatElectricityPrice = billingTemplate.getFlatElectricityPrice() != null + ? billingTemplate.getFlatElectricityPrice() + : BigDecimal.ZERO; + flatServicePrice = billingTemplate.getFlatServicePrice() != null + ? billingTemplate.getFlatServicePrice() + : BigDecimal.ZERO; + valleyElectricityPrice = billingTemplate.getValleyElectricityPrice() != null + ? billingTemplate.getValleyElectricityPrice() + : BigDecimal.ZERO; + valleyServicePrice = billingTemplate.getValleyServicePrice() != null + ? billingTemplate.getValleyServicePrice() + : BigDecimal.ZERO; } OrderDetail orderDetail = OrderDetail.builder() .orderCode(orderCode) diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileBillingTemplateServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileBillingTemplateServiceImpl.java index 8b5b52435..8542a6001 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileBillingTemplateServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileBillingTemplateServiceImpl.java @@ -450,9 +450,9 @@ public class PileBillingTemplateServiceImpl implements PileBillingTemplateServic */ @Override @Transactional(readOnly = false, propagation = Propagation.REQUIRED) - public int changeStationTemplate(String stationId, String templateId) { - // 根据stationId把站点下所有的计费模板设置为 未启用 - pileBillingTemplateMapper.updateStatusByStationId(stationId, Constants.ZERO); + public int changeStationTemplate(String stationId, String templateId, String deviceType) { + // 根据stationId把站点下所有的计费模板设置为 未启用, 区分deviceType + pileBillingTemplateMapper.updateStatusByStationId(stationId, Constants.ZERO, deviceType); // 根据templateId 修改状态为启用 pileBillingTemplateMapper.updateStatusByTemplateId(templateId, Constants.ONE); // 清缓存 diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileConnectorInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileConnectorInfoServiceImpl.java index 6e9eaed9e..3477e1fd6 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileConnectorInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileConnectorInfoServiceImpl.java @@ -600,8 +600,7 @@ public class PileConnectorInfoServiceImpl implements PileConnectorInfoService { } String redisKey = CacheConstants.PILE_CONNECTOR_STATUS_KEY + pileConnectorCode; // 获取缓存 String redisStatus = redisCache.getCacheObject(redisKey); - // log.info("更新枪口状态-枪口编号:{}, redisKey:{}, 缓存状态:{}, 传来的状态:{}, 状态描述:{}", pileConnectorCode, redisKey, - // redisStatus, status, PileConnectorDataBaseStatusEnum.getStatusDescription(status)); + if (!StringUtils.equals(redisStatus, status)) { log.info("更新枪口状态ing-枪口编号:{}, redisKey:{}, 缓存状态:{}, 传来的状态:{}, 状态描述:{}", pileConnectorCode, redisKey, redisStatus, status, PileConnectorDataBaseStatusEnum.getStatusDescription(status)); @@ -609,7 +608,7 @@ public class PileConnectorInfoServiceImpl implements PileConnectorInfoService { // 只修改一个枪口的状态 num = pileConnectorInfoMapper.updateConnectorStatus(pileConnectorCode, status); deleteRedisByPileSnOrPileConnectorCode(pileSn, pileConnectorCode); - redisCache.setCacheObject(redisKey, status, CacheConstants.cache_expire_time_3m); + redisCache.setCacheObject(redisKey, status, CacheConstants.cache_expire_time_5m); // 异步放缓存 CompletableFuture.runAsync(() -> statusChange(pileConnectorCode)); diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileReservationInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileReservationInfoServiceImpl.java index 9c4ad86d9..f8acec12f 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileReservationInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileReservationInfoServiceImpl.java @@ -13,6 +13,7 @@ import com.jsowell.common.enums.ykc.ReturnCodeEnum; import com.jsowell.common.exception.BusinessException; import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.YKCUtils; import com.jsowell.pile.domain.PileMemberRelation; import com.jsowell.pile.domain.PileReservationInfo; import com.jsowell.pile.domain.ykcCommond.ReservationChargingCommand; @@ -504,8 +505,10 @@ public class PileReservationInfoServiceImpl implements PileReservationInfoServic @Override public void personPileStopCharging(PersonPileStopChargingDTO dto) { String pileConnectorCode = dto.getPileConnectorCode(); - String pileSn = StringUtils.substring(pileConnectorCode, 0, pileConnectorCode.length() - 2); - String connectorCode = StringUtils.substring(pileConnectorCode, pileConnectorCode.length() - 2, pileConnectorCode.length()); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, pileConnectorCode.length() - 2); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); + // String connectorCode = StringUtils.substring(pileConnectorCode, pileConnectorCode.length() - 2, pileConnectorCode.length()); + String connectorCode = YKCUtils.getConnectorCode(pileConnectorCode); // 查询个人桩信息 List pileMemberRelations = pileMemberRelationService.selectPileMemberRelationByPileSn(pileSn); Map> listMap = pileMemberRelations.stream() diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileStationInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileStationInfoServiceImpl.java index 6424a1720..5ba9a9f6e 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileStationInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileStationInfoServiceImpl.java @@ -193,7 +193,7 @@ public class PileStationInfoServiceImpl implements PileStationInfoService { CoordinateUtil.Coordinate coordinate = CoordinateUtil.gcj02ToWgs84(Double.parseDouble(pileStationInfo.getStationLng()), Double.parseDouble(pileStationInfo.getStationLat())); vo.setStationLat(String.format("%.6f", coordinate.getLat())); vo.setStationLng(String.format("%.6f", coordinate.getLng())); - log.info("高德坐标:{}, 转天地图坐标:{}", pileStationInfo.getStationLng() + ", " + pileStationInfo.getStationLat(), vo.getStationLng() + ", " + vo.getStationLat()); + log.debug("高德坐标:{}, 转天地图坐标:{}", pileStationInfo.getStationLng() + ", " + pileStationInfo.getStationLat(), vo.getStationLng() + ", " + vo.getStationLat()); } vo.setCountryCode(pileStationInfo.getCountryCode()); @@ -223,7 +223,8 @@ public class PileStationInfoServiceImpl implements PileStationInfoService { if (StringUtils.isBlank(pileConnectorCode)) { return null; } - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); return getStationInfoByPileSn(pileSn); } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/YKCPushCommandServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/YKCPushCommandServiceImpl.java index 35e7d75ce..70d2c7d84 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/YKCPushCommandServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/YKCPushCommandServiceImpl.java @@ -281,6 +281,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { } catch (Exception e) { throw new RuntimeException(e); } + log.info("【=====平台下发充电指令=====】:订单id:{}, 桩号:{}, 枪口号:{}, 逻辑卡号:{}, 物理卡号:{}, 账户余额:{}", transactionCode, pileSn, BytesUtil.bcd2Str(connectorCodeByteArr), logicCardNum, physicsCardNum, chargeAmount); } @@ -314,7 +315,7 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { } catch (Exception e) { throw new RuntimeException(e); } - log.info("【=====平台下发指令=====】:获取充电桩:{} 的 {} 枪口实时数据信息", pileSn, connectorCode); + log.info("【=====平台下发指令=====】:获取枪口实时数据信息, pileSn:{}, 枪口:{} ", pileSn, connectorCode); } @Override @@ -327,7 +328,6 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { } catch (Exception e) { throw new RuntimeException(e); } - } // 下发二维码 diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/AbstractProgramLogic.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/AbstractProgramLogic.java index 70a55f3a2..ac6305ba7 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/AbstractProgramLogic.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/AbstractProgramLogic.java @@ -14,6 +14,7 @@ import com.jsowell.common.enums.ykc.*; import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.pile.domain.*; +import com.jsowell.pile.domain.ebike.deviceupload.EBikeMessageCmd03; import com.jsowell.pile.dto.*; import com.jsowell.pile.service.*; import com.jsowell.pile.transaction.service.TransactionService; @@ -53,6 +54,9 @@ public abstract class AbstractProgramLogic implements InitializingBean { @Autowired protected PileBasicInfoService pileBasicInfoService; + @Autowired + protected PileConnectorInfoService pileConnectorInfoService; + @Autowired protected PileStationInfoService pileStationInfoService; @@ -138,6 +142,13 @@ public abstract class AbstractProgramLogic implements InitializingBean { */ public abstract void settleOrder(TransactionRecordsData data, OrderBasicInfo orderBasicInfo); + /** + * 电单车结算逻辑 + * @param message + * @param orderBasicInfo + */ + public abstract void settleOrderForEBike(EBikeMessageCmd03 message, OrderBasicInfo orderBasicInfo); + /** * 第三方平台结算订单(目前给华为用) * diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/DelayMerchantProgramLogic.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/DelayMerchantProgramLogic.java index 9c35dc1e0..98beccce2 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/DelayMerchantProgramLogic.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/DelayMerchantProgramLogic.java @@ -27,9 +27,11 @@ import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.id.SnowflakeIdWorker; import com.jsowell.pile.domain.*; +import com.jsowell.pile.domain.ebike.deviceupload.EBikeMessageCmd03; import com.jsowell.pile.dto.*; import com.jsowell.pile.transaction.dto.OrderTransactionDTO; import com.jsowell.pile.vo.uniapp.customer.MemberVO; +import com.jsowell.pile.vo.uniapp.customer.PileConnectorDetailVO; import com.jsowell.pile.vo.web.BalanceDeductionAmountVO; import com.jsowell.pile.vo.web.BillingTemplateVO; import com.jsowell.pile.vo.web.OrderDetailInfoVO; @@ -67,18 +69,49 @@ public class DelayMerchantProgramLogic extends AbstractProgramLogic { */ @Override public OrderBasicInfo generateOrder(GenerateOrderDTO dto) throws ParseException { - logger.info("【{}】-生成订单start, param:{}", this.getClass().getSimpleName(), JSON.toJSONString(dto)); // 处理前端传的参数 orderBasicInfoService.analysisPileParameter(dto); + // 判断桩是电动汽车桩还是电单车桩 + PileConnectorDetailVO pileConnectorDetailVO = pileBasicInfoService.queryPileConnectorDetail(dto.getPileConnectorCode()); + if (!StringUtils.equals(pileConnectorDetailVO.getChargePortType(), Constants.THREE)) { // 不是3就是电动汽车桩 + // 电车桩 + return generateOrderForEV(dto); + } else { + // 电动车桩 + return generateOrderForEBike(dto); + } + } + + /** + * 生成电动汽车订单 + * @param dto + * @return + * @throws ParseException + */ + private OrderBasicInfo generateOrderForEV(GenerateOrderDTO dto) throws ParseException { + logger.info("【{}】-生成电动汽车订单start, param:{}", this.getClass().getSimpleName(), JSON.toJSONString(dto)); // 校验充电桩相关的信息 if (StringUtils.isBlank(dto.getTransactionCode())) { // 无transactionCode, 表示由平台端启动充电, 需要验证充电桩状态 - orderBasicInfoService.checkPileInfo(dto); + orderBasicInfoService.checkPileInfoForEV(dto); } // 保存订单到数据库 saveOrder2Database - return orderBasicInfoService.saveOrder2Database(dto); + return orderBasicInfoService.saveOrderForEV(dto); + } + + /** + * 生成电单车订单/电单车生成订单 + */ + private OrderBasicInfo generateOrderForEBike(GenerateOrderDTO dto) throws ParseException { + logger.info("【{}】-生成电单车订单start, param:{}", this.getClass().getSimpleName(), JSON.toJSONString(dto)); + // 校验充电桩相关的信息 + if (StringUtils.isBlank(dto.getTransactionCode())) { + // 无transactionCode, 表示由平台端启动充电, 需要验证充电桩状态 + orderBasicInfoService.checkPileInfoForEBike(dto); + } + return orderBasicInfoService.saveOrderForEBike(dto); } /** @@ -438,6 +471,11 @@ public class DelayMerchantProgramLogic extends AbstractProgramLogic { orderBasicInfo.getOrderCode(), orderBasicInfo.getTransactionCode(), JSON.toJSONString(dto)); } + @Override + public void settleOrderForEBike(EBikeMessageCmd03 message, OrderBasicInfo orderBasicInfo) { + + } + /** * 第三方平台结算订单(目前给华为用) * @param data diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/NotDelayMerchantProgramLogic.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/NotDelayMerchantProgramLogic.java index 926858719..6a5f4e0bb 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/NotDelayMerchantProgramLogic.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/NotDelayMerchantProgramLogic.java @@ -13,7 +13,6 @@ import com.jsowell.adapay.common.RefundInfo; import com.jsowell.adapay.config.AbstractAdapayConfig; import com.jsowell.adapay.factory.AdapayConfigFactory; import com.jsowell.adapay.response.RefundResponse; -import com.jsowell.adapay.vo.PaymentInfo; import com.jsowell.common.constant.CacheConstants; import com.jsowell.common.constant.Constants; import com.jsowell.common.core.domain.ykc.TransactionRecordsData; @@ -28,6 +27,7 @@ import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.id.SnowflakeIdWorker; import com.jsowell.pile.domain.*; +import com.jsowell.pile.domain.ebike.deviceupload.EBikeMessageCmd03; import com.jsowell.pile.dto.*; import com.jsowell.pile.transaction.dto.OrderTransactionDTO; import com.jsowell.pile.vo.uniapp.customer.MemberVO; @@ -45,7 +45,6 @@ import java.text.ParseException; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.function.Function; import java.util.stream.Collectors; /** @@ -74,11 +73,11 @@ public class NotDelayMerchantProgramLogic extends AbstractProgramLogic { // 校验充电桩相关的信息 if (StringUtils.isBlank(dto.getTransactionCode())) { // 无transactionCode, 表示由平台端启动充电, 需要验证充电桩状态 - orderBasicInfoService.checkPileInfo(dto); + orderBasicInfoService.checkPileInfoForEV(dto); } // 保存订单到数据库 saveOrder2Database - return orderBasicInfoService.saveOrder2Database(dto); + return orderBasicInfoService.saveOrderForEV(dto); } @Override @@ -130,94 +129,94 @@ public class NotDelayMerchantProgramLogic extends AbstractProgramLogic { * * @param dto */ - @Transactional(rollbackFor = Exception.class) - public void balancePayOrder(PayOrderDTO dto) { - logger.info("【{}】-余额支付订单start, param:{}", this.getClass().getSimpleName(), JSON.toJSONString(dto)); - String orderCode = dto.getOrderCode(); // 订单编号 - BigDecimal chargeAmount = dto.getPayAmount(); // 支付金额 - // 查询该会员的余额 - MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(dto.getMemberId()); - BigDecimal totalAccountAmount = memberVO.getPrincipalBalance(); - - if (totalAccountAmount.compareTo(chargeAmount) < 0) { - // 总余额小于充电金额 - throw new BusinessException(ReturnCodeEnum.CODE_BALANCE_IS_INSUFFICIENT); - } - BigDecimal principalPay = chargeAmount; - - // 更新会员钱包 - UpdateMemberBalanceDTO updateMemberBalanceDTO = UpdateMemberBalanceDTO.builder() - .memberId(dto.getMemberId()) - .type(MemberWalletEnum.TYPE_OUT.getValue()) - .subType(MemberWalletEnum.SUBTYPE_PAYMENT_FOR_ORDER.getValue()) - .updatePrincipalBalance(principalPay) // 使用本金支付的金额 - .relatedOrderCode(orderCode) - .build(); - memberBasicInfoService.updateMemberBalance(updateMemberBalanceDTO); - - // 查询余额充值有剩余的记录 - List list = calculateTheBalanceDeductionAmount(dto.getMemberId(), chargeAmount); - // 记录支订单付流水 - List paymentInfos = Lists.newArrayList(); - BigDecimal deductionAmount = BigDecimal.ZERO; - for (BalanceDeductionAmountVO balanceDeductionAmountVO : list) { - String paymentId = balanceDeductionAmountVO.getPaymentId(); - deductionAmount = deductionAmount.add(balanceDeductionAmountVO.getDeductionAmount()); - - PaymentInfo paymentInfo = new PaymentInfo(); - paymentInfo.setPaymentId(paymentId); - paymentInfo.setAmount(deductionAmount.toString()); - paymentInfos.add(paymentInfo); - } - // 记录流水 - OrderPayRecord orderPayRecord = OrderPayRecord.builder() - .orderCode(orderCode) - .payMode(OrderPayRecordEnum.PRINCIPAL_BALANCE_PAYMENT.getValue()) - .payAmount(deductionAmount) - .acquirer(AcquirerEnum.LOCAL.getValue()) - .deductionRecord(JSON.toJSONString(paymentInfos)) - .createBy(dto.getMemberId()) - .delFlag(DelFlagEnum.NORMAL.getValue()) - .build(); - - // 订单支付流水入库 - List payRecordList = Lists.newArrayList(orderPayRecord); - orderPayRecordService.batchInsert(payRecordList); - - // 把消费金额冻结 - for (OrderPayRecord record : payRecordList) { - List paymentInfoList = orderPayRecordService.parseDeductionRecord(record.getDeductionRecord()); - // 循环冻结金额 - for (PaymentInfo paymentInfo : paymentInfoList) { - String paymentId = paymentInfo.getPaymentId(); - BigDecimal amount = new BigDecimal(paymentInfo.getAmount()); - // 余额支付 临时冻结金额 - memberAdapayRecordService.updateFreezeAmount(paymentId, amount); - } - } - - // 余额支付可以直接调支付回调方法 - PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder() - .orderCode(orderCode) - .payAmount(chargeAmount) - .payMode(dto.getPayMode()) - .startMode(dto.getStartMode()) - .acquirer(AcquirerEnum.LOCAL.getValue()) - .build(); - payOrderSuccessCallback(callbackDTO); - - // 余额支付订单 记录会员交易流水 - MemberTransactionRecord record = MemberTransactionRecord.builder() - .orderCode(orderCode) - .scenarioType(ScenarioEnum.ORDER.getValue()) - .memberId(memberVO.getMemberId()) - .actionType(ActionTypeEnum.FORWARD.getValue()) - .payMode(PayModeEnum.PAYMENT_OF_BALANCE.getValue()) - .paymentInstitutions(PaymentInstitutionsEnum.LOCAL_ACCOUNTS.getValue()) - .amount(dto.getPayAmount()) // 单位元 - .build(); - memberTransactionRecordService.insertSelective(record); - } + // @Transactional(rollbackFor = Exception.class) + // public void balancePayOrder(PayOrderDTO dto) { + // logger.info("【{}】-余额支付订单start, param:{}", this.getClass().getSimpleName(), JSON.toJSONString(dto)); + // String orderCode = dto.getOrderCode(); // 订单编号 + // BigDecimal chargeAmount = dto.getPayAmount(); // 支付金额 + // // 查询该会员的余额 + // MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(dto.getMemberId()); + // BigDecimal totalAccountAmount = memberVO.getPrincipalBalance(); + // + // if (totalAccountAmount.compareTo(chargeAmount) < 0) { + // // 总余额小于充电金额 + // throw new BusinessException(ReturnCodeEnum.CODE_BALANCE_IS_INSUFFICIENT); + // } + // BigDecimal principalPay = chargeAmount; + // + // // 更新会员钱包 + // UpdateMemberBalanceDTO updateMemberBalanceDTO = UpdateMemberBalanceDTO.builder() + // .memberId(dto.getMemberId()) + // .type(MemberWalletEnum.TYPE_OUT.getValue()) + // .subType(MemberWalletEnum.SUBTYPE_PAYMENT_FOR_ORDER.getValue()) + // .updatePrincipalBalance(principalPay) // 使用本金支付的金额 + // .relatedOrderCode(orderCode) + // .build(); + // memberBasicInfoService.updateMemberBalance(updateMemberBalanceDTO); + // + // // 查询余额充值有剩余的记录 + // List list = calculateTheBalanceDeductionAmount(dto.getMemberId(), chargeAmount); + // // 记录支订单付流水 + // List paymentInfos = Lists.newArrayList(); + // BigDecimal deductionAmount = BigDecimal.ZERO; + // for (BalanceDeductionAmountVO balanceDeductionAmountVO : list) { + // String paymentId = balanceDeductionAmountVO.getPaymentId(); + // deductionAmount = deductionAmount.add(balanceDeductionAmountVO.getDeductionAmount()); + // + // PaymentInfo paymentInfo = new PaymentInfo(); + // paymentInfo.setPaymentId(paymentId); + // paymentInfo.setAmount(deductionAmount.toString()); + // paymentInfos.add(paymentInfo); + // } + // // 记录流水 + // OrderPayRecord orderPayRecord = OrderPayRecord.builder() + // .orderCode(orderCode) + // .payMode(OrderPayRecordEnum.PRINCIPAL_BALANCE_PAYMENT.getValue()) + // .payAmount(deductionAmount) + // .acquirer(AcquirerEnum.LOCAL.getValue()) + // .deductionRecord(JSON.toJSONString(paymentInfos)) + // .createBy(dto.getMemberId()) + // .delFlag(DelFlagEnum.NORMAL.getValue()) + // .build(); + // + // // 订单支付流水入库 + // List payRecordList = Lists.newArrayList(orderPayRecord); + // orderPayRecordService.batchInsert(payRecordList); + // + // // 把消费金额冻结 + // for (OrderPayRecord record : payRecordList) { + // List paymentInfoList = orderPayRecordService.parseDeductionRecord(record.getDeductionRecord()); + // // 循环冻结金额 + // for (PaymentInfo paymentInfo : paymentInfoList) { + // String paymentId = paymentInfo.getPaymentId(); + // BigDecimal amount = new BigDecimal(paymentInfo.getAmount()); + // // 余额支付 临时冻结金额 + // memberAdapayRecordService.updateFreezeAmount(paymentId, amount); + // } + // } + // + // // 余额支付可以直接调支付回调方法 + // PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder() + // .orderCode(orderCode) + // .payAmount(chargeAmount) + // .payMode(dto.getPayMode()) + // .startMode(dto.getStartMode()) + // .acquirer(AcquirerEnum.LOCAL.getValue()) + // .build(); + // payOrderSuccessCallback(callbackDTO); + // + // // 余额支付订单 记录会员交易流水 + // MemberTransactionRecord record = MemberTransactionRecord.builder() + // .orderCode(orderCode) + // .scenarioType(ScenarioEnum.ORDER.getValue()) + // .memberId(memberVO.getMemberId()) + // .actionType(ActionTypeEnum.FORWARD.getValue()) + // .payMode(PayModeEnum.PAYMENT_OF_BALANCE.getValue()) + // .paymentInstitutions(PaymentInstitutionsEnum.LOCAL_ACCOUNTS.getValue()) + // .amount(dto.getPayAmount()) // 单位元 + // .build(); + // memberTransactionRecordService.insertSelective(record); + // } /** * 余额支付订单逻辑 @@ -419,6 +418,11 @@ public class NotDelayMerchantProgramLogic extends AbstractProgramLogic { logger.info("结算订单end:{} OrderTransactionDTO:{}", orderBasicInfo.getOrderCode(), JSON.toJSONString(dto)); } + @Override + public void settleOrderForEBike(EBikeMessageCmd03 message, OrderBasicInfo orderBasicInfo) { + + } + /** * 第三方平台结算订单(目前给华为用) * @param data diff --git a/jsowell-pile/src/main/resources/mapper/pile/PileBillingTemplateMapper.xml b/jsowell-pile/src/main/resources/mapper/pile/PileBillingTemplateMapper.xml index 2ff424374..98cae8193 100644 --- a/jsowell-pile/src/main/resources/mapper/pile/PileBillingTemplateMapper.xml +++ b/jsowell-pile/src/main/resources/mapper/pile/PileBillingTemplateMapper.xml @@ -606,6 +606,7 @@ update pile_billing_template set status = #{status,jdbcType=VARCHAR} where station_id = #{stationId,jdbcType=VARCHAR} + and type = #{deviceType,jdbcType=VARCHAR} diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/huawei/HuaweiServiceV2.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/huawei/HuaweiServiceV2.java index 0c666e9ed..6cbcf95d1 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/huawei/HuaweiServiceV2.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/huawei/HuaweiServiceV2.java @@ -21,6 +21,7 @@ import com.jsowell.common.enums.ykc.StartModeEnum; import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.Threads; +import com.jsowell.common.util.YKCUtils; import com.jsowell.pile.domain.*; import com.jsowell.pile.domain.huawei.HWStationInfo; import com.jsowell.pile.domain.huawei.HWStationStatusInfo; @@ -281,7 +282,8 @@ public class HuaweiServiceV2 { public Map receiveNotificationStationStatus(ConnectorStatusInfo connectorStatusInfo) { String pileConnectorCode = connectorStatusInfo.getConnectorID(); Integer status = connectorStatusInfo.getStatus(); - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); if (status != 0) { setPileAlive(pileSn); } @@ -350,7 +352,8 @@ public class HuaweiServiceV2 { return null; } // 截取桩号 - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); // 查询该桩的站点id PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); // 根据桩号查询正在使用的计费模板 @@ -423,7 +426,8 @@ public class HuaweiServiceV2 { DeliverEquipBusinessDTO.ChargePolicyInfo.PricePolicyInfo.PolicyInfo policyInfo = null; // 截取桩号 - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); // 查询该桩的站点id PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); String stationId = String.valueOf(pileBasicInfo.getStationId()); @@ -775,7 +779,8 @@ public class HuaweiServiceV2 { String startChargeSeq = dto.getStartChargeSeq(); List chargeDetails = dto.getChargeDetails(); String pileConnectorCode = dto.getConnectorID(); - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); setPileAlive(pileSn); // 将源数据存缓存 @@ -883,8 +888,10 @@ public class HuaweiServiceV2 { String vinCode = dto.getVin(); String pileConnectorCode = dto.getConnectorID(); // 截取桩号、枪口号 - String pileSn = StringUtils.substring(pileConnectorCode, 0, pileConnectorCode.length() - 2); - String connectorCode = StringUtils.substring(pileConnectorCode, pileConnectorCode.length() - 2, pileConnectorCode.length()); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, pileConnectorCode.length() - 2); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); + // String connectorCode = StringUtils.substring(pileConnectorCode, pileConnectorCode.length() - 2, pileConnectorCode.length()); + String connectorCode = YKCUtils.getConnectorCode(pileConnectorCode); // 根据vin查询小程序平台用户信息 MemberPlateNumberRelation basicInfo = memberPlateNumberRelationService.getMemberPlateInfoByVinCode(vinCode); if (basicInfo == null) { diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/huawei/impl/HuaWeiServiceImpl.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/huawei/impl/HuaWeiServiceImpl.java index 817bb378d..5094ba390 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/huawei/impl/HuaWeiServiceImpl.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/huawei/impl/HuaWeiServiceImpl.java @@ -8,6 +8,7 @@ import com.jsowell.common.enums.ykc.ReturnCodeEnum; import com.jsowell.common.enums.ykc.StartModeEnum; import com.jsowell.common.exception.BusinessException; import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.YKCUtils; import com.jsowell.pile.domain.*; import com.jsowell.pile.domain.huawei.HWStationInfo; import com.jsowell.pile.dto.*; @@ -272,7 +273,8 @@ public class HuaWeiServiceImpl implements HuaWeiService { return null; } // 截取桩号 - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); // 查询该桩的站点id PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); // 根据桩号查询正在使用的计费模板 @@ -344,7 +346,8 @@ public class HuaWeiServiceImpl implements HuaWeiService { DeliverEquipBusinessDTO.ChargePolicyInfo.PricePolicyInfo.PolicyInfo policyInfo = null; // 截取桩号 - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); // 查询该桩的站点id PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); String stationId = String.valueOf(pileBasicInfo.getStationId()); @@ -493,8 +496,10 @@ public class HuaWeiServiceImpl implements HuaWeiService { String vinCode = dto.getVin(); String pileConnectorCode = dto.getConnectorID(); // 截取桩号、枪口号 - String pileSn = StringUtils.substring(pileConnectorCode, 0, pileConnectorCode.length() - 2); - String connectorCode = StringUtils.substring(pileConnectorCode, pileConnectorCode.length() - 2, pileConnectorCode.length()); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, pileConnectorCode.length() - 2); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); + // String connectorCode = StringUtils.substring(pileConnectorCode, pileConnectorCode.length() - 2, pileConnectorCode.length()); + String connectorCode = YKCUtils.getConnectorCode(pileConnectorCode); // 根据vin查询小程序平台用户信息 MemberPlateNumberRelation basicInfo = memberPlateNumberRelationService.getMemberPlateInfoByVinCode(vinCode); if (basicInfo == null) { diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/lianlian/service/impl/LianLianServiceImpl.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/lianlian/service/impl/LianLianServiceImpl.java index 9d41b17e4..92a2d662b 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/lianlian/service/impl/LianLianServiceImpl.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/lianlian/service/impl/LianLianServiceImpl.java @@ -20,10 +20,7 @@ import com.jsowell.common.enums.ykc.OrderPayModeEnum; import com.jsowell.common.enums.ykc.OrderStatusEnum; import com.jsowell.common.enums.ykc.PileConnectorDataBaseStatusEnum; import com.jsowell.common.enums.ykc.PileStatusEnum; -import com.jsowell.common.util.DateUtils; -import com.jsowell.common.util.JWTUtils; -import com.jsowell.common.util.PageUtils; -import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.*; import com.jsowell.pile.domain.*; import com.jsowell.pile.domain.ykcCommond.StartChargingCommand; import com.jsowell.pile.dto.*; @@ -590,7 +587,8 @@ public class LianLianServiceImpl implements LianLianService { } // 根据桩编号查询数据 // String merchantId = StringUtils.substring(equipAuthSeq, 0, 9); - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); vo.setSuccStat(1); // 1-失败 0-成功 默认失败 PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); if (pileBasicInfo != null) { @@ -916,7 +914,8 @@ public class LianLianServiceImpl implements LianLianService { String status = dto.getStatus(); String thirdPartyType = dto.getThirdPartyType(); // 查出该桩所属哪个站点 - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); PileStationVO stationVO = pileStationInfoService.getStationInfoByPileSn(pileSn); // 通过站点id查询相关配置信息 ThirdPartyStationRelation relation = new ThirdPartyStationRelation(); diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/nanrui/service/impl/NRServiceImpl.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/nanrui/service/impl/NRServiceImpl.java index 7f74d66d3..01e7ef62b 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/nanrui/service/impl/NRServiceImpl.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/nanrui/service/impl/NRServiceImpl.java @@ -15,6 +15,7 @@ import com.jsowell.common.enums.ykc.PileStatusEnum; import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.PageUtils; import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.YKCUtils; import com.jsowell.pile.domain.*; import com.jsowell.pile.domain.nanrui.JiangSuOrderInfo; import com.jsowell.pile.dto.PushStationInfoDTO; @@ -518,7 +519,8 @@ public class NRServiceImpl implements NRService { String thirdPartyType = realTimeMonitorData.getThirdPartyType(); // 查出该桩所属哪个站点 - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); PileStationVO stationVO = pileStationInfoService.getStationInfoByPileSn(pileSn); // 通过站点id查询相关配置信息 ThirdPartyStationRelation relation = new ThirdPartyStationRelation(); diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/HaiNanPlatformServiceImpl.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/HaiNanPlatformServiceImpl.java index 0e03d9365..3ae9644fa 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/HaiNanPlatformServiceImpl.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/HaiNanPlatformServiceImpl.java @@ -13,10 +13,7 @@ import com.jsowell.common.enums.thirdparty.ThirdPartyOperatorIdEnum; import com.jsowell.common.enums.thirdparty.ThirdPlatformTypeEnum; import com.jsowell.common.enums.ykc.OrderStatusEnum; import com.jsowell.common.enums.ykc.PileConnectorDataBaseStatusEnum; -import com.jsowell.common.util.AdapayUtil; -import com.jsowell.common.util.DateUtils; -import com.jsowell.common.util.PageUtils; -import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.*; import com.jsowell.pile.domain.*; import com.jsowell.pile.domain.ykcCommond.StartChargingCommand; import com.jsowell.pile.dto.*; @@ -607,7 +604,8 @@ public class HaiNanPlatformServiceImpl implements ThirdPartyPlatformService { } // 根据桩编号查询数据 // String merchantId = StringUtils.substring(equipAuthSeq, 0, 9); - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); vo.setSuccStat(1); // 1-失败 0-成功 默认失败 PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); if (pileBasicInfo != null) { @@ -654,7 +652,8 @@ public class HaiNanPlatformServiceImpl implements ThirdPartyPlatformService { return null; } // 截取桩号 - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); // 查询该桩的站点id PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); // 根据桩号查询正在使用的计费模板 diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/LianLianPlatformServiceImpl.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/LianLianPlatformServiceImpl.java index 561829278..7e7b58cf1 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/LianLianPlatformServiceImpl.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/LianLianPlatformServiceImpl.java @@ -17,10 +17,7 @@ import com.jsowell.common.enums.ykc.OrderPayModeEnum; import com.jsowell.common.enums.ykc.OrderStatusEnum; import com.jsowell.common.enums.ykc.PileConnectorDataBaseStatusEnum; import com.jsowell.common.exception.BusinessException; -import com.jsowell.common.util.DateUtils; -import com.jsowell.common.util.JWTUtils; -import com.jsowell.common.util.PageUtils; -import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.*; import com.jsowell.pile.domain.*; import com.jsowell.pile.domain.ykcCommond.StartChargingCommand; import com.jsowell.pile.dto.*; @@ -588,7 +585,8 @@ public class LianLianPlatformServiceImpl implements ThirdPartyPlatformService { String pileConnectorCode = dto.getPileConnectorCode(); // 查出该桩所属哪个站点 - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); PileStationVO stationVO = pileStationInfoService.getStationInfoByPileSn(pileSn); // 通过站点id查询相关配置信息 ThirdPartyStationRelationVO relationInfo = thirdPartyStationRelationService.selectRelationInfo(stationVO.getId()); @@ -1146,7 +1144,8 @@ public class LianLianPlatformServiceImpl implements ThirdPartyPlatformService { } // 根据桩编号查询数据 // String merchantId = StringUtils.substring(equipAuthSeq, 0, 9); - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); // vo.setSuccStat(1); // 1-失败 0-成功 默认失败 int succStat = 1; int failReason = 0; diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/NeiMengGuPlatformServiceImpl.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/NeiMengGuPlatformServiceImpl.java index ed1e47813..cd4822294 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/NeiMengGuPlatformServiceImpl.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/NeiMengGuPlatformServiceImpl.java @@ -15,10 +15,7 @@ import com.jsowell.common.enums.ykc.BillingTimeTypeEnum; import com.jsowell.common.enums.ykc.PileConnectorDataBaseStatusEnum; import com.jsowell.common.enums.ykc.ReturnCodeEnum; import com.jsowell.common.exception.BusinessException; -import com.jsowell.common.util.DateUtils; -import com.jsowell.common.util.JWTUtils; -import com.jsowell.common.util.PageUtils; -import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.*; import com.jsowell.pile.domain.OrderBasicInfo; import com.jsowell.pile.domain.OrderDetail; import com.jsowell.pile.domain.ThirdPartyPlatformConfig; @@ -365,7 +362,8 @@ public class NeiMengGuPlatformServiceImpl implements ThirdPartyPlatformService { String pileConnectorCode = dto.getPileConnectorCode(); // 查出该桩所属哪个站点 - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); PileStationVO stationVO = pileStationInfoService.getStationInfoByPileSn(pileSn); // 通过站点id查询相关配置信息 ThirdPartyStationRelationVO relationInfo = thirdPartyStationRelationService.selectRelationInfo(stationVO.getId()); diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/QingHaiPlatformServiceImpl.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/QingHaiPlatformServiceImpl.java index 8a85568b3..c65121f23 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/QingHaiPlatformServiceImpl.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/QingHaiPlatformServiceImpl.java @@ -11,10 +11,7 @@ import com.jsowell.common.enums.thirdparty.ThirdPlatformTypeEnum; import com.jsowell.common.enums.ykc.OrderStatusEnum; import com.jsowell.common.enums.ykc.ReturnCodeEnum; import com.jsowell.common.exception.BusinessException; -import com.jsowell.common.util.DateUtils; -import com.jsowell.common.util.JWTUtils; -import com.jsowell.common.util.PageUtils; -import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.*; import com.jsowell.pile.domain.*; import com.jsowell.pile.dto.PushRealTimeInfoDTO; import com.jsowell.pile.dto.QueryConnectorListDTO; @@ -534,7 +531,8 @@ public class QingHaiPlatformServiceImpl implements ThirdPartyPlatformService { return null; } // 截取桩号 - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); // 查询该桩的站点id PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); // 根据桩号查询正在使用的计费模板 diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/ShenZhenPlatformServiceImpl.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/ShenZhenPlatformServiceImpl.java index c31e1f581..490569ad2 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/ShenZhenPlatformServiceImpl.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/ShenZhenPlatformServiceImpl.java @@ -12,10 +12,7 @@ import com.jsowell.common.enums.thirdparty.ThirdPlatformTypeEnum; import com.jsowell.common.enums.ykc.PileConnectorDataBaseStatusEnum; import com.jsowell.common.enums.ykc.ReturnCodeEnum; import com.jsowell.common.exception.BusinessException; -import com.jsowell.common.util.DateUtils; -import com.jsowell.common.util.JWTUtils; -import com.jsowell.common.util.PageUtils; -import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.*; import com.jsowell.pile.domain.OrderBasicInfo; import com.jsowell.pile.domain.ThirdPartyStationRelation; import com.jsowell.pile.dto.PushRealTimeInfoDTO; @@ -487,7 +484,8 @@ public class ShenZhenPlatformServiceImpl implements ThirdPartyPlatformService { public String notificationBMSInfo(String pileConnectorCode) { BMSInfo bmsInfo = null; JSONObject resultJson = new JSONObject(); - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); // 查询枪口状态 PileConnectorInfoVO info = pileConnectorInfoService.getPileConnectorInfoByConnectorCode(pileConnectorCode); Integer connectorStatus = info.getStatus(); diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/zhongdianlian/service/impl/ZDLServiceImpl.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/zhongdianlian/service/impl/ZDLServiceImpl.java index 0fc840029..7177528d5 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/zhongdianlian/service/impl/ZDLServiceImpl.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/zhongdianlian/service/impl/ZDLServiceImpl.java @@ -9,6 +9,7 @@ import com.jsowell.common.constant.Constants; import com.jsowell.common.enums.thirdparty.ThirdPlatformTypeEnum; import com.jsowell.common.util.PageUtils; import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.YKCUtils; import com.jsowell.pile.domain.*; import com.jsowell.pile.dto.*; import com.jsowell.pile.service.*; @@ -503,7 +504,8 @@ public class ZDLServiceImpl implements ZDLService { return null; } // 截取桩号 - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + // String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String pileSn = YKCUtils.getPileSn(pileConnectorCode); // 查询该桩的站点id PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); // 根据桩号查询正在使用的计费模板 diff --git a/jsowell-ui/src/views/pile/station/components/billing.vue b/jsowell-ui/src/views/pile/station/components/billing.vue index ecf73e157..78de25f74 100644 --- a/jsowell-ui/src/views/pile/station/components/billing.vue +++ b/jsowell-ui/src/views/pile/station/components/billing.vue @@ -72,6 +72,14 @@ > + + +