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>
<artifactId>ruoyi-common-core</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-redis</artifactId>
</dependency>
</dependencies>
<build>
<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.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.xhpc.pp.logic.RegisterLogic;
import com.xhpc.pp.utils.SpringContextHolder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@ -13,6 +12,7 @@ import java.util.List;
import java.util.Map;
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;
@Configuration
@ -32,15 +32,16 @@ public class EarlierBeanConf {
public static boolean ifreg(String pileNo) throws NacosException {
Map<String, Object> cachePile = REDIS.getCacheMap("pile:".concat(pileNo));
String server = (String) cachePile.get("server");
if (server != null) {
if (!cachePile.isEmpty()) {
String server = (String) cachePile.get("svcSrv");
if (server == null) return true;
String nacosServer = REDIS.getCacheObject("nacos").toString();
NamingService namingService = NacosFactory.createNamingService(nacosServer);
List<Instance> ppInstances = namingService.getAllInstances("xhpc-power-pile");
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 (!RegisterLogic.DISCONNECTED.equals(status)) {
if (!DISCONNECTED.equals(status)) {
return false;
}
}

View File

@ -1,14 +1,21 @@
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.utils.HttpUtils;
import com.xhpc.common.api.PowerPileService;
import com.xhpc.common.data.down.StartChargingData;
import com.xhpc.common.data.up.OrderData;
import com.xhpc.pp.logic.FieldLogic;
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 org.apache.commons.lang3.ArrayUtils;
import org.quickserver.net.server.ClientHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
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 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.utils.security.HexUtils.toHexInt;
@RestController
public class ChargingController {
private static final Logger log = LoggerFactory.getLogger(ChargingController.class);
@Autowired
private PowerPileService powerPileService;
@Autowired
@ -39,10 +52,44 @@ public class ChargingController {
@PostMapping("charging/start")
public Object startCharging(@Validated @RequestBody StartChargingData startChargingData) {
byte[] msg = translate(startChargingData);
ClientHandler clientHandler = ChargingPileServer.getHandler(startChargingData.getPileNo());
if (clientHandler == null) return R.fail();
String pileNo = startChargingData.getPileNo();
String pileKey = "pile:".concat(pileNo);
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 {
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);
return R.ok();
} 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];
data = ArrayUtils.addAll(data, HexUtils.toBytes("6830007C0034"));
data = ArrayUtils.addAll(data, HexUtils.toBytes("6830".concat(seq).concat("0034")));
String version = startChargingData.getVersion();
if (default_version.equals(version)) {
data = ArrayUtils.addAll(data, HexUtils.toBytes(startChargingData.getOrderNo()));
@ -66,7 +114,9 @@ public class ChargingController {
} else {
// 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.Set;
import static com.xhpc.pp.config.EarlierBeanConf.getLocalIPAndPort;
import static com.xhpc.pp.server.ChargingPileServer.REDIS;
@Lazy
@ -38,10 +39,10 @@ public class RegisterLogic implements ServiceLogic {
int gunNum = Integer.parseInt(req.get("gunNum").toString());
for (int gunN = 1; gunN <= gunNum; gunN++) {
String gunId = String.format("%02d", (int) gunN);
String pileGun = "gun:".concat(pileNo.concat(gunId));
Map<String, Object> cacheGun = REDIS.getCacheMap(pileGun);
cacheGun.put("seq", 0);
REDIS.setCacheMap(pileGun, cacheGun);
String gunKey = "gun:".concat(pileNo.concat(gunId));
Map<String, Object> cacheGun = REDIS.getCacheMap(gunKey);
cacheGun.put("svcSrv", getLocalIPAndPort());
REDIS.setCacheMap(gunKey, cacheGun);
}
String resultStr = "680C00000002".concat(pileNo).concat(hexCode);
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)) {
reg(handler, pileNo, req);
} /*else if (SERVICE_HB.equals(serviceName)) {
// TODO: 2021/7/28
}*/
if (result.getBinary() != null) {
log.info("server send msg >>>> [{}] |{}|", pileNo, HexUtils.toHex(result.getBinary()));
@ -107,15 +107,26 @@ public class ChargingPileBinaryHandler implements ClientBinaryHandler {
String pileKey = "pile:".concat(pileNo);
Map<String, Object> pileCache = REDIS.getCacheMap(pileKey);
pileCache.put("status", REGISTERED);
pileCache.put("server", getLocalIPAndPort());
pileCache.put("svcSrv", getLocalIPAndPort());
REDIS.setCacheMap(pileKey, pileCache);
String svcKey = "ppSvcSrv:".concat(getLocalIPAndPort());
Set<String> svcPiles = REDIS.getCacheSet(svcKey);
svcPiles.add(pileKey);
REDIS.setCacheSet(svcKey, svcPiles);
cachePileGunSvcSrv("svcSrvPile:", pileNo);
int gunNum = Integer.parseInt(req.get("gunNum").toString());
for (int gunN = 1; gunN <= gunNum; gunN++) {
String gunId = String.format("%02d", (int) gunN);
String gunKey = pileNo.concat(gunId);
cachePileGunSvcSrv("svcSrvGun:", gunKey);
}
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) {
List<byte[]> dataList = new ArrayList<>();

View File

@ -131,9 +131,9 @@ public class ChargingPileServer {
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) {