mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-04-20 19:15:35 +08:00
update 预约充电
This commit is contained in:
@@ -85,6 +85,8 @@ import com.jsowell.wxpay.common.WeChatPayParameter;
|
||||
import com.jsowell.wxpay.dto.AppletTemplateMessageSendDTO;
|
||||
import com.jsowell.wxpay.response.WechatPayRefundRequest;
|
||||
import com.jsowell.wxpay.service.WxAppletRemoteService;
|
||||
import demo.ChargingPileServerHandler;
|
||||
import demo.ProtocolUtil;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.junit.Test;
|
||||
@@ -104,6 +106,8 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ActiveProfiles("dev")
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @program: com.cjml.service.partitem
|
||||
* @description:
|
||||
* @author: dc
|
||||
* @create: 2023-09-09 13:46
|
||||
**/
|
||||
public class Test {
|
||||
|
||||
public static void main(String[] args) {
|
||||
List<Category> testList = Lists.newArrayList();
|
||||
testList.add(new Category("100-50-10", 100, 50, 10));
|
||||
testList.add(new Category("110-30-8", 110, 30, 8));
|
||||
testList.add(new Category("0-10-12", 0, 10, 12));
|
||||
|
||||
testList = testList.stream().sorted(
|
||||
Comparator.comparing(Category::getCategoryGroupSort, Comparator.reverseOrder())
|
||||
.thenComparing(Category::getCategorySort, Comparator.reverseOrder())
|
||||
.thenComparing(Category::getPartSort)
|
||||
)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
System.out.println(testList.get(0).getCategoryName());
|
||||
System.out.println(testList.get(1).getCategoryName());
|
||||
System.out.println(testList.get(2).getCategoryName());
|
||||
}
|
||||
|
||||
static class Category {
|
||||
|
||||
private String categoryName;
|
||||
|
||||
private int categoryGroupSort;
|
||||
|
||||
private int categorySort;
|
||||
|
||||
private int partSort;
|
||||
|
||||
public Category() {
|
||||
}
|
||||
|
||||
public Category(String categoryName, int categoryGroupSort, int categorySort, int partSort) {
|
||||
this.categoryName = categoryName;
|
||||
this.categoryGroupSort = categoryGroupSort;
|
||||
this.categorySort = categorySort;
|
||||
this.partSort = partSort;
|
||||
}
|
||||
|
||||
public String getCategoryName() {
|
||||
return categoryName;
|
||||
}
|
||||
|
||||
public void setCategoryName(String categoryName) {
|
||||
this.categoryName = categoryName;
|
||||
}
|
||||
|
||||
public int getCategoryGroupSort() {
|
||||
return categoryGroupSort;
|
||||
}
|
||||
|
||||
public void setCategoryGroupSort(int categoryGroupSort) {
|
||||
this.categoryGroupSort = categoryGroupSort;
|
||||
}
|
||||
|
||||
public int getCategorySort() {
|
||||
return categorySort;
|
||||
}
|
||||
|
||||
public void setCategorySort(int categorySort) {
|
||||
this.categorySort = categorySort;
|
||||
}
|
||||
|
||||
public int getPartSort() {
|
||||
return partSort;
|
||||
}
|
||||
|
||||
public void setPartSort(int partSort) {
|
||||
this.partSort = partSort;
|
||||
}
|
||||
}
|
||||
}
|
||||
80
jsowell-admin/src/test/java/demo/ChargingPileClient.java
Normal file
80
jsowell-admin/src/test/java/demo/ChargingPileClient.java
Normal file
@@ -0,0 +1,80 @@
|
||||
package demo;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.bytes.ByteArrayDecoder;
|
||||
import io.netty.handler.codec.bytes.ByteArrayEncoder;
|
||||
|
||||
public class ChargingPileClient {
|
||||
private final String host;
|
||||
private final int port;
|
||||
|
||||
public ChargingPileClient(String host, int port) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void start() throws Exception {
|
||||
EventLoopGroup group = new NioEventLoopGroup();
|
||||
try {
|
||||
Bootstrap b = new Bootstrap();
|
||||
b.group(group)
|
||||
.channel(NioSocketChannel.class)
|
||||
.handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
public void initChannel(SocketChannel ch) throws Exception {
|
||||
ChannelPipeline pipeline = ch.pipeline();
|
||||
pipeline.addLast(new ByteArrayDecoder());
|
||||
pipeline.addLast(new ByteArrayEncoder());
|
||||
pipeline.addLast(new ChargingPileClientHandler());
|
||||
}
|
||||
});
|
||||
|
||||
ChannelFuture f = b.connect(host, port).sync();
|
||||
System.out.println("充电桩客户端已连接到服务器");
|
||||
f.channel().closeFuture().sync();
|
||||
} finally {
|
||||
group.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String host = "localhost";
|
||||
int port = 9011;
|
||||
new ChargingPileClient(host, port).start();
|
||||
}
|
||||
}
|
||||
|
||||
class ChargingPileClientHandler extends ChannelInboundHandlerAdapter {
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) {
|
||||
byte[] command = (byte[]) msg;
|
||||
System.out.println("收到服务器指令: " + ProtocolUtil.bytesToHex(command));
|
||||
|
||||
// 处理工作参数设置指令
|
||||
if (command[5] == 0x52) {
|
||||
String pileId = ProtocolUtil.bytesToHex(command).substring(12, 26);
|
||||
boolean allowWork = (command[19] == 0x00);
|
||||
int maxPower = command[20] & 0xFF;
|
||||
|
||||
System.out.println("收到工作参数设置:");
|
||||
System.out.println("桩编号: " + pileId);
|
||||
System.out.println("是否允许工作: " + (allowWork ? "允许" : "不允许"));
|
||||
System.out.println("最大允许输出功率: " + maxPower + "%");
|
||||
|
||||
// 模拟设置成功
|
||||
byte[] response = ProtocolUtil.createSetWorkParamsResponseFrame(pileId, true);
|
||||
ctx.writeAndFlush(response);
|
||||
System.out.println("发送响应: " + ProtocolUtil.bytesToHex(response));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
cause.printStackTrace();
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
34
jsowell-admin/src/test/java/demo/ChargingPileController.java
Normal file
34
jsowell-admin/src/test/java/demo/ChargingPileController.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package demo;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/charging")
|
||||
public class ChargingPileController {
|
||||
|
||||
private final ChannelHandlerContext chargingPileChannel;
|
||||
|
||||
public ChargingPileController(ChannelHandlerContext chargingPileChannel) {
|
||||
this.chargingPileChannel = chargingPileChannel;
|
||||
}
|
||||
|
||||
@PostMapping("/setWorkParams")
|
||||
public String setWorkParams(@RequestParam String pileId,
|
||||
@RequestParam boolean allowWork,
|
||||
@RequestParam int maxPower) {
|
||||
try {
|
||||
byte[] command = ProtocolUtil.createSetWorkParamsFrame(pileId, allowWork, maxPower);
|
||||
CompletableFuture<byte[]> future = ChargingPileServerHandler.sendCommand(chargingPileChannel, command);
|
||||
byte[] response = future.get(5, TimeUnit.SECONDS);
|
||||
|
||||
// 解析响应
|
||||
boolean success = (response[18] == 0x01);
|
||||
return "设置" + (success ? "成功" : "失败");
|
||||
} catch (Exception e) {
|
||||
return "发送指令失败: " + e.getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
50
jsowell-admin/src/test/java/demo/ChargingPileServer.java
Normal file
50
jsowell-admin/src/test/java/demo/ChargingPileServer.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package demo;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.codec.bytes.ByteArrayDecoder;
|
||||
import io.netty.handler.codec.bytes.ByteArrayEncoder;
|
||||
|
||||
public class ChargingPileServer {
|
||||
private final int port;
|
||||
|
||||
public ChargingPileServer(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void start() throws Exception {
|
||||
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
|
||||
EventLoopGroup workerGroup = new NioEventLoopGroup();
|
||||
try {
|
||||
ServerBootstrap b = new ServerBootstrap();
|
||||
b.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
public void initChannel(SocketChannel ch) throws Exception {
|
||||
ChannelPipeline pipeline = ch.pipeline();
|
||||
pipeline.addLast(new ByteArrayDecoder());
|
||||
pipeline.addLast(new ByteArrayEncoder());
|
||||
pipeline.addLast(new ChargingPileServerHandler());
|
||||
}
|
||||
})
|
||||
.option(ChannelOption.SO_BACKLOG, 128)
|
||||
.childOption(ChannelOption.SO_KEEPALIVE, true);
|
||||
|
||||
ChannelFuture f = b.bind(port).sync();
|
||||
System.out.println("充电桩服务器启动,监听端口: " + port);
|
||||
f.channel().closeFuture().sync();
|
||||
} finally {
|
||||
workerGroup.shutdownGracefully();
|
||||
bossGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int port = 9011;
|
||||
new ChargingPileServer(port).start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package demo;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class ChargingPileServerHandler extends ChannelInboundHandlerAdapter {
|
||||
private static CompletableFuture<byte[]> responseFuture;
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) {
|
||||
byte[] response = (byte[]) msg;
|
||||
System.out.println("接收到充电桩响应: " + ProtocolUtil.bytesToHex(response));
|
||||
if (responseFuture != null) {
|
||||
responseFuture.complete(response);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
cause.printStackTrace();
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
public static CompletableFuture<byte[]> sendCommand(ChannelHandlerContext ctx, byte[] command) {
|
||||
responseFuture = new CompletableFuture<>();
|
||||
ctx.writeAndFlush(command);
|
||||
System.out.println("发送指令到充电桩: " + ProtocolUtil.bytesToHex(command));
|
||||
return responseFuture;
|
||||
}
|
||||
}
|
||||
77
jsowell-admin/src/test/java/demo/ProtocolUtil.java
Normal file
77
jsowell-admin/src/test/java/demo/ProtocolUtil.java
Normal file
@@ -0,0 +1,77 @@
|
||||
package demo;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class ProtocolUtil {
|
||||
|
||||
public static byte[] createSetWorkParamsFrame(String pileId, boolean allowWork, int maxPower) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(21);
|
||||
buffer.put((byte) 0x68); // 起始标志
|
||||
buffer.put((byte) 0x0D); // 数据长度
|
||||
buffer.putShort((short) 0x0008); // 序列号域
|
||||
buffer.put((byte) 0x00); // 加密标志
|
||||
buffer.put((byte) 0x52); // 帧类型码
|
||||
|
||||
// 桩编码
|
||||
buffer.put(hexStringToByteArray(pileId));
|
||||
|
||||
// 是否允许工作
|
||||
buffer.put((byte) (allowWork ? 0x00 : 0x01));
|
||||
|
||||
// 充电桩最大允许输出功率
|
||||
buffer.put((byte) maxPower);
|
||||
|
||||
// 计算校验和
|
||||
short checksum = calculateChecksum(buffer.array(), 1, 19);
|
||||
buffer.putShort(checksum);
|
||||
|
||||
return buffer.array();
|
||||
}
|
||||
|
||||
public static byte[] createSetWorkParamsResponseFrame(String pileId, boolean success) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(20);
|
||||
buffer.put((byte) 0x68); // 起始标志
|
||||
buffer.put((byte) 0x0C); // 数据长度
|
||||
buffer.putShort((short) 0x0008); // 序列号域
|
||||
buffer.put((byte) 0x00); // 加密标志
|
||||
buffer.put((byte) 0x51); // 帧类型码
|
||||
|
||||
// 桩编码
|
||||
buffer.put(hexStringToByteArray(pileId));
|
||||
|
||||
// 设置结果
|
||||
buffer.put((byte) (success ? 0x01 : 0x00));
|
||||
|
||||
// 计算校验和
|
||||
short checksum = calculateChecksum(buffer.array(), 1, 18);
|
||||
buffer.putShort(checksum);
|
||||
|
||||
return buffer.array();
|
||||
}
|
||||
|
||||
public static short calculateChecksum(byte[] data, int offset, int length) {
|
||||
int sum = 0;
|
||||
for (int i = offset; i < offset + length; i++) {
|
||||
sum += (data[i] & 0xFF);
|
||||
}
|
||||
return (short) (sum & 0xFFFF);
|
||||
}
|
||||
|
||||
public static byte[] hexStringToByteArray(String s) {
|
||||
int len = s.length();
|
||||
byte[] data = new byte[len / 2];
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
|
||||
+ Character.digit(s.charAt(i+1), 16));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public static String bytesToHex(byte[] bytes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : bytes) {
|
||||
sb.append(String.format("%02X ", b));
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user