diff --git a/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/PersonPileController.java b/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/PersonPileController.java index be6dd77d0..0741c89e1 100644 --- a/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/PersonPileController.java +++ b/jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/PersonPileController.java @@ -12,6 +12,7 @@ import com.jsowell.common.response.RestApiResponse; import com.jsowell.common.util.StringUtils; import com.jsowell.pile.dto.*; import com.jsowell.pile.service.PileBasicInfoService; +import com.jsowell.pile.service.PileFirmwareInfoService; import com.jsowell.pile.service.PileMerchantInfoService; import com.jsowell.pile.service.PileReservationInfoService; import com.jsowell.pile.vo.PileReservationInfoVO; @@ -52,6 +53,9 @@ public class PersonPileController extends BaseController { @Autowired private PileReservationInfoService pileReservationInfoService; + @Autowired + private PileFirmwareInfoService pileFirmwareInfoService; + /** * 用户绑定个人桩 @@ -91,7 +95,7 @@ public class PersonPileController extends BaseController { */ @RequestMapping("/pileMemberBindingForBT") public RestApiResponse pileMemberBindingForBT(HttpServletRequest request, @RequestBody PileMemberBindingDTO dto) { - logger.info("绑定个人桩信息(蓝牙) params:{}", JSON.toJSONString(dto)); + // logger.info("绑定个人桩信息(蓝牙) params:{}", JSON.toJSONString(dto)); RestApiResponse response = null; try { String memberId = getMemberIdByAuthorization(request); @@ -105,7 +109,7 @@ public class PersonPileController extends BaseController { logger.error("绑定个人桩信息(蓝牙) error,", exception); response = new RestApiResponse<>(ReturnCodeEnum.CODE_BINDING_PERSONAL_PILE_ERROR); } - logger.info("绑定个人桩信息(蓝牙) result:{}", response); + logger.info("绑定个人桩信息(蓝牙), params:{}, result:{}", JSON.toJSONString(dto), JSON.toJSONString(response)); return response; } @@ -509,4 +513,22 @@ public class PersonPileController extends BaseController { logger.info("保存蓝牙充电记录params:{}, result:{}", dto, JSON.toJSONString(response)); return response; } + + /** + * 查询桩升级程序信息列表 + * http://localhost:8080/uniapp/personalPile/selectPileFirmwareList + * @return + */ + @PostMapping("/selectPileFirmwareList") + public RestApiResponse selectPileFirmwareList(@RequestBody PileFirmwareInfoDTO dto) { + RestApiResponse response = null; + try { + PageResponse pageResponse = pileFirmwareInfoService.selectPileFirmwareListByUseRange(dto); + response = new RestApiResponse<>(pageResponse); + } catch (Exception e) { + logger.error("查询桩升级程序信息列表 error, ",e); + } + logger.info("查询桩升级程序信息列表 param:{}, result:{}", JSON.toJSONString(dto), response); + return response; + } } 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 5fff245d9..1fd94afb2 100644 --- a/jsowell-admin/src/main/java/com/jsowell/service/OrderService.java +++ b/jsowell-admin/src/main/java/com/jsowell/service/OrderService.java @@ -149,6 +149,9 @@ public class OrderService { @Resource private RedisCache redisCache; + @Autowired + private PersonalChargingRecordService personalChargingRecordService; + // 引入线程池 private ThreadPoolTaskExecutor executor = SpringUtils.getBean("threadPoolTaskExecutor"); @@ -1451,5 +1454,41 @@ public class OrderService { * @param dto */ public void saveBluetoothChargingRecord(BluetoothChargingRecordDTO dto) { + PersonalChargingRecord record = new PersonalChargingRecord(); + record.setTransactionCode(dto.getTrxSN()); + record.setStatus(OrderStatusEnum.ORDER_COMPLETE.getValue()); + record.setMemberId(dto.getMemberId()); + // record.setStationId(dto.getStationId()); + // record.setMerchantId(dto.getMerchantId()); + record.setPileSn(dto.getPileNo()); + record.setConnectorCode(dto.getPlugNo()); + record.setPileConnectorCode(record.getPileSn() + record.getConnectorCode()); + record.setLogicCard(dto.getPCardID()); + record.setVinCode(dto.getVin()); + record.setStartMode(dto.getStartMode()); + // record.setPlateNumber(dto.getPlateNumber()); + record.setChargeStartTime(DateUtils.parseDate(dto.getStartTime())); + record.setChargeEndTime(DateUtils.parseDate(dto.getEndTime())); + // record.setStartType(dto.getStartType()); + // record.setReservationStartTime(DateUtils.parseDate(dto.getReservationStartTime())); + // record.setReservationEndTime(DateUtils.parseDate(dto.getReservationEndTime())); + // record.setStartSoc(dto.getst()); + // record.setEndSoc(dto.getEndSoc()); + record.setAmmeterTotalStart(dto.getStartKwh()); + record.setAmmeterTotalEnd(dto.getStopKwh()); + record.setTotalUsedElectricity(new BigDecimal(dto.getTotalEnergy())); + record.setSharpUsedElectricity(new BigDecimal(dto.getEnergySharp())); + record.setPeakUsedElectricity(new BigDecimal(dto.getEnergyPeak())); + record.setFlatUsedElectricity(new BigDecimal(dto.getEnergyFlat())); + record.setValleyUsedElectricity(new BigDecimal(dto.getEnergyValley())); + record.setReason(dto.getStopReason()); + record.setTradeDate(DateUtils.parseDate(dto.getTradeTime())); + record.setSourceType("BT"); + record.setCreateBy(dto.getMemberId()); + record.setCreateTime(new Date()); + // record.setUpdateBy(dto.getUpdateBy()); + // record.setUpdateTime(new Date()); + record.setDelFlag(DelFlagEnum.NORMAL.getValue()); + personalChargingRecordService.insertOrUpdateSelective(record); } } 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 d3a983084..28b0b6578 100644 --- a/jsowell-admin/src/main/java/com/jsowell/service/PileService.java +++ b/jsowell-admin/src/main/java/com/jsowell/service/PileService.java @@ -641,6 +641,7 @@ public class PileService { PersonPileConnectorSumInfoVO vo; for (PersonalChargingRecord personalChargingRecord : pageInfo.getList()) { vo = new PersonPileConnectorSumInfoVO(); + vo.setSourceType(personalChargingRecord.getSourceType()); if (personalChargingRecord.getChargeStartTime() != null && personalChargingRecord.getChargeEndTime() != null){ vo.setChargeStartTime(DateUtils.dateTime(personalChargingRecord.getChargeStartTime())); vo.setChargeEndTime(DateUtils.dateTime(personalChargingRecord.getChargeEndTime())); diff --git a/jsowell-admin/src/main/java/com/jsowell/service/TempService.java b/jsowell-admin/src/main/java/com/jsowell/service/TempService.java index 8ef31a78e..58fa26b5c 100644 --- a/jsowell-admin/src/main/java/com/jsowell/service/TempService.java +++ b/jsowell-admin/src/main/java/com/jsowell/service/TempService.java @@ -14,6 +14,7 @@ import com.jsowell.adapay.response.QueryPaymentConfirmDetailResponse; import com.jsowell.adapay.service.AdapayService; import com.jsowell.adapay.vo.OrderSplitResult; import com.jsowell.adapay.vo.PaymentInfo; +import com.jsowell.common.annotation.CostTime; import com.jsowell.common.core.redis.RedisCache; import com.jsowell.common.enums.adapay.AdapayStatusEnum; import com.jsowell.common.enums.ykc.*; @@ -592,6 +593,7 @@ public class TempService { /** * 校验是否为并充订单 */ + @CostTime public Map> checkCombinedChargingOrder(List orderCodeList) throws BaseAdaPayException { Map> resultMap = Maps.newHashMap(); List combinedChargingOrderList = Lists.newArrayList(); diff --git a/jsowell-admin/src/main/java/com/jsowell/web/controller/common/CommonController.java b/jsowell-admin/src/main/java/com/jsowell/web/controller/common/CommonController.java index 1aaa9cfe3..ab2eb210d 100644 --- a/jsowell-admin/src/main/java/com/jsowell/web/controller/common/CommonController.java +++ b/jsowell-admin/src/main/java/com/jsowell/web/controller/common/CommonController.java @@ -219,4 +219,29 @@ public class CommonController { return AjaxResult.error(e.getMessage()); } } + + /** + * 上传蓝牙升级程序到阿里云oss + * http://localhost:8080/common/uploadBlueToothFile2OSS + * @param file + * @return + * @throws Exception + */ + @CrossOrigin + @PostMapping("/uploadBlueToothFile2OSS") + public AjaxResult uploadBlueToothFile2OSS(MultipartFile file) throws Exception { + try { + String url = AliyunOssUploadUtils.uploadBlueToothFile(file); + AjaxResult ajax = AjaxResult.success(); + ajax.put("url", url); + ajax.put("fileName", FileUtils.getName(url)); + ajax.put("newFileName", FileUtils.getName(url)); + ajax.put("originalFilename", file.getOriginalFilename()); + log.info("固件上传成功 url:{}", url); + return ajax; + }catch (Exception e){ + log.error("上传到阿里云oss error, ", e); + return AjaxResult.error(e.getMessage()); + } + } } diff --git a/jsowell-admin/src/main/java/com/jsowell/web/controller/pile/PileFirmwareInfoController.java b/jsowell-admin/src/main/java/com/jsowell/web/controller/pile/PileFirmwareInfoController.java index ffa4b6138..9184d883f 100644 --- a/jsowell-admin/src/main/java/com/jsowell/web/controller/pile/PileFirmwareInfoController.java +++ b/jsowell-admin/src/main/java/com/jsowell/web/controller/pile/PileFirmwareInfoController.java @@ -5,12 +5,15 @@ import com.jsowell.common.core.controller.BaseController; import com.jsowell.common.core.domain.AjaxResult; import com.jsowell.common.core.page.TableDataInfo; import com.jsowell.common.enums.BusinessType; +import com.jsowell.common.response.RestApiResponse; +import com.jsowell.common.util.file.AliyunOssUploadUtils; import com.jsowell.common.util.poi.ExcelUtil; import com.jsowell.pile.domain.PileFirmwareInfo; import com.jsowell.pile.service.PileFirmwareInfoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.util.List; @@ -88,4 +91,19 @@ public class PileFirmwareInfoController extends BaseController { public AjaxResult remove(@PathVariable Long[] ids) { return toAjax(pileFirmwareInfoService.deletePileFirmwareInfoByIds(ids)); } + + + /** + * 上传蓝牙升级程序 + * @param file + * @return + */ + // @PostMapping("/uploadBlueToothFile") + // public AjaxResult uploadBlueToothFile(@RequestParam("blueToothFile") MultipartFile file) { + // if (!file.isEmpty()) { + // String result = AliyunOssUploadUtils.uploadBlueToothFile(file); + // return AjaxResult.success(); + // } + // return AjaxResult.error("上传文件错误!!"); + // } } diff --git a/jsowell-admin/src/main/resources/application-dev.yml b/jsowell-admin/src/main/resources/application-dev.yml index 92f0dd6a0..434cc5f17 100644 --- a/jsowell-admin/src/main/resources/application-dev.yml +++ b/jsowell-admin/src/main/resources/application-dev.yml @@ -141,8 +141,10 @@ aliyunoss: bucketName: ydc-oss-dev # bucket下文件夹的路径 filehost: img + # 蓝牙小程序文件保存路径 + bluetoothFileHost: bluetooth # 访问域名 - # url: https://ydc-oss-dev.oss-cn-shanghai.aliyuncs.com + interviewUrl: https://ydc-oss-prod.oss-cn-shanghai.aliyuncs.com url: http://img.sit.jsowellcloud.com diff --git a/jsowell-admin/src/main/resources/application-prd.yml b/jsowell-admin/src/main/resources/application-prd.yml index d4a8040b7..e0c575db8 100644 --- a/jsowell-admin/src/main/resources/application-prd.yml +++ b/jsowell-admin/src/main/resources/application-prd.yml @@ -140,8 +140,10 @@ aliyunoss: bucketName: ydc-oss-prod # bucket下文件夹的路径 filehost: img + # 蓝牙小程序文件保存路径 + bluetoothFileHost: bluetooth # 访问域名 - # url: https://ydc-oss-prod.oss-cn-shanghai.aliyuncs.com + interviewUrl: https://ydc-oss-prod.oss-cn-shanghai.aliyuncs.com url: https://img.jsowellcloud.com ########################微信支付参数####################################### diff --git a/jsowell-admin/src/main/resources/application-pre.yml b/jsowell-admin/src/main/resources/application-pre.yml index afe982603..90d10c2ae 100644 --- a/jsowell-admin/src/main/resources/application-pre.yml +++ b/jsowell-admin/src/main/resources/application-pre.yml @@ -140,8 +140,10 @@ aliyunoss: bucketName: ydc-oss-prod # bucket下文件夹的路径 filehost: img + # 蓝牙小程序文件保存路径 + bluetoothFileHost: bluetooth # 访问域名 - # url: https://ydc-oss-prod.oss-cn-shanghai.aliyuncs.com + interviewUrl: https://ydc-oss-prod.oss-cn-shanghai.aliyuncs.com url: https://img.jsowellcloud.com ########################微信支付参数####################################### diff --git a/jsowell-admin/src/main/resources/application-sit.yml b/jsowell-admin/src/main/resources/application-sit.yml index fdffe21b0..af7bc8053 100644 --- a/jsowell-admin/src/main/resources/application-sit.yml +++ b/jsowell-admin/src/main/resources/application-sit.yml @@ -140,8 +140,10 @@ aliyunoss: bucketName: ydc-oss-dev # bucket下文件夹的路径 filehost: img + # 蓝牙小程序文件保存路径 + bluetoothFileHost: bluetooth # 访问域名 - # url: https://ydc-oss-dev.oss-cn-shanghai.aliyuncs.com + interviewUrl: https://ydc-oss-prod.oss-cn-shanghai.aliyuncs.com url: http://img.sit.jsowellcloud.com diff --git a/jsowell-admin/src/test/java/SpringBootTestController.java b/jsowell-admin/src/test/java/SpringBootTestController.java index 4d562efae..8dd7d0248 100644 --- a/jsowell-admin/src/test/java/SpringBootTestController.java +++ b/jsowell-admin/src/test/java/SpringBootTestController.java @@ -675,6 +675,14 @@ public class SpringBootTestController { // memberAdapayRecordService.unfreezeAmountAndUpdateSpendAmount("test01", payAmount, refundAmt); } + @Test + public void selectBillingTemplateDetailByPileSnTest() { + String pileSn = "88000000000001"; + // 查询充电桩的计费模板 + BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(pileSn); + System.out.println(JSON.toJSONString(billingTemplateVO)); + } + // 生成订单 private OrderBasicInfo generateAnOrder() throws ParseException { GenerateOrderDTO dto = new GenerateOrderDTO(); diff --git a/jsowell-common/src/main/java/com/jsowell/common/annotation/CostTime.java b/jsowell-common/src/main/java/com/jsowell/common/annotation/CostTime.java new file mode 100644 index 000000000..2467192de --- /dev/null +++ b/jsowell-common/src/main/java/com/jsowell/common/annotation/CostTime.java @@ -0,0 +1,15 @@ +package com.jsowell.common.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 统计函数执行耗时 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface CostTime { + +} \ No newline at end of file diff --git a/jsowell-common/src/main/java/com/jsowell/common/config/AliyunOssConfig.java b/jsowell-common/src/main/java/com/jsowell/common/config/AliyunOssConfig.java index 09b5a9d83..dd883f356 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/config/AliyunOssConfig.java +++ b/jsowell-common/src/main/java/com/jsowell/common/config/AliyunOssConfig.java @@ -1,5 +1,6 @@ package com.jsowell.common.config; +import org.apache.commons.lang3.builder.ToStringBuilder; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @@ -31,6 +32,16 @@ public class AliyunOssConfig { */ private String filehost; + /** + * 蓝牙小程序文件路径 + */ + private String bluetoothFileHost; + + /** + * 访问域名(上传蓝牙固件时用) + */ + private String interviewUrl; + /** * 访问域名 */ @@ -76,6 +87,22 @@ public class AliyunOssConfig { this.filehost = filehost; } + public String getBluetoothFileHost() { + return bluetoothFileHost; + } + + public void setBluetoothFileHost(String bluetoothFileHost) { + this.bluetoothFileHost = bluetoothFileHost; + } + + public String getInterviewUrl() { + return interviewUrl; + } + + public void setInterviewUrl(String interviewUrl) { + this.interviewUrl = interviewUrl; + } + public String getUrl() { return url; } @@ -86,13 +113,15 @@ public class AliyunOssConfig { @Override public String toString() { - return "AliyunOssConfig{" + - "endpoint='" + endpoint + '\'' + - ", accessKeyId='" + accessKeyId + '\'' + - ", accessKeySecret='" + accessKeySecret + '\'' + - ", bucketName='" + bucketName + '\'' + - ", filehost='" + filehost + '\'' + - ", url='" + url + '\'' + - '}'; + return new ToStringBuilder(this) + .append("endpoint", endpoint) + .append("accessKeyId", accessKeyId) + .append("accessKeySecret", accessKeySecret) + .append("bucketName", bucketName) + .append("filehost", filehost) + .append("bluetoothFileHost", bluetoothFileHost) + .append("interviewUrl", interviewUrl) + .append("url", url) + .toString(); } } \ No newline at end of file diff --git a/jsowell-common/src/main/java/com/jsowell/common/constant/CacheConstants.java b/jsowell-common/src/main/java/com/jsowell/common/constant/CacheConstants.java index 10d374ee3..6d5c6822a 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/constant/CacheConstants.java +++ b/jsowell-common/src/main/java/com/jsowell/common/constant/CacheConstants.java @@ -344,4 +344,9 @@ public class CacheConstants { * 验证码有效期时长 redis key */ public static final String SMS_VERIFICATION_CODE_KEY = "sms_verification_code:"; + + /** + * 根据桩号查询计费模板 + */ + public static final String BILLING_TEMPLATE_BY_PILE_SN = "billing_template_by_pile_sn:"; } diff --git a/jsowell-common/src/main/java/com/jsowell/common/util/file/AliyunOssUploadUtils.java b/jsowell-common/src/main/java/com/jsowell/common/util/file/AliyunOssUploadUtils.java index 892343f6d..2d43397b6 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/util/file/AliyunOssUploadUtils.java +++ b/jsowell-common/src/main/java/com/jsowell/common/util/file/AliyunOssUploadUtils.java @@ -1,9 +1,12 @@ package com.jsowell.common.util.file; +import com.alibaba.fastjson2.JSONObject; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.model.ObjectMetadata; +import com.aliyun.oss.model.PutObjectResult; import com.jsowell.common.config.AliyunOssConfig; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; @@ -14,6 +17,7 @@ import java.io.InputStream; import java.time.LocalDateTime; import java.time.ZoneOffset; +@Slf4j @Component public class AliyunOssUploadUtils { @@ -55,7 +59,8 @@ public class AliyunOssUploadUtils { // 文件路径名称 filePathName = aliyunOssConfig.getFilehost() + "/" + dir_name + randomNumber + filePathName; try { - ossClient.putObject(aliyunOssConfig.getBucketName(), filePathName, file.getInputStream()); + PutObjectResult putObjectResult = ossClient.putObject(aliyunOssConfig.getBucketName(), filePathName, file.getInputStream()); + // log.info("上传OSS成功, url:{}", putObjectResult.getResponse().getUri()); } catch (IOException e) { e.printStackTrace(); } finally { @@ -67,7 +72,34 @@ public class AliyunOssUploadUtils { } /** - * 上传到阿里云(车位相机用) + * 上传蓝牙升级程序文件 + * @param file + * @return + */ + public static String uploadBlueToothFile(MultipartFile file) { + // 生成 OSSClient + OSS ossClient = new OSSClientBuilder().build(aliyunOssConfig.getEndpoint(), aliyunOssConfig.getAccessKeyId(), aliyunOssConfig.getAccessKeySecret()); + + // 编码文件名 + String filePathName = FileUploadUtils.extractFilename(file); + + // 拼装路径 + filePathName = aliyunOssConfig.getBluetoothFileHost() + "/files/" + filePathName; + try { + PutObjectResult putObjectResult = ossClient.putObject(aliyunOssConfig.getBucketName(), filePathName, file.getInputStream()); + // log.info("上传蓝牙升级文件到OSS成功, putObjectResult:{}", JSONObject.toJSONString(putObjectResult)); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (ossClient != null) { + ossClient.shutdown(); + } + } + return aliyunOssConfig.getInterviewUrl() + "/" + filePathName; + } + + /** + * 车位相机图片上传到阿里云(车位相机用) * @param compressedImageBytes * @param fileName 文件名 (车位号 + 时间戳).jpg * @return diff --git a/jsowell-framework/pom.xml b/jsowell-framework/pom.xml index bcadd8a8b..e31ffef36 100644 --- a/jsowell-framework/pom.xml +++ b/jsowell-framework/pom.xml @@ -68,6 +68,10 @@ + + org.projectlombok + lombok + diff --git a/jsowell-framework/src/main/java/com/jsowell/framework/aspectj/CostTimeAspect.java b/jsowell-framework/src/main/java/com/jsowell/framework/aspectj/CostTimeAspect.java new file mode 100644 index 000000000..cf6dc7a80 --- /dev/null +++ b/jsowell-framework/src/main/java/com/jsowell/framework/aspectj/CostTimeAspect.java @@ -0,0 +1,54 @@ +package com.jsowell.framework.aspectj; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@Aspect +@Order(1) +@Component// 使用spring容器进行管理 +public class CostTimeAspect { + private static final Logger logger = LoggerFactory.getLogger(CostTimeAspect.class); + /** + * 首先定义一个切点 + */ + // @org.aspectj.lang.annotation.Pointcut("@annotation(com.counttime.annotation.entity.CostTime)") + // @org.aspectj.lang.annotation.Pointcut("@annotation(com.jsowell.common.annotation.CostTime)") + // public void countTime() { + // + // } + + // @Around("countTime()") + // public Object doAround(ProceedingJoinPoint joinPoint) { + // Object obj = null; + // try { + // long beginTime = System.currentTimeMillis(); + // obj = joinPoint.proceed(); + // // 获取方法名称 + // String methodName = joinPoint.getSignature().getName(); + // // 获取类名称 + // String className = joinPoint.getSignature().getDeclaringTypeName(); + // log.info("统计方法耗时, 类:[{}], 方法:[{}], 耗时时间为:[{}ms]", className, methodName, (System.currentTimeMillis() - beginTime)); + // } catch (Throwable throwable) { + // throwable.printStackTrace(); + // } + // return obj; + // } + + @Around("@annotation(com.jsowell.common.annotation.CostTime)") + public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable { + long startTime = System.currentTimeMillis(); + try { + return joinPoint.proceed(); + } finally { + long endTime = System.currentTimeMillis(); + long timeConsumed = endTime - startTime; + logger.info("方法 {} 耗时 {} 毫秒", joinPoint.getSignature().toShortString(), timeConsumed); + } + } +} + diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/factory/YKCOperateFactoryV2.java b/jsowell-netty/src/main/java/com/jsowell/netty/factory/YKCOperateFactoryV2.java new file mode 100644 index 000000000..2f976f8bd --- /dev/null +++ b/jsowell-netty/src/main/java/com/jsowell/netty/factory/YKCOperateFactoryV2.java @@ -0,0 +1,48 @@ +package com.jsowell.netty.factory; + +import com.jsowell.netty.strategy.ykc.AbstractYkcStrategy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +/** + * 工厂设计模式 + * 云快充操作 + */ +@Component +public class YKCOperateFactoryV2 { + + @Autowired + private Map strategyMap; + + private static Map operationMap = new HashMap<>(); + + static { + //初始化实现类 + operationMap.put("0x01", "loginRequestStrategy"); + operationMap.put("0x05", "billingTemplateValidateRequestStrategy"); + // more operators + } + + /** + * 注册 + * @param str + * @param handler + */ + // public void register(String str, AbstractYkcHandlerV2 handler) { + // if (StringUtils.isBlank(str) || Objects.isNull(handler)) { + // return; + // } + // strategyMap.put(str, handler); + // } + + /** + * 获取 + */ + public AbstractYkcStrategy getInvokeStrategy(String frameType) { + String s = operationMap.get(frameType); + return strategyMap.get(s); + } +} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/AbstractYkcHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/AbstractYkcHandler.java index 6045d4df2..514244d2d 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/AbstractYkcHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/AbstractYkcHandler.java @@ -24,26 +24,10 @@ public abstract class AbstractYkcHandler implements InitializingBean { private static final String REQUEST_PREFIX = "Request_"; - /** - * 执行逻辑 - * 有应答 - */ - // public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, Channel channel) { - // throw new UnsupportedOperationException(); - // } - public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { throw new UnsupportedOperationException(); } - /** - * 执行逻辑 - * 不需要应答 - */ - // public void pushProcess() { - // throw new UnsupportedOperationException(); - // } - /** * 组装应答的结果 * @param ykcDataProtocol 请求数据 diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/LoginRequestHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/LoginRequestHandler.java index 58a57c36c..567826722 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/LoginRequestHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/LoginRequestHandler.java @@ -115,6 +115,7 @@ public class LoginRequestHandler extends AbstractYkcHandler { String business = BytesUtil.bcd2Str(businessTypeByteArr); } + @Override public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext ctx) { if (verifyTheDuplicateRequest(ykcDataProtocol, ctx)) { diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/ParameterConfigurationHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/ParameterConfigurationHandler.java index d63f93704..544e6fd92 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/ParameterConfigurationHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/ParameterConfigurationHandler.java @@ -12,6 +12,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.math.BigDecimal; import java.util.Objects; /** @@ -60,28 +61,34 @@ public class ParameterConfigurationHandler extends AbstractYkcHandler { startIndex += length; length = 1; byte[] pileConnectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileConnectorCode = BytesUtil.bcd2Str(pileConnectorNumByteArr); // BMS 单体动力蓄电池最高允许充电电压 0.01 V/位, 0 V 偏移量; 数据范围: 0~24 V startIndex += length; length = 2; byte[] BMSMaxVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String BMSMaxVoltage = String.valueOf(BytesUtil.bytesToIntLittle(BMSMaxVoltageByteArr) * 0.01); // BMS 最高允许充电电流 0.1 A/位, -400A 偏移量 startIndex += length; byte[] BMSMaxCurrentByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String BMSMaxCurrent = String.valueOf(BytesUtil.bytesToIntLittle(BMSMaxCurrentByteArr) * 0.1 - 400); // BMS 动力蓄电池标称总能量 0.1 kWh/位, 0 kWh 偏移量; 数据范围: 0~1000 kWh startIndex += length; byte[] BMSSumEnergyByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String BMSSumEnergy = String.valueOf(BytesUtil.bytesToIntLittle(BMSSumEnergyByteArr) * 0.1); // BMS 最高允许充电总电压 0.1 V/位, 0 V 偏移量 startIndex += length; byte[] BMSMaxChargingVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String BMSMaxChargingVoltage = String.valueOf(BytesUtil.bytesToIntLittle(BMSMaxChargingVoltageByteArr) * 0.1); // BMS 最高允许温度 1ºC/位, -50 ºC 偏移量;数据范 围: -50 ºC ~+200 ºC startIndex += length; length = 1; byte[] BMSMaxTemperatureByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String BMSMaxTemperature = String.valueOf(BytesUtil.bytesToIntLittle(BMSMaxTemperatureByteArr) - 50); // BMS 整车动力 蓄电池荷电状态(soc) 0.1%/位, 0%偏移量;数据范围: 0~100% startIndex += length; @@ -89,26 +96,30 @@ public class ParameterConfigurationHandler extends AbstractYkcHandler { byte[] BMSSocByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); String soc = YKCUtils.convertVoltageCurrent(BMSSocByteArr); - // BMS 整车动力蓄电池当前电池电压 整车动力蓄电池总电压 startIndex += length; byte[] BMSRealTimeVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String BMSRealTimeVoltage = String.valueOf(BytesUtil.bytesToIntLittle(BMSRealTimeVoltageByteArr) * 0.1); // 电桩最高输出电压 0.1 V /位, 0 V 偏移量 startIndex += length; byte[] pileMaxOutputVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileMaxOutputVoltage = String.valueOf(BytesUtil.bytesToIntLittle(pileMaxOutputVoltageByteArr) * 0.1); // 电桩最低输出电压 0.1 V /位, 0 V 偏移量 startIndex += length; byte[] pileMinOutputVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileMinOutputVoltage = String.valueOf(BytesUtil.bytesToIntLittle(pileMinOutputVoltageByteArr) * 0.1); // 电桩最大输出电流 0.1 A/位, -400 A 偏移量 startIndex += length; byte[] pileMaxOutputCurrentByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileMaxOutputCurrent = String.valueOf(BytesUtil.bytesToIntLittle(pileMaxOutputCurrentByteArr) * 0.1 - 400); // 电桩最小输出电流 0.1 A/位, -400 A 偏移量 startIndex += length; byte[] pileMinOutputCurrentByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileMinOutputCurrent = String.valueOf(BytesUtil.bytesToIntLittle(pileMinOutputCurrentByteArr) * 0.1 - 400); // 查询该订单下信息,将起始soc传入 OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByTransactionCode(transactionCode); diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/service/yunkuaichong/impl/YKCBusinessServiceImpl.java b/jsowell-netty/src/main/java/com/jsowell/netty/service/yunkuaichong/impl/YKCBusinessServiceImpl.java index 7a996d323..ad7971900 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/service/yunkuaichong/impl/YKCBusinessServiceImpl.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/service/yunkuaichong/impl/YKCBusinessServiceImpl.java @@ -7,6 +7,7 @@ import com.jsowell.common.enums.ykc.PileConnectorDataBaseStatusEnum; import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.YKCUtils; import com.jsowell.netty.factory.YKCOperateFactory; +import com.jsowell.netty.factory.YKCOperateFactoryV2; import com.jsowell.netty.handler.yunkuaichong.AbstractYkcHandler; import com.jsowell.netty.service.yunkuaichong.YKCBusinessService; import com.jsowell.pile.service.OrderBasicInfoService; @@ -31,6 +32,9 @@ public class YKCBusinessServiceImpl implements YKCBusinessService { @Autowired private OrderBasicInfoService orderBasicInfoService; + @Autowired + private YKCOperateFactoryV2 ykcOperateFactoryV2; // 使用注解注入 + @Override public byte[] process(byte[] msg, ChannelHandlerContext ctx) { if (!YKCUtils.checkMsg(msg)) { @@ -42,6 +46,7 @@ public class YKCBusinessServiceImpl implements YKCBusinessService { String frameType = YKCUtils.frameType2Str(ykcDataProtocol.getFrameType()); // 获取业务处理handler AbstractYkcHandler invokeStrategy = YKCOperateFactory.getInvokeStrategy(frameType); + // AbstractYkcHandlerV2 invokeStrategy = ykcOperateFactoryV2.getInvokeStrategy(frameType); return invokeStrategy.supplyProcess(ykcDataProtocol, ctx); } diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/AbstractYkcStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/AbstractYkcStrategy.java new file mode 100644 index 000000000..b0d21d0dc --- /dev/null +++ b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/AbstractYkcStrategy.java @@ -0,0 +1,85 @@ +package com.jsowell.netty.strategy.ykc; + +import com.google.common.primitives.Bytes; +import com.jsowell.common.constant.CacheConstants; +import com.jsowell.common.core.domain.ykc.YKCDataProtocol; +import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; +import com.jsowell.common.core.redis.StaticRedisCache; +import com.jsowell.common.enums.ykc.PileChannelEntity; +import com.jsowell.common.util.BytesUtil; +import com.jsowell.common.util.CRC16Util; +import com.jsowell.common.util.DateUtils; +import com.jsowell.common.util.YKCUtils; +import io.netty.channel.ChannelHandlerContext; + +/** + * 模板方法模式 + */ +public interface AbstractYkcStrategy { + + String REQUEST_PREFIX = "Request_"; + + + byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel); + + /** + * 组装应答的结果 + * @param ykcDataProtocol 请求数据 + * @param messageBody 消息体 + * @return 应答结果 + */ + default byte[] getResult(YKCDataProtocol ykcDataProtocol, byte[] messageBody) { + // 起始标志 + byte[] head = ykcDataProtocol.getHead(); + + // 序列号域 + byte[] serialNumber = ykcDataProtocol.getSerialNumber(); + + // 加密标志 + byte[] encryptFlag = ykcDataProtocol.getEncryptFlag(); + + // 请求帧类型 + byte[] requestFrameType = ykcDataProtocol.getFrameType(); + + // 应答帧类型 + byte[] responseFrameType = YKCFrameTypeCode.PlatformAnswersRelation.getResponseFrameTypeBytes(requestFrameType); + + // 数据域 值为“序列号域+加密标志+帧类型标志+消息体”字节数之和 + byte[] dataFields = Bytes.concat(serialNumber, encryptFlag, responseFrameType, messageBody); + + // 计算crc: 从序列号域到数据域的 CRC 校验 + int crc16 = CRC16Util.calcCrc16(dataFields); + + return Bytes.concat(head, BytesUtil.intToBytes(dataFields.length, 1), dataFields, BytesUtil.intToBytes(crc16)); + } + + /** + * 保存桩最后链接到平台的时间 + * @param pileSn 桩编号 + */ + default void saveLastTimeAndCheckChannel(String pileSn, ChannelHandlerContext ctx) { + String redisKey = CacheConstants.PILE_LAST_CONNECTION + pileSn; + StaticRedisCache.staticRedisCache.setCacheObject(redisKey, DateUtils.getDateTime(), CacheConstants.cache_expire_time_30d); + + // 保存桩号和channel的关系 + PileChannelEntity.checkChannel(pileSn, ctx); + } + + /** + * 阻止重复帧 + * @return true 重复 + */ + default boolean verifyTheDuplicateRequest(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext ctx) { + // 获取序列号域 + int serialNumber = BytesUtil.bytesToIntLittle(ykcDataProtocol.getSerialNumber()); + // 获取帧类型 + String frameTypeStr = YKCUtils.frameType2Str(ykcDataProtocol.getFrameType()); + // 获取channelId + String channelId = ctx.channel().id().asShortText(); + String redisKey = REQUEST_PREFIX + channelId + "_" + frameTypeStr; + Boolean result = StaticRedisCache.staticRedisCache.setnx(redisKey, ykcDataProtocol.getHEXString(), 30); + // result返回false说明没有设置成功,就是说已经有相同请求了,所以返回true重复 + return !result; + } + +} \ No newline at end of file diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BillingTemplateValidateRequestStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BillingTemplateValidateRequestStrategy.java new file mode 100644 index 000000000..9cc37a92c --- /dev/null +++ b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/BillingTemplateValidateRequestStrategy.java @@ -0,0 +1,69 @@ +package com.jsowell.netty.strategy.ykc; + +import com.google.common.primitives.Bytes; +import com.jsowell.common.annotation.CostTime; +import com.jsowell.common.constant.Constants; +import com.jsowell.common.core.domain.ykc.YKCDataProtocol; +import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; +import com.jsowell.common.util.BytesUtil; +import com.jsowell.common.util.YKCUtils; +import com.jsowell.pile.service.PileBillingTemplateService; +import com.jsowell.pile.service.YKCPushCommandService; +import io.netty.channel.ChannelHandlerContext; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 计费模板验证请求Handler + * + * @author JS-ZZA + * @date 2022/9/17 14:10 + */ +@Slf4j +@Service +public class BillingTemplateValidateRequestStrategy implements AbstractYkcStrategy { + + private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.BILLING_TEMPLATE_VALIDATE_CODE.getBytes()); + + @Autowired + private PileBillingTemplateService pileBillingTemplateService; + + @Autowired + private YKCPushCommandService ykcPushCommandService; + + // @Override + // public void afterPropertiesSet() throws Exception { + // YKCOperateFactory.register(type, this); + // } + @CostTime + @Override + public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { + // log.info("[===执行计费模板验证请求逻辑===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); + // 获取消息体 + byte[] msgBody = ykcDataProtocol.getMsgBody(); + + int startIndex = 0; + int length = 7; + + // 桩号 + byte[] pileSnByte = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileSn = BytesUtil.binary(pileSnByte, 16); + + // 保存时间 + saveLastTimeAndCheckChannel(pileSn, channel); + + // 计费模型编码 + startIndex += length; + length = 2; + byte[] billingTemplateCodeByte = BytesUtil.copyBytes(msgBody, startIndex, length); + String billingTemplateCode = BytesUtil.binary(billingTemplateCodeByte, 16); + + // byte[] flag = Constants.oneByteArray; 0x00 桩计费模型与平台一致 0x01桩计费模型与平台不一致 + byte[] flag = Constants.zeroByteArray; + + // 消息体 + byte[] messageBody = Bytes.concat(pileSnByte, billingTemplateCodeByte, flag); + return getResult(ykcDataProtocol, messageBody); + } +} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/LoginRequestStrategy.java b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/LoginRequestStrategy.java new file mode 100644 index 000000000..4f060b33f --- /dev/null +++ b/jsowell-netty/src/main/java/com/jsowell/netty/strategy/ykc/LoginRequestStrategy.java @@ -0,0 +1,284 @@ +package com.jsowell.netty.strategy.ykc; + +import com.alibaba.fastjson2.JSON; +import com.google.common.collect.Lists; +import com.google.common.primitives.Bytes; +import com.jsowell.common.annotation.CostTime; +import com.jsowell.common.constant.Constants; +import com.jsowell.common.core.domain.ykc.LoginRequestData; +import com.jsowell.common.core.domain.ykc.YKCDataProtocol; +import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; +import com.jsowell.common.util.BytesUtil; +import com.jsowell.common.util.StringUtils; +import com.jsowell.common.util.YKCUtils; +import com.jsowell.common.util.spring.SpringUtils; +import com.jsowell.pile.domain.PileBasicInfo; +import com.jsowell.pile.domain.ykcCommond.IssueQRCodeCommand; +import com.jsowell.pile.domain.ykcCommond.ProofreadTimeCommand; +import com.jsowell.pile.domain.ykcCommond.PublishPileBillingTemplateCommand; +import com.jsowell.pile.service.PileBasicInfoService; +import com.jsowell.pile.service.PileBillingTemplateService; +import com.jsowell.pile.service.PileMsgRecordService; +import com.jsowell.pile.service.YKCPushCommandService; +import com.jsowell.pile.vo.web.BillingTemplateVO; +import io.netty.channel.ChannelHandlerContext; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +@Slf4j +@Service +public class LoginRequestStrategy implements AbstractYkcStrategy { + private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.LOGIN_CODE.getBytes()); + + @Autowired + private PileBasicInfoService pileBasicInfoService; + + @Autowired + private YKCPushCommandService ykcPushCommandService; + + @Autowired + private PileMsgRecordService pileMsgRecordService; + + @Autowired + private PileBillingTemplateService pileBillingTemplateService; + + private List newProgramVersionList = Lists.newArrayList("c6-30"); + + // 引入线程池 + private ThreadPoolTaskExecutor executor = SpringUtils.getBean("threadPoolTaskExecutor"); + + // @Override + // public void afterPropertiesSet() throws Exception { + // YKCOperateFactory.register(type, this); + // } + + public static void main(String[] args) { + String msg = "8800000000009000020f56312e323035303000898604940121c138531304"; + byte[] msgBody = BytesUtil.str2Bcd(msg); + + int startIndex = 0; + int length = 7; + + // 桩编码 + byte[] pileSnByte = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileSn = BytesUtil.binary(pileSnByte, 16); + // log.info("桩号:{}", pileSn); + + // 桩类型 0 表示直流桩, 1 表示交流桩 + startIndex += length; + length = 1; + byte[] pileTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileType = BytesUtil.bcd2Str(pileTypeByteArr); + + // 充电枪数量 + startIndex += length; + byte[] connectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String connectorNum = BytesUtil.bcd2Str(connectorNumByteArr); + + // 通信协议版本 版本号乘 10,v1.0 表示 0x0A + startIndex += length; + byte[] communicationVersionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + // int i = Integer.parseInt(BytesUtil.bcd2Str(communicationVersionByteArr)); // 0F --> 15 + BigDecimal bigDecimal = new BigDecimal(BytesUtil.bcd2Str(communicationVersionByteArr)); + BigDecimal communicationVersionTemp = bigDecimal.divide(new BigDecimal(10)); + String communicationVersion = "v" + communicationVersionTemp; + + // 程序版本 + startIndex += length; + length = 8; + byte[] programVersionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String programVersion = BytesUtil.ascii2Str(programVersionByteArr); + log.info("程序版本:{} length:{}", programVersion, programVersion.length()); + + // 网络连接类型 0x00 SIM 卡 0x01 LAN 0x02 WAN 0x03 其他 + startIndex += length; + length = 1; + byte[] internetConnectionTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String internetConnection = BytesUtil.bcd2Str(internetConnectionTypeByteArr); + + // sim卡 + startIndex += length; + length = 10; + byte[] simCardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String iccid = BytesUtil.bin2HexStr(simCardNumByteArr); + + // 运营商 0x00 移动 0x02 电信 0x03 联通 0x04 其他 + startIndex += length; + length = 1; + byte[] businessTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String business = BytesUtil.bcd2Str(businessTypeByteArr); + } + + @CostTime + @Override + public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext ctx) { + if (verifyTheDuplicateRequest(ykcDataProtocol, ctx)) { + // 阻止重复帧 + return null; + } + + // 获取消息体 + byte[] msgBody = ykcDataProtocol.getMsgBody(); + + int startIndex = 0; + int length = 7; + + // 桩编码 + byte[] pileSnByte = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileSn = BytesUtil.binary(pileSnByte, 16); + + // 保存时间 + saveLastTimeAndCheckChannel(pileSn, ctx); + + // 桩类型 0 表示直流桩, 1 表示交流桩 + startIndex += length; + length = 1; + byte[] pileTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileType = BytesUtil.bcd2Str(pileTypeByteArr); + + // 充电枪数量 + startIndex += length; + byte[] connectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String connectorNum = BytesUtil.bcd2Str(connectorNumByteArr); + + // 通信协议版本 版本号乘 10,v1.0 表示 0x0A + startIndex += length; + byte[] communicationVersionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + BigDecimal bigDecimal = new BigDecimal(BytesUtil.bcd2Str(communicationVersionByteArr)); + BigDecimal communicationVersionTemp = bigDecimal.divide(new BigDecimal(10)); + String communicationVersion = "v" + communicationVersionTemp; + + // 程序版本 + startIndex += length; + length = 8; + byte[] programVersionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String programVersion = BytesUtil.ascii2Str(programVersionByteArr); + // log.info("程序版本:{} length:{}", programVersion, programVersion.length()); + + // 网络连接类型 0x00 SIM 卡 0x01 LAN 0x02 WAN 0x03 其他 + startIndex += length; + length = 1; + byte[] internetConnectionTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String internetConnection = BytesUtil.bcd2Str(internetConnectionTypeByteArr); + + // sim卡 + startIndex += length; + length = 10; + byte[] simCardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String iccid = BytesUtil.bin2HexStr(simCardNumByteArr); + + // 运营商 0x00 移动 0x02 电信 0x03 联通 0x04 其他 + startIndex += length; + length = 1; + byte[] businessTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String business = BytesUtil.bcd2Str(businessTypeByteArr); + + // *********************** 字段解析完成,下面进行逻辑处理 *********************** // + LoginRequestData loginRequestData = LoginRequestData.builder() + .pileSn(pileSn) + .pileType(pileType) + .connectorNum(connectorNum) + .communicationVersion(communicationVersion) + .programVersion(programVersion) + .internetConnection(internetConnection) + .iccid(iccid) + .business(business) + .build(); + + // 结果(默认 0x01:登录失败) + byte[] flag = Constants.oneByteArray; + + // 通过桩编码SN查询数据库,如果有数据,则登录成功,否则登录失败 + PileBasicInfo pileBasicInfo = null; + try { + pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); + } catch (Exception e) { + log.error("selectPileBasicInfoBySN发生异常", e); + } + + if (pileBasicInfo != null) { + flag = Constants.zeroByteArray; + + // 异步修改充电桩状态 + CompletableFuture.runAsync(() -> { + try { + // 更改桩和该桩下的枪口状态分别为 在线、空闲 公共方法修改状态 + pileBasicInfoService.updateStatus(BytesUtil.bcd2Str(ykcDataProtocol.getFrameType()), pileSn, null, null, null); + } catch (Exception e) { + e.printStackTrace(); + } + }, executor); + + // 异步发送对时指令 + CompletableFuture.runAsync(() -> { + try { + Thread.sleep(200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // 对时 + ProofreadTimeCommand command = ProofreadTimeCommand.builder().pileSn(pileSn).build(); + ykcPushCommandService.pushProofreadTimeCommand(command); + }, executor); + + // log.info("下面进行下发二维码 pileSn:{}, thread:{}", pileSn, Thread.currentThread().getName()); + // 异步发送下发二维码指令 + CompletableFuture.runAsync(() -> { + try { + Thread.sleep(600); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // 下发二维码 + IssueQRCodeCommand issueQRCodeCommand = IssueQRCodeCommand.builder().pileSn(pileSn).build(); + ykcPushCommandService.pushIssueQRCodeCommand(issueQRCodeCommand); + }, executor); + + // 异步发送0x58 + CompletableFuture.runAsync(() -> { + // 查询计费模板 + BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(pileSn); + PublishPileBillingTemplateCommand command = PublishPileBillingTemplateCommand.builder() + .pileSn(pileSn) + .billingTemplateVO(billingTemplateVO) + .build(); + // 发送请求 + ykcPushCommandService.pushPublishPileBillingTemplate(command); + }, executor); + + if (StringUtils.equals("00", internetConnection)) { + CompletableFuture.runAsync(() -> { + // 充电桩使用的sim卡,把信息存库 + try { + // pileBasicInfoService.updatePileSimInfo(pileSn, iccid); + // pileBasicInfoService.updatePileSimInfoV2(pileSn, iccid); + pileBasicInfoService.bindPileSimCard(pileSn, iccid); + } catch (Exception e) { + log.error("更新充电桩sim卡信息失败pileSn:{}, iccid:{}", pileSn, iccid, e); + } + }, executor); + } + } + + // 异步保持登录报文 + CompletableFuture.runAsync(() -> { + // 保存报文 没有登录认证通过还要不要保存报文? + try { + String jsonMsg = JSON.toJSONString(loginRequestData); + pileMsgRecordService.save(pileSn, pileSn, type, jsonMsg, ykcDataProtocol.getHEXString()); + } catch (Exception e) { + log.error("保存报文失败pileSn:{}", pileSn, e); + } + }, executor); + + // 消息体 + byte[] messageBody = Bytes.concat(pileSnByte, flag); + return getResult(ykcDataProtocol, messageBody); + } +} diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/domain/PersonalChargingRecord.java b/jsowell-pile/src/main/java/com/jsowell/pile/domain/PersonalChargingRecord.java index ece957c1f..2958eb285 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/domain/PersonalChargingRecord.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/domain/PersonalChargingRecord.java @@ -1,7 +1,5 @@ package com.jsowell.pile.domain; -import java.math.BigDecimal; -import java.util.Date; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -9,9 +7,12 @@ import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import lombok.experimental.SuperBuilder; +import java.math.BigDecimal; +import java.util.Date; + /** - * 个人充电桩的充电记录 - */ + * 个人充电桩的充电记录 + */ @Data @Accessors(chain = true) @SuperBuilder @@ -20,157 +21,177 @@ import lombok.experimental.SuperBuilder; @NoArgsConstructor public class PersonalChargingRecord { /** - * 主键 - */ + * 主键 + */ private Integer id; /** - * 交易流水号 - */ + * 交易流水号 + */ private String transactionCode; /** - * 订单状态(0-未启动;1-充电中;2-待结算;3-待补缴;4-异常;5-可疑;6-订单完成;7-超时关闭) - */ + * 订单状态(0-未启动;1-充电中;2-待结算;3-待补缴;4-异常;5-可疑;6-订单完成;7-超时关闭) + */ private String status; /** - * 会员id - */ + * 会员id + */ private String memberId; /** - * 站点id - */ + * 站点id + */ private String stationId; /** - * 运营商id - */ + * 运营商id + */ private String merchantId; /** - * 充电桩sn - */ + * 充电桩sn + */ private String pileSn; /** - * 充电桩枪口号 - */ + * 充电桩枪口号 + */ private String connectorCode; /** - * 充电桩枪口编号 - */ + * 充电桩枪口编号 + */ private String pileConnectorCode; /** - * 卡启动时的卡号 - */ + * 卡启动时的卡号 + */ private String logicCard; /** - * vin启动时的vin码 - */ + * vin启动时的vin码 + */ private String vinCode; /** - * 启动方式(0-后管启动;1-用户app启动;2-卡启动;3-离线卡启动; 4-第三方平台启动; 5-车辆vin码启动) - */ + * 启动方式(0-后管启动;1-用户app启动;2-卡启动;3-离线卡启动; 4-第三方平台启动; 5-车辆vin码启动) + */ private String startMode; /** - * 车牌号码 - */ + * 车牌号码 + */ private String plateNumber; /** - * 充电开始时间 - */ + * 充电开始时间 + */ private Date chargeStartTime; /** - * 充电结束时间 - */ + * 充电结束时间 + */ private Date chargeEndTime; /** - * 启动类型(now-立即启动;reservation-预约启动) - */ + * 启动类型(now-立即启动;reservation-预约启动) + */ private String startType; /** - * 预约开始时间 - */ + * 预约开始时间 + */ private Date reservationStartTime; /** - * 预约结束时间 - */ + * 预约结束时间 + */ private Date reservationEndTime; /** - * 开始SOC - */ + * 开始SOC + */ private String startSoc; /** - * 结束SOC - */ + * 结束SOC + */ private String endSoc; /** - * 总用电量 - */ + * 电表总起值 + */ + private String ammeterTotalStart; + + /** + * 电表总止值 + */ + private String ammeterTotalEnd; + + /** + * 总用电量 + */ private BigDecimal totalUsedElectricity; /** - * 尖时段用电量 - */ + * 尖时段用电量 + */ private BigDecimal sharpUsedElectricity; /** - * 峰时段用电量 - */ + * 峰时段用电量 + */ private BigDecimal peakUsedElectricity; /** - * 平时段用电量 - */ + * 平时段用电量 + */ private BigDecimal flatUsedElectricity; /** - * 谷时段用电量 - */ + * 谷时段用电量 + */ private BigDecimal valleyUsedElectricity; /** - * 异常原因 - */ + * 异常原因 + */ private String reason; /** - * 创建人 - */ + * 交易日期 + */ + private Date tradeDate; + + /** + * 来源(4G/BT) + */ + private String sourceType; + + /** + * 创建人 + */ private String createBy; /** - * 创建时间 - */ + * 创建时间 + */ private Date createTime; /** - * 更新人 - */ + * 更新人 + */ private String updateBy; /** - * 更新时间 - */ + * 更新时间 + */ private Date updateTime; /** - * 删除标识(0-正常;1-删除) - */ + * 删除标识(0-正常;1-删除) + */ private String delFlag; } \ No newline at end of file diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/domain/PileFirmwareInfo.java b/jsowell-pile/src/main/java/com/jsowell/pile/domain/PileFirmwareInfo.java index c59f1ed57..a10369ed0 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/domain/PileFirmwareInfo.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/domain/PileFirmwareInfo.java @@ -47,6 +47,18 @@ public class PileFirmwareInfo extends BaseEntity { @Excel(name = "适用类型") private String applyType; + /** + * 使用范围 + */ + @Excel(name = "使用范围") + private String useRange; + + /** + * 下载链接url + */ + @Excel(name = "下载链接url") + private String downloadUrl; + /** * 删除标识(0-正常;1-删除) */ @@ -54,16 +66,15 @@ public class PileFirmwareInfo extends BaseEntity { @Override public String toString() { - return new ToStringBuilder(this, ToStringStyle.JSON_STYLE) - .append("id", getId()) - .append("name", getName()) - .append("desc", getDescription()) - .append("filePath", getFilePath()) - .append("createTime", getCreateTime()) - .append("createBy", getCreateBy()) - .append("updateTime", getUpdateTime()) - .append("updateBy", getUpdateBy()) - .append("delFlag", getDelFlag()) + return new ToStringBuilder(this) + .append("id", id) + .append("name", name) + .append("description", description) + .append("filePath", filePath) + .append("applyType", applyType) + .append("useRange", useRange) + .append("downloadUrl", downloadUrl) + .append("delFlag", delFlag) .toString(); } } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/dto/BluetoothChargingRecordDTO.java b/jsowell-pile/src/main/java/com/jsowell/pile/dto/BluetoothChargingRecordDTO.java index 1feae3ff2..4be34f887 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/dto/BluetoothChargingRecordDTO.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/dto/BluetoothChargingRecordDTO.java @@ -2,6 +2,8 @@ package com.jsowell.pile.dto; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; /** * 蓝牙充电记录 @@ -95,7 +97,6 @@ public class BluetoothChargingRecordDTO { @JsonProperty(value = "MoneyValley") private String moneyValley; - // 电表总起值 @JsonProperty(value = "StartKwh") private String startKwh; @@ -135,4 +136,42 @@ public class BluetoothChargingRecordDTO { // 物理卡号 @JsonProperty(value = "PCardID") private String pCardID; + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.JSON_STYLE) + .append("memberId", memberId) + .append("trxSN", trxSN) + .append("pileNo", pileNo) + .append("plugNo", plugNo) + .append("startTime", startTime) + .append("endTime", endTime) + .append("priceSharp", priceSharp) + .append("energySharp", energySharp) + .append("lossKwhSharp", lossKwhSharp) + .append("moneySharp", moneySharp) + .append("pricePeak", pricePeak) + .append("energyPeak", energyPeak) + .append("lossKwhPeak", lossKwhPeak) + .append("moneyPeak", moneyPeak) + .append("priceFlat", priceFlat) + .append("energyFlat", energyFlat) + .append("lossKwhFlat", lossKwhFlat) + .append("moneyFlat", moneyFlat) + .append("priceValley", priceValley) + .append("energyValley", energyValley) + .append("lossKwhValley", lossKwhValley) + .append("moneyValley", moneyValley) + .append("startKwh", startKwh) + .append("stopKwh", stopKwh) + .append("totalEnergy", totalEnergy) + .append("lossTotalKwh", lossTotalKwh) + .append("totalMoney", totalMoney) + .append("vin", vin) + .append("startMode", startMode) + .append("tradeTime", tradeTime) + .append("stopReason", stopReason) + .append("pCardID", pCardID) + .toString(); + } } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/dto/PileFirmwareInfoDTO.java b/jsowell-pile/src/main/java/com/jsowell/pile/dto/PileFirmwareInfoDTO.java new file mode 100644 index 000000000..6fe65c6ff --- /dev/null +++ b/jsowell-pile/src/main/java/com/jsowell/pile/dto/PileFirmwareInfoDTO.java @@ -0,0 +1,30 @@ +package com.jsowell.pile.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 查询桩固件DTO + * + * @author Lemon + * @Date 2024/11/21 16:03:18 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class PileFirmwareInfoDTO { + + private Integer pageNo; + + private Integer pageSize; + + /** + * 使用范围 + * 1-4G;2-蓝牙 + */ + private String useRange; + +} diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/mapper/OrderBasicInfoMapper.java b/jsowell-pile/src/main/java/com/jsowell/pile/mapper/OrderBasicInfoMapper.java index 688939576..6f6e22b5c 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/mapper/OrderBasicInfoMapper.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/mapper/OrderBasicInfoMapper.java @@ -247,6 +247,15 @@ public interface OrderBasicInfoMapper { */ SendMessageVO selectOrderInfoByOrderCode(@Param("orderCode") String orderCode); + /** + * 查询时间段内订单列表 + * TODO 慢sql需要优化 + * @param startTime + * @param endTime + * @param orderStatus + * @param payStatus + * @return + */ List selectOrderListByTimeRangeAndStatus(@Param("startTime") String startTime, @Param("endTime") String endTime, @Param("orderStatus") String orderStatus, diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/PersonalChargingRecordService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/PersonalChargingRecordService.java index c73a96778..944c6d106 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/PersonalChargingRecordService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/PersonalChargingRecordService.java @@ -8,7 +8,6 @@ import com.jsowell.pile.dto.QueryPersonPileDTO; import java.util.List; public interface PersonalChargingRecordService{ - int deleteByPrimaryKey(Integer id); int insert(PersonalChargingRecord record); diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/PileFirmwareInfoService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/PileFirmwareInfoService.java index 021aebe9c..4b757c819 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/PileFirmwareInfoService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/PileFirmwareInfoService.java @@ -1,6 +1,9 @@ package com.jsowell.pile.service; +import com.jsowell.common.core.page.PageResponse; import com.jsowell.pile.domain.PileFirmwareInfo; +import com.jsowell.pile.dto.PileFirmwareInfoDTO; +import org.springframework.web.multipart.MultipartFile; import java.util.List; @@ -58,4 +61,11 @@ public interface PileFirmwareInfoService { * @return 结果 */ public int deletePileFirmwareInfoById(Long id); + + /** + * 通过使用范围查询桩固件信息列表 + * @param dto + * @return + */ + PageResponse selectPileFirmwareListByUseRange(PileFirmwareInfoDTO dto); } 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 f55cfc8ed..95b08ddd7 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 @@ -35,6 +35,7 @@ import java.net.UnknownHostException; import java.util.Date; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; @Service public class PileRemoteService { @@ -289,19 +290,20 @@ public class PileRemoteService { pileBillingTemplate.setId(Long.valueOf(billingTemplateVO.getTemplateId())); pileBillingTemplate.setPublishTime(new Date()); pileBillingTemplateService.updatePileBillingTemplate(pileBillingTemplate); - - // 获取到站点下所有的桩, 下发计费模板, 电单车不支持 - if (StringUtils.equals(billingTemplateVO.getDeviceType(), Constants.ONE)) { - List pileList = pileBasicInfoService.selectPileListByStationIds(Lists.newArrayList(Long.valueOf(dto.getStationId()))); - if (CollectionUtils.isNotEmpty(pileList)) { - // for (PileDetailVO pileInfoVO : pileList) { - // // 下发计费模板 - // publishPileBillingTemplate(pileInfoVO.getPileSn(), billingTemplateVO); - // } + // 获取到站点下所有的桩 + List pileList = pileBasicInfoService.selectPileListByStationIds(Lists.newArrayList(Long.valueOf(dto.getStationId()))); + if (CollectionUtils.isNotEmpty(pileList)) { + // 删除缓存 + List collect = pileList.parallelStream() + .map(vo -> CacheConstants.BILLING_TEMPLATE_BY_PILE_SN + vo.getPileSn()) + .collect(Collectors.toList()); + redisCache.deleteObject(collect); + // 下发计费模板, 电单车不支持 + if (StringUtils.equals(billingTemplateVO.getDeviceType(), Constants.ONE)) { + // 下发指令 pileList.parallelStream().forEach(pileInfoVO -> publishPileBillingTemplate(pileInfoVO.getPileSn(), billingTemplateVO)); } } - // 修改计费模板状态 pileBillingTemplateService.changeStationTemplate(dto.getStationId(), dto.getTemplateId(), billingTemplateVO.getDeviceType()); return true; diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PersonalChargingRecordServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PersonalChargingRecordServiceImpl.java index 8a93adc98..9dafd5ca9 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PersonalChargingRecordServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PersonalChargingRecordServiceImpl.java @@ -132,7 +132,7 @@ public class PersonalChargingRecordServiceImpl implements PersonalChargingRecord chargingRecord.setTotalUsedElectricity(totalUsedElectricity); chargingRecord.setReason(data.getStopReasonMsg()); // 创建或更新 - personalChargingRecordMapper.insertOrUpdateSelective(chargingRecord); + this.insertOrUpdateSelective(chargingRecord); } /** @@ -176,7 +176,7 @@ public class PersonalChargingRecordServiceImpl implements PersonalChargingRecord // chargingRecord.setTotalUsedElectricity(totalUsedElectricity); // chargingRecord.setReason(data.getStopReasonMsg()); // 创建或更新 - personalChargingRecordMapper.insertOrUpdateSelective(chargingRecord); + this.insertOrUpdateSelective(chargingRecord); } @Override 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 9b04e29a9..888c5b0da 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 @@ -839,7 +839,16 @@ public class PileBillingTemplateServiceImpl implements PileBillingTemplateServic */ @Override public BillingTemplateVO selectBillingTemplateDetailByPileSn(String pileSn) { - return pileBillingTemplateMapper.selectBillingTemplateByPileSn(pileSn); + String redisKey = CacheConstants.BILLING_TEMPLATE_BY_PILE_SN + pileSn; + Object cacheObject = redisCache.getCacheObject(redisKey); + if (cacheObject != null) { + return JSON.parseObject(cacheObject.toString(), BillingTemplateVO.class); + } + BillingTemplateVO billingTemplateVO = pileBillingTemplateMapper.selectBillingTemplateByPileSn(pileSn); + if (billingTemplateVO != null) { + redisCache.setCacheObject(redisKey, JSON.toJSONString(billingTemplateVO), CacheConstants.cache_expire_time_1d); + } + return billingTemplateVO; } @Override diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileFirmwareInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileFirmwareInfoServiceImpl.java index 4db17b410..9fb339a7d 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileFirmwareInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileFirmwareInfoServiceImpl.java @@ -1,11 +1,19 @@ package com.jsowell.pile.service.impl; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.jsowell.common.constant.Constants; +import com.jsowell.common.core.page.PageResponse; import com.jsowell.common.util.DateUtils; +import com.jsowell.common.util.file.AliyunOssUploadUtils; import com.jsowell.pile.domain.PileFirmwareInfo; +import com.jsowell.pile.domain.PileReservationInfo; +import com.jsowell.pile.dto.PileFirmwareInfoDTO; import com.jsowell.pile.mapper.PileFirmwareInfoMapper; import com.jsowell.pile.service.PileFirmwareInfoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; import java.util.List; @@ -98,4 +106,32 @@ public class PileFirmwareInfoServiceImpl implements PileFirmwareInfoService { public int deletePileFirmwareInfoById(Long id) { return pileFirmwareInfoMapper.deletePileFirmwareInfoById(id); } + + /** + * 通过使用范围查询桩固件信息列表 + * @param dto + * @return + */ + @Override + public PageResponse selectPileFirmwareListByUseRange(PileFirmwareInfoDTO dto) { + int pageNo = dto.getPageNo() == null ? Constants.one : dto.getPageNo(); + int pageSize = dto.getPageSize() == null ? 10 : dto.getPageSize(); + + PileFirmwareInfo pileFirmwareInfo = new PileFirmwareInfo(); + pileFirmwareInfo.setUseRange(dto.getUseRange()); + + PageHelper.startPage(pageNo, pageSize); + List list = selectPileFirmwareInfoList(pileFirmwareInfo); + + PageInfo pageInfo = new PageInfo<>(list); + + PageResponse pageResponse = new PageResponse(); + pageResponse.setPageNum(pageInfo.getPageNum()); + pageResponse.setPageSize(pageInfo.getPageSize()); + pageResponse.setPages(pageInfo.getPages()); + pageResponse.setTotal(pageInfo.getTotal()); + pageResponse.setList(pageInfo.getList()); + + return pageResponse; + } } 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 f01dff181..5d3a9a608 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 @@ -151,9 +151,9 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { public byte[] supplySend(byte[] msg, String pileSn, Enum frameTypeCode, long timeout, TimeUnit unit) throws Exception { // 通过桩编号获取channel ChannelHandlerContext ctx = PileChannelEntity.getChannelByPileSn(pileSn); - String value = ((YKCFrameTypeCode) frameTypeCode).getValue(); // 帧类型名称 + String frameTypeName = ((YKCFrameTypeCode) frameTypeCode).getValue(); // 帧类型名称 if (Objects.isNull(ctx)) { - log.error("push命令[{}]失败, 桩号:{}无法获取到长连接, 请检查充电桩连接状态!", value, pileSn); + log.error("push命令[{}]失败, 桩号:{}无法获取到长连接, 请检查充电桩连接状态!", frameTypeName, pileSn); throw new NullPointerException("channel"); } if(msg == null) { @@ -206,12 +206,12 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { // 检查操作的状态 if (channelFutureListener.isSuccess()) { log.info("【push结果===>成功】, pileSn:{}, remoteAddress:{}, channelId:{}, 帧类型:{}, 报文:{}", - pileSn, ctx.channel().remoteAddress(), ctx.channel().id(), value, wholeMsg); + pileSn, ctx.channel().remoteAddress(), ctx.channel().id(), frameTypeName, wholeMsg); } else { // 如果发生错误,则访问描述原因的Throwable Throwable cause = channelFutureListener.cause(); log.info("【push结果===>失败】, pileSn:{}, remoteAddress:{}, channelId:{}, 帧类型:{}, 报文:{}", - pileSn, ctx.channel().remoteAddress(), ctx.channel().id(), value, wholeMsg); + pileSn, ctx.channel().remoteAddress(), ctx.channel().id(), frameTypeName, wholeMsg); log.error("push发送命令失败, pileSn:{}", pileSn, cause); } }); @@ -221,9 +221,9 @@ public class YKCPushCommandServiceImpl implements YKCPushCommandService { if(rpcResponse == null) { if(syncPromise.isTimeout()) { // throw new TimeoutException("等待响应结果超时"); - log.error("发送[{}]指令后, 等待响应结果超时", value); + log.error("pileSn:{}, 发送[{}]指令后, 等待响应结果超时", pileSn, frameTypeName); } else{ - log.error("发送[{}]指令后, 发生其他异常", value); + log.error("pileSn:{}, 发送[{}]指令后, 发生其他异常", pileSn, frameTypeName); } } // 移除容器 diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/vo/uniapp/customer/PersonPileConnectorSumInfoVO.java b/jsowell-pile/src/main/java/com/jsowell/pile/vo/uniapp/customer/PersonPileConnectorSumInfoVO.java index 99458c970..bd39b7c52 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/vo/uniapp/customer/PersonPileConnectorSumInfoVO.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/vo/uniapp/customer/PersonPileConnectorSumInfoVO.java @@ -41,4 +41,9 @@ public class PersonPileConnectorSumInfoVO { * 累计充电时长 */ private String sumChargingTime; + + /** + * 来源(4G/BT) sourceType + */ + private String sourceType; } diff --git a/jsowell-pile/src/main/resources/mapper/pile/PersonalChargingRecordMapper.xml b/jsowell-pile/src/main/resources/mapper/pile/PersonalChargingRecordMapper.xml index 47cac591f..7931d6c52 100644 --- a/jsowell-pile/src/main/resources/mapper/pile/PersonalChargingRecordMapper.xml +++ b/jsowell-pile/src/main/resources/mapper/pile/PersonalChargingRecordMapper.xml @@ -24,12 +24,16 @@ + + + + @@ -41,9 +45,9 @@ id, transaction_code, `status`, member_id, station_id, merchant_id, pile_sn, connector_code, pile_connector_code, logic_card, vin_code, start_mode, plate_number, charge_start_time, charge_end_time, start_type, reservation_start_time, reservation_end_time, start_soc, - end_soc, total_used_electricity, sharp_used_electricity, peak_used_electricity, flat_used_electricity, - valley_used_electricity, reason, create_by, create_time, update_by, update_time, - del_flag + end_soc, ammeter_total_start, ammeter_total_end, total_used_electricity, sharp_used_electricity, + peak_used_electricity, flat_used_electricity, valley_used_electricity, reason, trade_date, + source_type, create_by, create_time, update_by, update_time, del_flag and name like concat('%', #{name}, '%') + and use_range = #{useRange,jdbcType=VARCHAR} @@ -41,6 +44,8 @@ description, file_path, apply_type, + use_range, + download_url, create_time, create_by, update_time, @@ -53,6 +58,8 @@ #{description}, #{filePath}, #{applyType}, + #{useRange}, + #{downloadUrl}, #{createTime}, #{createBy}, #{updateTime}, @@ -68,6 +75,8 @@ description = #{description}, file_path = #{filePath}, apply_type = #{applyType}, + use_range = #{useRange}, + download_url = #{downloadUrl}, create_time = #{createTime}, create_by = #{createBy}, update_time = #{updateTime}, diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/domain/ChargeAlgorithmData.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/domain/ChargeAlgorithmData.java new file mode 100644 index 000000000..6ed648eae --- /dev/null +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/domain/ChargeAlgorithmData.java @@ -0,0 +1,234 @@ +package com.jsowell.thirdparty.platform.domain; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 充电订单算法Data + * + * @author Lemon + * @Date 2024/11/19 14:02:40 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ChargeAlgorithmData { + /** + * 订单号 + */ + private String orderCode; + + /** + * 初始SOC + */ + private Integer initSoc; + + /** + * 当前soc + */ + private Integer currentSoc; + + /** + * 告警编码 + */ + private String alarmCode; + + /** + * 累计服务费 + */ + private String currentServiceFee; + + /** + * 总费用 + */ + private String currentTotalFee; + + /** + * 累计充电量 + */ + private String totalCharge; + + /** + * 充电时长 + */ + private Integer totalChargeTime; + + /** + * 剩余充电时间 + */ + private Integer remainChargeTime; + + /** + * 最高允许电流 + */ + private String maxAllowElectricity; + + /** + * 单体最高允许电压 + */ + private String singleMaxAllowVoltage; + + /** + * 直流充电电压 + */ + private String dcv; + + /** + * 直流充电电流 + */ + private String dca; + + /** + * BMS需求电压 + */ + private String bmsDemandVoltage; + + /** + * BMS需求电流 + */ + private String bmsDemandElectricity; + + /** + * BMS充电模式 + */ + private Integer bmsChargeMode; + + /** + * 充电前电表读数 + */ + private String readBeforeCharge; + + /** + * 当前电表读数 + */ + private String readCurrentCharge; + + /** + * 开始充电时间 + */ + private String beginTime; + + /** + * 最高允许温度 + */ + private String maxAllowTemp; + + /** + * 充电功率 + */ + private String chargePower; + + /** + * 电池额定容量 + */ + private String ratedCapacity; + + /** + * 电池标称总能量 + */ + private String nominalEnergy; + + /** + * 电池额定总电压 + */ + private String ratedVoltage; + + /** + * 单体最高电压 + */ + private String singleMaxVoltage; + + /** + * 单体最低电压 + */ + private String singleMinVoltage; + + /** + * 单体最高温度 + */ + private String singleMaxTemp; + + /** + * 单体最低温度 + */ + private String singleMinTemp; + + /** + * 出风口温度 + */ + private String ventTemp; + + /** + * 环境温度 + */ + private String environmentTemp; + + /** + * 充电枪温度 + */ + private String gunTemp; + + /** + * 舱门状态 + */ + private Integer doorStatus; + + /** + * BMS版本 + */ + private String bmsVersion; + + /** + * 车辆测量充电电压 + */ + private String measuringChargeVoltage; + + /** + * 车辆测量充电电流 + */ + private String measuringChargeElectricity; + + /** + * 最高单体电压组号 + */ + private Integer maxSingleVoltageGroupNum; + + /** + * 最高单体电压编号 + */ + private Integer maxSingleVoltageNum; + + /** + * 最高温度点编号 + */ + private Integer maxTempPointNum; + + /** + * 最低温度点编号 + */ + private Integer minTempPointNum; + + /** + * 电池类型 + */ + private String batteryType; + + /** + * 电池绝缘状态 + */ + private Integer batteryInsulation; + + /** + * 最高允许充电总电压 + */ + private String maxAllowTotalVoltage; + + /** + * 充电前总电压 + */ + private String beforeChargeTotalVoltage; + +} diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/util/HttpRequestUtil.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/util/HttpRequestUtil.java index 72e684331..8c03f2f5e 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/util/HttpRequestUtil.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/util/HttpRequestUtil.java @@ -129,12 +129,10 @@ public class HttpRequestUtil { if(StringUtils.isBlank(label)) { label = operatorId + "(" + url + ")"; } - log.info(label + "发送请求 data:{}", data); //加密 byte[] encryptText = Cryptos.aesEncrypt(data.getBytes(), dataSecret.getBytes(), dataSecretIV.getBytes()); String encryptData = Encodes.encodeBase64(encryptText); - log.info(label + "发送请求 加密数据:" + encryptData); Map params = Maps.newLinkedHashMap(); params.put("OperatorID", operatorId); @@ -151,19 +149,18 @@ public class HttpRequestUtil { params.put("Sig", sign); String postData = JSON.toJSONString(params); - log.info(label + "发送请求 最终提交数据:{}, 加密数据:{}", params, postData); - // System.out.println("最终提交数据:" + postData); + // log.info(label + "发送请求 最终提交数据:{}, 加密数据:{}", params, postData); + log.info("[{}]准备发送请求, 原始data:{}, 请求param:{}", label, data, postData); - String hutoolRequest = HttpRequest.post(url).header("Authorization", "Bearer " + token).body(postData).execute().body(); + String response = HttpRequest.post(url).header("Authorization", "Bearer " + token).body(postData).execute().body(); - log.info(label + "发送请求 接收到返回数据:{}", hutoolRequest); + // log.info(label + "发送请求 接收到返回数据:{}", response); + log.info("[{}]发送请求成功, params:{}, response:{}", label, postData, response); - if (StringUtils.isBlank(hutoolRequest)) { + if (StringUtils.isBlank(response)) { return "返回数据为空"; } - Map map = (Map) JSON.parse(hutoolRequest); - - // log.info("联联平台发送请求 返回数据map:{}", JSON.toJSONString(map)); + Map map = (Map) JSON.parse(response); int ret = Integer.parseInt(String.valueOf(map.get("Ret"))); String resultMsg = (String) map.get("Msg"); @@ -182,7 +179,7 @@ public class HttpRequestUtil { } catch (Exception e) { e.printStackTrace(); } - log.info(label + "发送请求 返回数据map:{}, 解密数据:{}", JSON.toJSONString(map), plainData); + log.info("[{}]解密返参, 返回数据map:{}, 解密数据:{}", label, JSON.toJSONString(map), plainData); return resultMsg; } diff --git a/jsowell-ui/src/views/pile/firmware/index.vue b/jsowell-ui/src/views/pile/firmware/index.vue index 554291632..60ff01784 100644 --- a/jsowell-ui/src/views/pile/firmware/index.vue +++ b/jsowell-ui/src/views/pile/firmware/index.vue @@ -1,307 +1,417 @@