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 47e51bbc7..3dc02b0f6 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 @@ -175,6 +175,11 @@ public class CacheConstants { */ public static final String TRANSACTION_RECORD_BY_TRANSACTION_CODE = "transaction_record_by_transaction_code:"; + /** + * 0x23缓存key + */ + public static final String BMS_CHARGE_INFO_BY_TRANSACTION_CODE = "bms_charge_info_by_transaction_code:"; + /** * 充电桩状态前缀 */ diff --git a/jsowell-common/src/main/java/com/jsowell/common/core/domain/ykc/BMSDemandAndChargerOutputData.java b/jsowell-common/src/main/java/com/jsowell/common/core/domain/ykc/BMSDemandAndChargerOutputData.java new file mode 100644 index 000000000..e4219a70d --- /dev/null +++ b/jsowell-common/src/main/java/com/jsowell/common/core/domain/ykc/BMSDemandAndChargerOutputData.java @@ -0,0 +1,37 @@ +package com.jsowell.common.core.domain.ykc; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 0x23信息数据 + * + * @author Lemon + * @Date 2024/12/9 14:33:35 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class BMSDemandAndChargerOutputData { + + private String transactionCode; // 交易流水号 + private String pileSn; // 桩编号 + private String connectorCode; // 枪口号 + private String bmsVoltageDemand; // BMS 电压需求 0.1 V/位, 0 V 偏移量 + private String bmsCurrentDemand; // BMS 电流需求 0.1 A/位, -400 A 偏移量 + private String bmsChargingModel; // BMS 充电模式 0x01:恒压充电; 0x02:恒流充电 + private String bmsChargingVoltage; // BMS 充电电压测量值 0.1 V/位, 0 V 偏移量 + private String bmsChargingCurrent; // BMS 充电电流测量值 0.1 A/位, -400 A 偏移量 + private String bmsMaxVoltageAndGroup; // BMS 最高单体动力蓄电池电压及组号 1-12 位:最高单体动力蓄电池电压, 数据分辨率: 0.01 V/位, 0 V 偏移量;数据范围: 0~24 V; 13-16 位: 最高单体动力蓄电池电 压所在组号,数据分辨率: 1/位, 0 偏移量;数据范围: 0~15 + private String soc; // BMS 当前荷电状态 SOC( %) 1%/位, 0%偏移量; 数据范围: 0~100% + private String bmsTheRestChargingTime; // BMS 估算剩余充电时间 1 min/位, 0 min 偏移量; 数据范围: 0~600 min + private String pileVoltageOutput; // 电桩电压输出值 0.1 V/位, 0 V 偏移量 + private String pileCurrentOutput; // 电桩电流输出值 0.1 A/位, -400 A 偏移量 + private String chargingTime; // 累计充电时间 1 min/位, 0 min 偏移量; 数据范围: 0~600 min + + private String dateTime; + private String outputPower; +} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/BMSDemandAndChargerOutputHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/BMSDemandAndChargerOutputHandler.java index d9dd0265d..04d6d5816 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/BMSDemandAndChargerOutputHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/BMSDemandAndChargerOutputHandler.java @@ -2,11 +2,15 @@ package com.jsowell.netty.handler.yunkuaichong; import com.jsowell.common.core.domain.ykc.YKCDataProtocol; import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; +import com.jsowell.common.core.redis.RedisCache; import com.jsowell.common.util.BytesUtil; import com.jsowell.common.util.YKCUtils; import com.jsowell.netty.factory.YKCOperateFactory; +import com.jsowell.common.core.domain.ykc.BMSDemandAndChargerOutputData; +import com.jsowell.pile.service.PileBasicInfoService; import io.netty.channel.ChannelHandlerContext; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** @@ -19,6 +23,13 @@ import org.springframework.stereotype.Component; @Slf4j @Component public class BMSDemandAndChargerOutputHandler extends AbstractYkcHandler { + + @Autowired + private RedisCache redisCache; + + @Autowired + private PileBasicInfoService pileBasicInfoService; + private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.CHARGING_PROCESS_BMS_DEMAND_AND_CHARGER_OUTPUT_CODE.getBytes()); @Override @@ -26,6 +37,94 @@ public class BMSDemandAndChargerOutputHandler extends AbstractYkcHandler { YKCOperateFactory.register(type, this); } + public static void main(String[] args) { + + String msg = "8823000000259602241208235501743088230000002596023c10ed1202d70d40037201175500e10de3120000"; + // 获取消息体 + byte[] msgBody = BytesUtil.str2Bcd(msg); + + int startIndex = 0; + int length = 16; + + // 交易流水号 + byte[] serialNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String transactionCode = BytesUtil.bcd2Str(serialNumByteArr); + + // 桩编码 + startIndex += length; + length = 7; + byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileSn = BytesUtil.bcd2Str(pileSnByteArr); + + // 枪号 + startIndex += length; + length = 1; + byte[] pileConnectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String connectorCode = BytesUtil.bcd2Str(pileConnectorNumByteArr); + + // BMS 电压需求 0.1 V/位, 0 V 偏移量 + startIndex += length; + length = 2; + byte[] bmsVoltageDemandByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsVoltageDemand = String.valueOf(BytesUtil.bytesToIntLittle(bmsVoltageDemandByteArr) * 0.1); + + // BMS 电流需求 0.1 A/位, -400 A 偏移量 + startIndex += length; + byte[] bmsCurrentDemandByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsCurrentDemand = String.valueOf(BytesUtil.bytesToIntLittle(bmsCurrentDemandByteArr) * 0.1 - 400); + + // BMS 充电模式 0x01:恒压充电; 0x02:恒流充电 + startIndex += length; + length = 1; + byte[] bmsChargingModelByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsChargingModel = BytesUtil.bcd2Str(bmsChargingModelByteArr); + + // BMS 充电电压测量值 0.1 V/位, 0 V 偏移量 + startIndex += length; + length = 2; + byte[] bmsChargingVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsChargingVoltage = String.valueOf(BytesUtil.bytesToIntLittle(bmsChargingVoltageByteArr) * 0.1); + + // BMS 充电电流测量值 0.1 A/位, -400 A 偏移量 + startIndex += length; + byte[] bmsChargingCurrentByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsChargingCurrent = String.valueOf(BytesUtil.bytesToIntLittle(bmsChargingCurrentByteArr) * 0.1 - 400); + + // BMS 最高单体动力蓄电池电压及组号 1-12 位:最高单体动力蓄电池电压, 数据分辨率: 0.01 V/位, 0 V 偏移量;数据范围: 0~24 V; 13-16 位: 最高单体动力蓄电池电 压所在组号,数据分辨率: 1/位, 0 偏移量;数据范围: 0~15 + startIndex += length; + byte[] bmsMaxVoltageAndGroupNum = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsMaxVoltageAndGroup = String.valueOf(BytesUtil.bytesToIntLittle(bmsMaxVoltageAndGroupNum) * 0.01); + + // BMS 当前荷电状态 SOC( %) 1%/位, 0%偏移量; 数据范围: 0~100% + startIndex += length; + length = 1; + byte[] socByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String soc = BytesUtil.bcd2Str(socByteArr); + + // BMS 估算剩余充电时间 1 min/位, 0 min 偏移量; 数据范围: 0~600 min + startIndex += length; + length = 2; + byte[] bmsTheRestChargingTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsTheRestChargingTime = String.valueOf(BytesUtil.bytesToIntLittle(bmsTheRestChargingTimeByteArr)); + + // 电桩电压输出值 0.1 V/位, 0 V 偏移量 + startIndex += length; + byte[] pileVoltageOutputByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileVoltageOutput = String.valueOf(BytesUtil.bytesToIntLittle(pileVoltageOutputByteArr) * 0.1); + + // 电桩电流输出值 0.1 A/位, -400 A 偏移量 + startIndex += length; + byte[] pileCurrentOutputByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileCurrentOutput = String.valueOf(BytesUtil.bytesToIntLittle(pileCurrentOutputByteArr) * 0.1 - 400); + + // 累计充电时间 1 min/位, 0 min 偏移量; 数据范围: 0~600 min + startIndex += length; + byte[] chargingTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String chargingTime = String.valueOf(BytesUtil.bytesToIntLittle(chargingTimeByteArr)); + + + } + @Override public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { // log.info("[===充电过程 BMS 需求与充电机输出===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); @@ -37,6 +136,7 @@ public class BMSDemandAndChargerOutputHandler extends AbstractYkcHandler { // 交易流水号 byte[] serialNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String transactionCode = BytesUtil.bcd2Str(serialNumByteArr); // 桩编码 startIndex += length; @@ -51,56 +151,89 @@ public class BMSDemandAndChargerOutputHandler extends AbstractYkcHandler { startIndex += length; length = 1; byte[] pileConnectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String connectorCode = BytesUtil.bcd2Str(pileConnectorNumByteArr); // BMS 电压需求 0.1 V/位, 0 V 偏移量 startIndex += length; length = 2; byte[] bmsVoltageDemandByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsVoltageDemand = String.valueOf(BytesUtil.bytesToIntLittle(bmsVoltageDemandByteArr) * 0.1); // BMS 电流需求 0.1 A/位, -400 A 偏移量 startIndex += length; byte[] bmsCurrentDemandByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsCurrentDemand = String.valueOf(BytesUtil.bytesToIntLittle(bmsCurrentDemandByteArr) * 0.1 - 400); // BMS 充电模式 0x01:恒压充电; 0x02:恒流充电 startIndex += length; length = 1; byte[] bmsChargingModelByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsChargingModel = BytesUtil.bcd2Str(bmsChargingModelByteArr); // BMS 充电电压测量值 0.1 V/位, 0 V 偏移量 startIndex += length; length = 2; byte[] bmsChargingVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsChargingVoltage = String.valueOf(BytesUtil.bytesToIntLittle(bmsChargingVoltageByteArr) * 0.1); // BMS 充电电流测量值 0.1 A/位, -400 A 偏移量 startIndex += length; byte[] bmsChargingCurrentByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsChargingCurrent = String.valueOf(BytesUtil.bytesToIntLittle(bmsChargingCurrentByteArr) * 0.1 - 400); // BMS 最高单体动力蓄电池电压及组号 1-12 位:最高单体动力蓄电池电压, 数据分辨率: 0.01 V/位, 0 V 偏移量;数据范围: 0~24 V; 13-16 位: 最高单体动力蓄电池电 压所在组号,数据分辨率: 1/位, 0 偏移量;数据范围: 0~15 startIndex += length; byte[] bmsMaxVoltageAndGroupNum = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsMaxVoltageAndGroup = String.valueOf(BytesUtil.bytesToIntLittle(bmsMaxVoltageAndGroupNum) * 0.01); // BMS 当前荷电状态 SOC( %) 1%/位, 0%偏移量; 数据范围: 0~100% startIndex += length; length = 1; byte[] socByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String soc = BytesUtil.bcd2Str(socByteArr); // BMS 估算剩余充电时间 1 min/位, 0 min 偏移量; 数据范围: 0~600 min startIndex += length; length = 2; byte[] bmsTheRestChargingTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsTheRestChargingTime = String.valueOf(BytesUtil.bytesToIntLittle(bmsTheRestChargingTimeByteArr)); // 电桩电压输出值 0.1 V/位, 0 V 偏移量 startIndex += length; byte[] pileVoltageOutputByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileVoltageOutput = String.valueOf(BytesUtil.bytesToIntLittle(pileVoltageOutputByteArr) * 0.1); // 电桩电流输出值 0.1 A/位, -400 A 偏移量 startIndex += length; byte[] pileCurrentOutputByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileCurrentOutput = String.valueOf(BytesUtil.bytesToIntLittle(pileCurrentOutputByteArr) * 0.1 - 400); // 累计充电时间 1 min/位, 0 min 偏移量; 数据范围: 0~600 min startIndex += length; byte[] chargingTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String chargingTime = String.valueOf(BytesUtil.bytesToIntLittle(chargingTimeByteArr)); + // 存入缓存(过期时间 3 天) + BMSDemandAndChargerOutputData bmsDemandAndChargerOutputData = BMSDemandAndChargerOutputData.builder() + .transactionCode(transactionCode) + .pileSn(pileSn) + .connectorCode(connectorCode) + .bmsVoltageDemand(bmsVoltageDemand) + .bmsCurrentDemand(bmsCurrentDemand) + .bmsChargingModel(bmsChargingModel) + .bmsChargingVoltage(bmsChargingVoltage) + .bmsChargingCurrent(bmsChargingCurrent) + .bmsMaxVoltageAndGroup(bmsMaxVoltageAndGroup) + .soc(soc) + .bmsTheRestChargingTime(bmsTheRestChargingTime) + .pileVoltageOutput(pileVoltageOutput) + .pileCurrentOutput(pileCurrentOutput) + .chargingTime(chargingTime) + + .build(); + + // 调用方法存入缓存 + pileBasicInfoService.saveBMSDemandAndChargerOutputInfo2Redis(bmsDemandAndChargerOutputData); return null; } diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/BMSInformationHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/BMSInformationHandler.java index 44e0bb607..8c0f50aac 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/BMSInformationHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/BMSInformationHandler.java @@ -26,6 +26,113 @@ public class BMSInformationHandler extends AbstractYkcHandler { YKCOperateFactory.register(type, this); } + public static void main(String[] args) { + String msg = "8823000000104502241209160539911188230000001045027c45043e080010"; + + byte[] msgBody = BytesUtil.str2Bcd(msg); + + int startIndex = 0; + int length = 16; + + // 交易流水号 + byte[] serialNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String transactionCode = BytesUtil.bcd2Str(serialNumByteArr); + + // 桩编码 + startIndex += length; + length = 7; + byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String pileSn = BytesUtil.bcd2Str(pileSnByteArr); + + // 枪号 + startIndex += length; + length = 1; + byte[] pileConnectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String connectorCode = BytesUtil.bcd2Str(pileConnectorNumByteArr); + + // BMS 最高单体动力蓄电池电压所在编号 1/位, 1 偏移量; 数据范围: 1~256 + startIndex += length; + byte[] BMSMaxVoltageNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsMaxVoltageNum = String.valueOf(BytesUtil.bytesToIntLittle(BMSMaxVoltageNumByteArr)); + + // BMS 最高动力蓄电池温度 1ºC/位, -50 ºC 偏移量;数据范 围: -50 ºC ~+200 ºC + startIndex += length; + byte[] BMSMaxBatteryTemperatureByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsMaxBatteryTemperature = String.valueOf(BytesUtil.bytesToIntLittle(BMSMaxBatteryTemperatureByteArr) - 50); + + // 最高温度检测点编号 1/位, 1 偏移量; 数据范围: 1~128 + startIndex += length; + byte[] maxTemperatureDetectionNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String maxTemperatureDetectionNum = String.valueOf(BytesUtil.bytesToIntLittle(maxTemperatureDetectionNumByteArr) + 1); + + // 最低动力蓄电池温度 1ºC/位, -50 ºC 偏移量;数据范 围: -50 ºC ~+200 ºC + startIndex += length; + byte[] minBatteryTemperatureByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String minBatteryTemperature = String.valueOf(BytesUtil.bytesToIntLittle(minBatteryTemperatureByteArr) - 50); + + // 最低动力蓄电池温度检测点编号 1/位, 1 偏移量; 数据范围: 1~128 + startIndex += length; + byte[] minTemperatureDetectionNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String minTemperatureDetectionNum = String.valueOf(BytesUtil.bytesToIntLittle(minTemperatureDetectionNumByteArr) + 1); + + /** + * BMS 单体动力蓄电池电压过高 /过低 (<00> :=正常 ; <01> :=过高 ; <10>: =过低) + */ + startIndex += length; + length = 2; + byte[] singleBMSVoltageStatusByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String singleBMSVoltageStatus = BytesUtil.bcd2Str(singleBMSVoltageStatusByteArr); + + /** + * BMS 整车动力蓄电池荷电状态 SOC 过高/过低 (<00> :=正常 ; <01> :=过高 ; <10>: =过低) + */ + startIndex += length; + byte[] carBMSSocStatusByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String carBMSSocStatus = BytesUtil.bcd2Str(carBMSSocStatusByteArr); + + /** + * BMS 动力蓄电池充电过电流 (<00> :=正常 ; <01> :=过流 ; <10>: =不可信状态) + */ + startIndex += length; + byte[] BMSBatteryChargeCurrentStatusByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsBatteryChargeCurrentStatus = BytesUtil.bcd2Str(BMSBatteryChargeCurrentStatusByteArr); + + /** + * BMS 动力蓄电池温度过高 (<00> :=正常 ; <01> :=过流 ; <10>: =不可信状态) + */ + startIndex += length; + byte[] BMSBatteryTemperatureByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsBatteryTemperature = BytesUtil.bcd2Str(BMSBatteryTemperatureByteArr); + + /** + * BMS 动力蓄电池绝缘状态 (<00> :=正常 ; <01> :=过流 ; <10>: =不可信状态) + */ + startIndex += length; + byte[] BMSBatteryInsulationStatusByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsBatteryInsulationStatus = BytesUtil.bcd2Str(BMSBatteryInsulationStatusByteArr); + + + /** + * BMS 动力蓄电池组输出连接器连接状态 (<00> :=正常 ; <01> :=过流 ; <10>: =不可信状态) + */ + startIndex += length; + byte[] BMSBatteryOutputStatusByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsBatteryOutputStatus = BytesUtil.bcd2Str(BMSBatteryOutputStatusByteArr); + + /** + * 充电禁止 (<00>: =禁止; <01>: =允许) + */ + startIndex += length; + byte[] chargeProhibitByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String chargeProhibit = BytesUtil.bcd2Str(chargeProhibitByteArr); + + /** + * 预留位 + */ + startIndex += length; + byte[] noMeanPositionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + } + @Override public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, ChannelHandlerContext channel) { // log.info("[===充电过程 BMS 信息===] param:{}, channel:{}", JSON.toJSONString(ykcDataProtocol), channel.toString()); @@ -37,6 +144,7 @@ public class BMSInformationHandler extends AbstractYkcHandler { // 交易流水号 byte[] serialNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String transactionCode = BytesUtil.bcd2Str(serialNumByteArr); // 桩编码 startIndex += length; @@ -51,46 +159,88 @@ public class BMSInformationHandler extends AbstractYkcHandler { startIndex += length; length = 1; byte[] pileConnectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String connectorCode = BytesUtil.bcd2Str(pileConnectorNumByteArr); // BMS 最高单体动力蓄电池电压所在编号 1/位, 1 偏移量; 数据范围: 1~256 startIndex += length; byte[] BMSMaxVoltageNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsMaxVoltageNum = String.valueOf(BytesUtil.bytesToIntLittle(BMSMaxVoltageNumByteArr)); // BMS 最高动力蓄电池温度 1ºC/位, -50 ºC 偏移量;数据范 围: -50 ºC ~+200 ºC startIndex += length; byte[] BMSMaxBatteryTemperatureByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsMaxBatteryTemperature = String.valueOf(BytesUtil.bytesToIntLittle(BMSMaxBatteryTemperatureByteArr) - 50); // 最高温度检测点编号 1/位, 1 偏移量; 数据范围: 1~128 startIndex += length; byte[] maxTemperatureDetectionNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String maxTemperatureDetectionNum = String.valueOf(BytesUtil.bytesToIntLittle(maxTemperatureDetectionNumByteArr) + 1); // 最低动力蓄电池温度 1ºC/位, -50 ºC 偏移量;数据范 围: -50 ºC ~+200 ºC startIndex += length; - byte[] minBatteryTemperature = BytesUtil.copyBytes(msgBody, startIndex, length); + byte[] minBatteryTemperatureByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String minBatteryTemperature = String.valueOf(BytesUtil.bytesToIntLittle(minBatteryTemperatureByteArr) - 50); // 最低动力蓄电池温度检测点编号 1/位, 1 偏移量; 数据范围: 1~128 startIndex += length; byte[] minTemperatureDetectionNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String minTemperatureDetectionNum = String.valueOf(BytesUtil.bytesToIntLittle(minTemperatureDetectionNumByteArr) + 1); /** - * 9-12 - * 9: BMS 单体动力蓄电池电压过高 /过低 (<00> :=正常 ; <01> :=过高 ; <10>: =过低) - * 10: BMS 整车动力蓄电池荷电状态 SOC 过高/过低 (<00> :=正常 ; <01> :=过高 ; <10>: =过低) - * 11: BMS 动力蓄电池充电过电流 (<00> :=正常 ; <01> :=过流 ; <10>: =不可信状态) - * 12: BMS 动力蓄电池温度过高 (<00> :=正常 ; <01> :=过流 ; <10>: =不可信状态) + * BMS 单体动力蓄电池电压过高 /过低 (<00> :=正常 ; <01> :=过高 ; <10>: =过低) */ startIndex += length; - byte[] numNineToTwelve = BytesUtil.copyBytes(msgBody, startIndex, length); + length = 2; + byte[] singleBMSVoltageStatusByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String singleBMSVoltageStatus = BytesUtil.bcd2Str(singleBMSVoltageStatusByteArr); /** - * 13-16 - * 13: BMS 动力蓄电池绝缘状态 (<00> :=正常 ; <01> :=过流 ; <10>: =不可信状态) - * 14: BMS 动力蓄电池组输出连接器连接状态 (<00> :=正常 ; <01> :=过流 ; <10>: =不可信状态) - * 15: 充电禁止 (<00>: =禁止; <01>: =允许) - * 16: 预留位 00 + * BMS 整车动力蓄电池荷电状态 SOC 过高/过低 (<00> :=正常 ; <01> :=过高 ; <10>: =过低) */ startIndex += length; - byte[] numThirteenToSixteen = BytesUtil.copyBytes(msgBody, startIndex, length); + byte[] carBMSSocStatusByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String carBMSSocStatus = BytesUtil.bcd2Str(carBMSSocStatusByteArr); + + /** + * BMS 动力蓄电池充电过电流 (<00> :=正常 ; <01> :=过流 ; <10>: =不可信状态) + */ + startIndex += length; + byte[] BMSBatteryChargeCurrentStatusByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsBatteryChargeCurrentStatus = BytesUtil.bcd2Str(BMSBatteryChargeCurrentStatusByteArr); + + /** + * BMS 动力蓄电池温度过高 (<00> :=正常 ; <01> :=过流 ; <10>: =不可信状态) + */ + startIndex += length; + byte[] BMSBatteryTemperatureByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsBatteryTemperature = BytesUtil.bcd2Str(BMSBatteryTemperatureByteArr); + + /** + * BMS 动力蓄电池绝缘状态 (<00> :=正常 ; <01> :=过流 ; <10>: =不可信状态) + */ + startIndex += length; + byte[] BMSBatteryInsulationStatusByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsBatteryInsulationStatus = BytesUtil.bcd2Str(BMSBatteryInsulationStatusByteArr); + + /** + * BMS 动力蓄电池组输出连接器连接状态 (<00> :=正常 ; <01> :=过流 ; <10>: =不可信状态) + */ + startIndex += length; + byte[] BMSBatteryOutputStatusByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsBatteryOutputStatus = BytesUtil.bcd2Str(BMSBatteryOutputStatusByteArr); + + /** + * 充电禁止 (<00>: =禁止; <01>: =允许) + */ + startIndex += length; + byte[] chargeProhibitByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String chargeProhibit = BytesUtil.bcd2Str(chargeProhibitByteArr); + + /** + * 预留位 + */ + startIndex += length; + byte[] noMeanPositionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); return null; diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/ChargingHandshakeHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/ChargingHandshakeHandler.java index 8f7ea544c..056b411e4 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/ChargingHandshakeHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/ChargingHandshakeHandler.java @@ -2,11 +2,13 @@ package com.jsowell.netty.handler.yunkuaichong; import com.jsowell.common.core.domain.ykc.YKCDataProtocol; import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; +import com.jsowell.common.core.redis.RedisCache; import com.jsowell.common.util.BytesUtil; import com.jsowell.common.util.YKCUtils; import com.jsowell.netty.factory.YKCOperateFactory; import io.netty.channel.ChannelHandlerContext; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** @@ -19,6 +21,9 @@ import org.springframework.stereotype.Component; @Slf4j @Component public class ChargingHandshakeHandler extends AbstractYkcHandler { + @Autowired + private RedisCache redisCache; + private final String type = YKCUtils.frameType2Str(YKCFrameTypeCode.CHARGING_HANDSHAKE_CODE.getBytes()); @Override @@ -37,6 +42,7 @@ public class ChargingHandshakeHandler extends AbstractYkcHandler { // 交易流水号 byte[] serialNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String transactionCode = BytesUtil.bcd2Str(serialNumByteArr); // 桩编码 startIndex += length; @@ -57,48 +63,57 @@ public class ChargingHandshakeHandler extends AbstractYkcHandler { startIndex += length; length = 3; byte[] BMSCommunicationProtocolVersionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - + String bmsCommunicationVersion = "V1.1"; // BMS 电池类型 01H:铅酸电池;02H:氢 电池;03H:磷酸铁锂电池;04H:锰 酸锂电池;05H:钴酸锂电池 ;06H: 三元材料电池;07H:聚合物锂离子 电池;08H:钛酸锂电池;FFH:其他 startIndex += length; length = 1; byte[] BMSBatteryTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsBatteryType = BytesUtil.bcd2Str(BMSBatteryTypeByteArr); // 03 // BMS 整车动力蓄电池系统额定容量 0.1 Ah /位, 0 Ah 偏移量 startIndex += length; length = 2; byte[] BMSBatteryCapacityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsBatteryCapacity = String.valueOf(BytesUtil.bytesToIntLittle(BMSBatteryCapacityByteArr) * 0.1); // 171.0 // BMS 整车动力蓄电池系统额定总电压 0.1V/位, 0V 偏移量 startIndex += length; byte[] BMSBatteryVoltageByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsBatteryVoltage = String.valueOf(BytesUtil.bytesToIntLittle(BMSBatteryVoltageByteArr) * 0.1); // 347.8 // BMS 电池生产厂商名称 startIndex += length; length = 4; byte[] BMSBatteryFactoryByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsBatteryFactory = BytesUtil.ascii2Str(BMSBatteryFactoryByteArr); // CATL // BMS 电池组序号 startIndex += length; byte[] BMSBatteryNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsBatteryNum = BytesUtil.bin2HexStr(BMSBatteryNumByteArr); // BMS 电池组生产日期年 1985 年偏移量, 数据范围: 1985~ 2235 年 startIndex += length; length = 1; byte[] BMSProductionDateYearByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsProductionDateYear = BytesUtil.bin2HexStr(BMSProductionDateYearByteArr); // BMS 电池组生产日期月 0 月偏移量, 数据范围: 1~12 月 startIndex += length; byte[] BMSProductionDateMonthByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsProductionDateMonth = BytesUtil.bin2HexStr(BMSProductionDateMonthByteArr); // BMS 电池组生产日期日 0 日偏移量, 数据范围: 1~31 日 startIndex += length; byte[] BMSProductionDateDayByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsProductionDateDay = BytesUtil.bin2HexStr(BMSProductionDateDayByteArr); // BMS 电池组充电次数 1 次/位, 0 次偏移量, 以 BMS 统 计为准 startIndex += length; length = 3; byte[] BMSChargingTimesByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String bmsChargingTimes = BytesUtil.bin2HexStr(BMSChargingTimesByteArr); // BMS 电池组产权标识 (<0>: =租赁; <1>: =车自有) startIndex += length; @@ -112,14 +127,16 @@ public class ChargingHandshakeHandler extends AbstractYkcHandler { // BMS 车辆识别码 startIndex += length; length = 17; - byte[] BMSCarIdentifyCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + byte[] vinByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); + String vinCode = YKCUtils.parseVin(vinByteArr); // BMS 软件版本号 startIndex += length; length = 8; byte[] BMSSoftwareVersionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); - + // 保存数据到redis + // redisCache.setCacheObject(); return null; } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/PileBasicInfoService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/PileBasicInfoService.java index 2720a625c..2e6e153e9 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/PileBasicInfoService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/PileBasicInfoService.java @@ -1,5 +1,6 @@ package com.jsowell.pile.service; +import com.jsowell.common.core.domain.ykc.BMSDemandAndChargerOutputData; import com.jsowell.common.core.domain.ykc.RealTimeMonitorData; import com.jsowell.pile.domain.PileBasicInfo; import com.jsowell.pile.domain.ebike.deviceupload.EBikeMessageCmd20; @@ -151,6 +152,19 @@ public interface PileBasicInfoService { */ void saveRealTimeMonitorData2Redis(RealTimeMonitorData realTimeMonitorData); + /** + * 0x23数据保存到redis + * @param bmsDemandAndChargerOutputData + */ + void saveBMSDemandAndChargerOutputInfo2Redis(BMSDemandAndChargerOutputData bmsDemandAndChargerOutputData); + + /** + * 根据交易流水号查询0x23数据(时间倒序) + * @param transactionCode + * @return + */ + List getBMSDemandAndChargerOutputInfoList(String transactionCode); + PileConnectorDetailVO queryPileConnectorDetail(String pileConnectorCode); String getPileQrCodeUrl(String pileSn); diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileBasicInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileBasicInfoServiceImpl.java index fb50aea81..4631511a3 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileBasicInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileBasicInfoServiceImpl.java @@ -1,11 +1,13 @@ package com.jsowell.pile.service.impl; import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; import com.google.common.collect.Lists; import com.jsowell.common.YouDianUtils; import com.jsowell.common.constant.CacheConstants; import com.jsowell.common.constant.Constants; import com.jsowell.common.core.domain.vo.AuthorizedDeptVO; +import com.jsowell.common.core.domain.ykc.BMSDemandAndChargerOutputData; import com.jsowell.common.core.domain.ykc.GroundLockData; import com.jsowell.common.core.domain.ykc.RealTimeMonitorData; import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode; @@ -663,6 +665,66 @@ public class PileBasicInfoServiceImpl implements PileBasicInfoService { redisCache.setCacheObject(pileIsChargingKey, realTimeMonitorData.getTransactionCode(), 20); } + /** + * 0x23信息设置缓存 (缓存时间3天) + * @param data + */ + public void saveBMSDemandAndChargerOutputInfo2Redis(BMSDemandAndChargerOutputData data) { + if (StringUtils.equals(data.getTransactionCode(), Constants.ILLEGAL_TRANSACTION_CODE)) { + return; + } + // 保存到redis + String redisKey = CacheConstants.BMS_CHARGE_INFO_BY_TRANSACTION_CODE + data.getTransactionCode(); + // 设置接收到实时数据的时间 + Date now = new Date(); + data.setDateTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now)); + // 计算功率,后面查询要用 + String power = new BigDecimal(data.getPileVoltageOutput()) + .multiply(new BigDecimal(data.getPileCurrentOutput())).setScale(2, RoundingMode.HALF_UP).toString(); + data.setOutputPower(power); + // 保存json字符串 + String jsonMsg = JSON.toJSONString(data); + // 0x23数据20秒发送一次,1分钟3次,在同一分钟内,只保留最后一条实时数据 + redisCache.hset(redisKey, DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:00", now), jsonMsg); + + // 设置过期时间 + try { + redisCache.expire(redisKey, CacheConstants.cache_expire_time_3d); + // if (redisCache.getExpire(redisKey) < 0) { + // } + } catch (Exception e) { + log.info("0x23存入缓存设置过期时间error", e); + } + } + + /** + * 根据交易流水号查询0x23数据(时间倒序) + * @param transactionCode + * @return + */ + @Override + public List getBMSDemandAndChargerOutputInfoList(String transactionCode) { + List resultList = Lists.newArrayList(); + if (StringUtils.isBlank(transactionCode)) { + return resultList; + } + String redisKey = CacheConstants.BMS_CHARGE_INFO_BY_TRANSACTION_CODE + transactionCode; + // 拿到所有数据 + Map map = redisCache.hmget(redisKey); + if (map != null && !map.isEmpty()) { + List keyList = map.keySet().stream() + .map(x -> (String) x) + .sorted(Comparator.reverseOrder()) // 对keyList排序 时间倒序 + .collect(Collectors.toList()); + for (String s : keyList) { + Object o = map.get(s); + BMSDemandAndChargerOutputData data = JSONObject.parseObject((String) o, BMSDemandAndChargerOutputData.class); + resultList.add(data); + } + } + return resultList; + } + @Override public PileConnectorDetailVO queryPileConnectorDetail(String pileConnectorCode) { return pileBasicInfoMapper.queryPileConnectorDetail(pileConnectorCode); diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/ChargeAlgorithmService.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/ChargeAlgorithmService.java index d9567f1f0..32106eac2 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/ChargeAlgorithmService.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/ChargeAlgorithmService.java @@ -1,16 +1,24 @@ package com.jsowell.thirdparty.platform.service.impl; +import cn.hutool.http.HttpRequest; +import com.alibaba.fastjson2.JSON; import com.jsowell.common.constant.CacheConstants; import com.jsowell.common.constant.Constants; +import com.jsowell.common.core.domain.ykc.BMSDemandAndChargerOutputData; +import com.jsowell.common.core.domain.ykc.RealTimeMonitorData; import com.jsowell.common.core.domain.ykc.TransactionRecordsData; import com.jsowell.common.core.redis.RedisCache; import com.jsowell.common.util.StringUtils; import com.jsowell.pile.service.OrderBasicInfoService; +import com.jsowell.pile.service.PileBasicInfoService; import com.jsowell.pile.thirdparty.ParameterConfigData; import com.jsowell.pile.vo.uniapp.customer.OrderVO; import com.jsowell.thirdparty.platform.domain.ChargeAlgorithmData; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.List; /** * 订单算法平台Service @@ -24,6 +32,9 @@ public class ChargeAlgorithmService { @Autowired private OrderBasicInfoService orderBasicInfoService; + @Autowired + private PileBasicInfoService pileBasicInfoService; + @Autowired private RedisCache redisCache; @@ -48,6 +59,23 @@ public class ChargeAlgorithmService { String transactionDataKey = CacheConstants.TRANSACTION_RECORD_BY_TRANSACTION_CODE + transactionCode; TransactionRecordsData transactionRecordsData = redisCache.getCacheObject(transactionDataKey); + // 获取最近一条的0x23数据 + List bmsChargeInfoList = pileBasicInfoService.getBMSDemandAndChargerOutputInfoList(transactionCode); + if (CollectionUtils.isEmpty(bmsChargeInfoList)) { + return; + } + BMSDemandAndChargerOutputData bmsDemandAndChargerOutputData = bmsChargeInfoList.get(0); + + // 获取最后一条0x13 + List chargingRealTimeDataList = orderBasicInfoService.getChargingRealTimeData(transactionCode); + if (CollectionUtils.isEmpty(chargingRealTimeDataList)) { + return; + } + RealTimeMonitorData realTimeMonitorData = chargingRealTimeDataList.get(0); + + // 获取0x25 + + ChargeAlgorithmData data = ChargeAlgorithmData.builder() .orderCode(orderCode) .initSoc(Constants.zero) @@ -60,37 +88,38 @@ public class ChargeAlgorithmService { .remainChargeTime(Constants.zero) .maxAllowElectricity(parameterConfigData.getBmsMaxCurrent()) .singleMaxAllowVoltage(parameterConfigData.getBmsMaxVoltage()) - // .dcv() - // .dca() - // .bmsDemandVoltage(parameterConfigData.get) - // .bmsDemandElectricity() - // .bmsChargeMode() + .dcv(bmsDemandAndChargerOutputData.getPileVoltageOutput()) // 直流充电电压 + .dca(bmsDemandAndChargerOutputData.getPileCurrentOutput()) // 直流充电电流 + .bmsDemandVoltage(bmsDemandAndChargerOutputData.getBmsVoltageDemand()) // BMS需求电压 + .bmsDemandElectricity(bmsDemandAndChargerOutputData.getBmsCurrentDemand()) // BMS需求电流 + .bmsChargeMode(Integer.parseInt(bmsDemandAndChargerOutputData.getBmsChargingModel())) // BMS充电模式 .readBeforeCharge(transactionRecordsData.getAmmeterTotalStart()) .readCurrentCharge(transactionRecordsData.getAmmeterTotalEnd()) .beginTime(orderVO.getStartTime()) .maxAllowTemp(parameterConfigData.getBmsMaxTemperature()) - // .chargePower() - // .ratedCapacity() + .chargePower(bmsDemandAndChargerOutputData.getOutputPower()) // 充电功率 + .ratedCapacity(parameterConfigData.getBmsSumEnergy()) // 电池额定容量 .nominalEnergy(parameterConfigData.getBmsSumEnergy()) - // .ratedVoltage() + // .ratedVoltage() // 电池额定总电压 .singleMaxVoltage(parameterConfigData.getPileMaxOutputVoltage()) .singleMinVoltage(parameterConfigData.getPileMinOutputVoltage()) - // .singleMaxTemp() - // .ventTemp() - // .environmentTemp() - // .gunTemp() - // .doorStatus() - // .bmsVersion() - // .measuringChargeVoltage() - // .measuringChargeElectricity() - // .maxSingleVoltageGroupNum() - // .maxSingleVoltageNum() - // .maxTempPointNum() - // .minTempPointNum() - // .batteryType() - // .batteryInsulation() + // .singleMaxTemp(realTimeMonitorData.getBatteryMaxTemperature()) // 单体最高温度 + // .singleMinTemp() // 单体最低温度 + // .ventTemp() // 出风口温度 + // .environmentTemp() // 环境温度 + .gunTemp(realTimeMonitorData.getGunLineCode()) // 充电枪温度 + .doorStatus(Constants.zero) // 舱门状态 + .bmsVersion("V1.1") // BMS版本 + .measuringChargeVoltage(bmsDemandAndChargerOutputData.getBmsChargingVoltage()) // 车辆测量充电电压 + .measuringChargeElectricity(bmsDemandAndChargerOutputData.getBmsChargingCurrent()) // 车辆测量充电电流 + // .maxSingleVoltageGroupNum() // 最高单体电压组号 + // .maxSingleVoltageNum() // 最高单体电压编号 + // .maxTempPointNum() // 最高温度点编号 + // .minTempPointNum() // 最低温度点编号 + // .batteryType() // 电池类型 + // .batteryInsulation() // 电池绝缘状态 .maxAllowTotalVoltage(parameterConfigData.getBmsMaxChargingVoltage()) - // .beforeChargeTotalVoltage() + // .beforeChargeTotalVoltage() // 充电前总电压 .build(); @@ -100,5 +129,12 @@ public class ChargeAlgorithmService { if (StringUtils.isNotBlank(orderVO.getEndSoc())) { data.setCurrentSoc(Integer.parseInt(orderVO.getEndSoc())); } + + String url = "http://150.158.199.92:58910/gateway/api/user/battery/algorithm/json"; + String clientId = ""; + // 发送请求 + String response = HttpRequest.post(url).header("clientId", clientId).body(JSON.toJSONString(data)).execute().body(); + + } }