WIP:启动充电,Redis自增溢出重置序列号 TODO:HBLogic

This commit is contained in:
ZZ 2021-07-27 18:41:10 +08:00
parent 25718029fd
commit fa8fd1965e
7 changed files with 138 additions and 23 deletions

View File

@ -24,6 +24,10 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-core</artifactId> <artifactId>ruoyi-common-core</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-redis</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
<finalName>${project.artifactId}</finalName> <finalName>${project.artifactId}</finalName>

View File

@ -0,0 +1,48 @@
package com.xhpc.common.data.redis;
import com.ruoyi.common.redis.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class SeqUtil {
public static RedisService REDIS;
@Autowired
public RedisService redisService;
@PostConstruct
public void init() {
REDIS = redisService;
}
public synchronized static String seqHex(String key) {
String upperCode = "";
RedisAtomicLong counter = new RedisAtomicLong(key, REDIS.redisTemplate.getConnectionFactory());
long result = counter.incrementAndGet();
upperCode = String.format("%04X", result);
if (upperCode.equals("FFFF")) {
REDIS.deleteObject(key);
}
return upperCode;
}
public synchronized static String seqDec(String key, int len) {
String upperCode = "";
RedisAtomicLong counter = new RedisAtomicLong(key, REDIS.redisTemplate.getConnectionFactory());
long result = counter.incrementAndGet();
upperCode = String.format("%04d", result);
if (upperCode.equals("9999")) {
REDIS.deleteObject(key);
}
return upperCode;
}
}

View File

@ -4,7 +4,6 @@ import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService; import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance; import com.alibaba.nacos.api.naming.pojo.Instance;
import com.xhpc.pp.logic.RegisterLogic;
import com.xhpc.pp.utils.SpringContextHolder; import com.xhpc.pp.utils.SpringContextHolder;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -13,6 +12,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import static com.ruoyi.common.core.utils.GetIpAndPort.getLocalIP; import static com.ruoyi.common.core.utils.GetIpAndPort.getLocalIP;
import static com.xhpc.pp.logic.RegisterLogic.DISCONNECTED;
import static com.xhpc.pp.server.ChargingPileServer.REDIS; import static com.xhpc.pp.server.ChargingPileServer.REDIS;
@Configuration @Configuration
@ -32,15 +32,16 @@ public class EarlierBeanConf {
public static boolean ifreg(String pileNo) throws NacosException { public static boolean ifreg(String pileNo) throws NacosException {
Map<String, Object> cachePile = REDIS.getCacheMap("pile:".concat(pileNo)); Map<String, Object> cachePile = REDIS.getCacheMap("pile:".concat(pileNo));
String server = (String) cachePile.get("server"); if (!cachePile.isEmpty()) {
if (server != null) { String server = (String) cachePile.get("svcSrv");
if (server == null) return true;
String nacosServer = REDIS.getCacheObject("nacos").toString(); String nacosServer = REDIS.getCacheObject("nacos").toString();
NamingService namingService = NacosFactory.createNamingService(nacosServer); NamingService namingService = NacosFactory.createNamingService(nacosServer);
List<Instance> ppInstances = namingService.getAllInstances("xhpc-power-pile"); List<Instance> ppInstances = namingService.getAllInstances("xhpc-power-pile");
String status = (String) cachePile.get("status"); String status = (String) cachePile.get("status");
for (Instance i : ppInstances) { for (Instance i : ppInstances) { // todo make HBLogic work
if (i.getIp().concat("#").concat(Integer.valueOf(i.getPort()).toString()).equals(server)) { if (i.getIp().concat("#").concat(Integer.valueOf(i.getPort()).toString()).equals(server)) {
if (!RegisterLogic.DISCONNECTED.equals(status)) { if (!DISCONNECTED.equals(status)) {
return false; return false;
} }
} }

View File

@ -1,14 +1,21 @@
package com.xhpc.pp.controller; package com.xhpc.pp.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.HttpUtils;
import com.xhpc.common.api.PowerPileService; import com.xhpc.common.api.PowerPileService;
import com.xhpc.common.data.down.StartChargingData; import com.xhpc.common.data.down.StartChargingData;
import com.xhpc.common.data.up.OrderData; import com.xhpc.common.data.up.OrderData;
import com.xhpc.pp.logic.FieldLogic; import com.xhpc.pp.logic.FieldLogic;
import com.xhpc.pp.server.ChargingPileServer; import com.xhpc.pp.server.ChargingPileServer;
import com.xhpc.pp.tx.ServiceResult;
import com.xhpc.pp.utils.security.CRCCalculator;
import com.xhpc.pp.utils.security.HexUtils; import com.xhpc.pp.utils.security.HexUtils;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.quickserver.net.server.ClientHandler; import org.quickserver.net.server.ClientHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -16,13 +23,19 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.io.IOException; import java.io.IOException;
import java.util.Map;
import static com.xhpc.common.data.redis.SeqUtil.seqHex;
import static com.xhpc.pp.logic.RegisterLogic.REGISTERED;
import static com.xhpc.pp.server.ChargingPileServer.REDIS;
import static com.xhpc.pp.server.ChargingPileServer.default_version; import static com.xhpc.pp.server.ChargingPileServer.default_version;
import static com.xhpc.pp.utils.security.HexUtils.toHexInt; import static com.xhpc.pp.utils.security.HexUtils.toHexInt;
@RestController @RestController
public class ChargingController { public class ChargingController {
private static final Logger log = LoggerFactory.getLogger(ChargingController.class);
@Autowired @Autowired
private PowerPileService powerPileService; private PowerPileService powerPileService;
@Autowired @Autowired
@ -39,10 +52,44 @@ public class ChargingController {
@PostMapping("charging/start") @PostMapping("charging/start")
public Object startCharging(@Validated @RequestBody StartChargingData startChargingData) { public Object startCharging(@Validated @RequestBody StartChargingData startChargingData) {
byte[] msg = translate(startChargingData); String pileNo = startChargingData.getPileNo();
ClientHandler clientHandler = ChargingPileServer.getHandler(startChargingData.getPileNo()); String pileKey = "pile:".concat(pileNo);
if (clientHandler == null) return R.fail(); Map<String, String> cachePile = REDIS.getCacheMap(pileKey);
if (cachePile.isEmpty()) {
return R.fail("充电桩未注册");
}
String status = cachePile.get("status");
if (!REGISTERED.equals(status)) {
return R.fail("充电桩离线");
}
String svcSrv = cachePile.get("svcSrv");
JSONObject json = (JSONObject) JSON.toJSON(startChargingData);
String response = HttpUtils.post(fmt(svcSrv).concat("/native/charging/start"), json);
JSONObject responseJson = (JSONObject) JSON.parse(response);
int code = responseJson.getInteger("code");
if (code != 200) {
return R.fail(code, responseJson.getString("msg"));
}
return R.ok(responseJson.get("data"), responseJson.getString("msg"));
}
private String fmt(String svcSrv) {
String[] split = svcSrv.split("#");
return "http://".concat(split[0]).concat(":").concat(split[1]);
}
@PostMapping("native/charging/start")
public Object nativeStartCharging(@Validated @RequestBody StartChargingData startChargingData) {
String pileNo = startChargingData.getPileNo();
ClientHandler clientHandler = ChargingPileServer.getHandler(pileNo);
if (clientHandler == null) return R.fail("充电桩没有连接到上次注册的服务器");
try { try {
String gunKey = "gun:".concat(pileNo).concat(startChargingData.getGunId());
String skey = gunKey.concat(".seqhex");
String seq = seqHex(skey);
byte[] msg = translateSucc(startChargingData, seq);
clientHandler.sendClientBinary(msg); clientHandler.sendClientBinary(msg);
return R.ok(); return R.ok();
} catch (IOException e) { } catch (IOException e) {
@ -51,10 +98,11 @@ public class ChargingController {
} }
} }
private byte[] translate(StartChargingData startChargingData) {
private byte[] translateSucc(StartChargingData startChargingData, String seq) {
byte[] data = new byte[0]; byte[] data = new byte[0];
data = ArrayUtils.addAll(data, HexUtils.toBytes("6830007C0034")); data = ArrayUtils.addAll(data, HexUtils.toBytes("6830".concat(seq).concat("0034")));
String version = startChargingData.getVersion(); String version = startChargingData.getVersion();
if (default_version.equals(version)) { if (default_version.equals(version)) {
data = ArrayUtils.addAll(data, HexUtils.toBytes(startChargingData.getOrderNo())); data = ArrayUtils.addAll(data, HexUtils.toBytes(startChargingData.getOrderNo()));
@ -66,7 +114,9 @@ public class ChargingController {
} else { } else {
// not defined or implemented yet // not defined or implemented yet
} }
return data; String msg = HexUtils.toHex(data).concat(ServiceResult.HEX_OK);
log.info("msg2bsent2pile:{}", msg);
return HexUtils.toBytes(msg.concat(CRCCalculator.calcCrc(msg)));
} }
} }

View File

@ -13,6 +13,7 @@ import org.springframework.stereotype.Component;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import static com.xhpc.pp.config.EarlierBeanConf.getLocalIPAndPort;
import static com.xhpc.pp.server.ChargingPileServer.REDIS; import static com.xhpc.pp.server.ChargingPileServer.REDIS;
@Lazy @Lazy
@ -38,10 +39,10 @@ public class RegisterLogic implements ServiceLogic {
int gunNum = Integer.parseInt(req.get("gunNum").toString()); int gunNum = Integer.parseInt(req.get("gunNum").toString());
for (int gunN = 1; gunN <= gunNum; gunN++) { for (int gunN = 1; gunN <= gunNum; gunN++) {
String gunId = String.format("%02d", (int) gunN); String gunId = String.format("%02d", (int) gunN);
String pileGun = "gun:".concat(pileNo.concat(gunId)); String gunKey = "gun:".concat(pileNo.concat(gunId));
Map<String, Object> cacheGun = REDIS.getCacheMap(pileGun); Map<String, Object> cacheGun = REDIS.getCacheMap(gunKey);
cacheGun.put("seq", 0); cacheGun.put("svcSrv", getLocalIPAndPort());
REDIS.setCacheMap(pileGun, cacheGun); REDIS.setCacheMap(gunKey, cacheGun);
} }
String resultStr = "680C00000002".concat(pileNo).concat(hexCode); String resultStr = "680C00000002".concat(pileNo).concat(hexCode);
resultStr = resultStr.concat(CRCCalculator.calcCrc(resultStr)); resultStr = resultStr.concat(CRCCalculator.calcCrc(resultStr));

View File

@ -88,7 +88,7 @@ public class ChargingPileBinaryHandler implements ClientBinaryHandler {
if (SERVICE_REGISTER.equals(serviceName) && OK.equals(resultCode)) { if (SERVICE_REGISTER.equals(serviceName) && OK.equals(resultCode)) {
reg(handler, pileNo, req); reg(handler, pileNo, req);
} /*else if (SERVICE_HB.equals(serviceName)) { } /*else if (SERVICE_HB.equals(serviceName)) {
// TODO: 2021/7/28
}*/ }*/
if (result.getBinary() != null) { if (result.getBinary() != null) {
log.info("server send msg >>>> [{}] |{}|", pileNo, HexUtils.toHex(result.getBinary())); log.info("server send msg >>>> [{}] |{}|", pileNo, HexUtils.toHex(result.getBinary()));
@ -107,15 +107,26 @@ public class ChargingPileBinaryHandler implements ClientBinaryHandler {
String pileKey = "pile:".concat(pileNo); String pileKey = "pile:".concat(pileNo);
Map<String, Object> pileCache = REDIS.getCacheMap(pileKey); Map<String, Object> pileCache = REDIS.getCacheMap(pileKey);
pileCache.put("status", REGISTERED); pileCache.put("status", REGISTERED);
pileCache.put("server", getLocalIPAndPort()); pileCache.put("svcSrv", getLocalIPAndPort());
REDIS.setCacheMap(pileKey, pileCache); REDIS.setCacheMap(pileKey, pileCache);
String svcKey = "ppSvcSrv:".concat(getLocalIPAndPort()); cachePileGunSvcSrv("svcSrvPile:", pileNo);
Set<String> svcPiles = REDIS.getCacheSet(svcKey); int gunNum = Integer.parseInt(req.get("gunNum").toString());
svcPiles.add(pileKey); for (int gunN = 1; gunN <= gunNum; gunN++) {
REDIS.setCacheSet(svcKey, svcPiles); String gunId = String.format("%02d", (int) gunN);
String gunKey = pileNo.concat(gunId);
cachePileGunSvcSrv("svcSrvGun:", gunKey);
}
log.info("pile registering >>>> [{}] ", pileNo); log.info("pile registering >>>> [{}] ", pileNo);
} }
private void cachePileGunSvcSrv(String prefix, String key) {
String svcKey = prefix.concat(getLocalIPAndPort());
Set<String> svcPileGuns = REDIS.getCacheSet(svcKey);
svcPileGuns.add(key);
REDIS.setCacheSet(svcKey, svcPileGuns);
}
private List<byte[]> parseDataList(byte[] data) { private List<byte[]> parseDataList(byte[] data) {
List<byte[]> dataList = new ArrayList<>(); List<byte[]> dataList = new ArrayList<>();

View File

@ -131,9 +131,9 @@ public class ChargingPileServer {
return version; return version;
} }
public static ClientHandler getHandler(String pileNo) { public static ClientHandler getHandler(String pile) {
return handlerMap.get(pileNo); return handlerMap.get(pile);
} }
public static String getPileNo(ClientHandler handler) { public static String getPileNo(ClientHandler handler) {