diff --git a/README.md b/README.md
index e658d64..256e4ae 100644
--- a/README.md
+++ b/README.md
@@ -43,23 +43,34 @@ Java 后端项目,大规模集群设备的管理平台,使用 Spring 作为
- 采用 Redis 作为数据库的缓存,极大提升数据库的使用效率,并将服务器对帧的处理效率提升2个数量级以上。
+### Netty 服务器设计方案
+
+本节内容总结为以下文章,点击查看:
+
+[基于 Netty 的自定义帧高可靠性读取方案](http://www.jianshu.com/p/7b1010e7e293)
+
### 帧调度算法概述
>本节介绍 Java 服务器中,Netty 模块使用的帧调度算法,由于众多硬件设备的**数据帧处理能力较差**,**可靠性较差**,服务器大规模下发数据帧时,需进行有效的**拥塞控制、超时重发**,可有效提升集群设备的可靠性,降低集群设备的研发难度。
内容较多,这部分内容被放在了独立博文中,请使用如下链接查看:
-|来源|网址|
-|---|---|
-|简书|http://www.jianshu.com/p/c5da14855515|
-|主页|http://bitky.cc/2017/07/19/java/|
+[基于 Netty 的帧调度策略,自行实现流量控制及可靠性通信](http://www.jianshu.com/p/c5da14855515)
-**「注」**本部分为源码「Netty服务器」部分的解释说明,需结合源码进行阅读。
+「注」本部分为源码「Netty服务器」部分的解释说明,需结合源码进行阅读。
## JavaFX 设备模拟客户端
基于 JavaFX 开发 GUI 客户端,模拟集群设备的行为,并可对服务器进行压力测试。
+本程序开发时,相关技巧和填坑总结为以下文章:
+
+[JavaFX 8 下简化自定义控件的外部调用以及流式布局示例](http://www.jianshu.com/p/9b5300b44f39)
+
+[Maven 集成 JavaFX 8 以及 fx:root 问题探讨](http://www.jianshu.com/p/fce816babefc)
+
+
+
### 模拟客户端主界面

diff --git a/clustermanage-server/.gitignore b/clustermanage-server/.gitignore
index 9acd70e..d31078f 100644
--- a/clustermanage-server/.gitignore
+++ b/clustermanage-server/.gitignore
@@ -1,3 +1,6 @@
+运行/
+
+
target/
.mvn/
diff --git a/clustermanage-server/pom.xml b/clustermanage-server/pom.xml
index 1eb18a6..6de990c 100644
--- a/clustermanage-server/pom.xml
+++ b/clustermanage-server/pom.xml
@@ -6,7 +6,7 @@
cc.bitky.clustermanage
clustermanage-server
- 0.9.2-release
+ 0.9.3-release
jar
clustermanage-server
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/ClustermanageServerApplication.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/ClustermanageServerApplication.java
index 127043f..3c7f183 100644
--- a/clustermanage-server/src/main/java/cc/bitky/clustermanage/ClustermanageServerApplication.java
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/ClustermanageServerApplication.java
@@ -52,6 +52,7 @@ private static void initSetting() {
ServerSetting.DEFAULT_EMPLOYEE_CARD_NUMBER = exSetting.员工默认卡号;
ServerSetting.DEFAULT_EMPLOYEE_NAME = exSetting.员工默认姓名;
ServerSetting.DEFAULT_EMPLOYEE_DEPARTMENT = exSetting.员工默认部门;
+ ServerSetting.AUTO_REPEAT_REQUEST_TIMES = exSetting.检错重发最大重复次数;
}
}
}
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/db/presenter/DbDevicePresenter.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/db/presenter/DbDevicePresenter.java
index 02e7a85..e1e33f4 100644
--- a/clustermanage-server/src/main/java/cc/bitky/clustermanage/db/presenter/DbDevicePresenter.java
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/db/presenter/DbDevicePresenter.java
@@ -11,6 +11,7 @@
import cc.bitky.clustermanage.db.bean.Device;
import cc.bitky.clustermanage.db.repository.DeviceRepository;
+import cc.bitky.clustermanage.server.message.ChargeStatus;
import cc.bitky.clustermanage.server.message.tcp.TcpMsgResponseStatus;
@Service
@@ -48,7 +49,7 @@ Device handleMsgDeviceStatus(TcpMsgResponseStatus msgStatus) {
if (device == null) return null;
int rawStatus = device.getStatus();
int newStatus = msgStatus.getStatus();
- if (newStatus > 6 || newStatus < 0) newStatus = 50;
+ if (newStatus > 6 || newStatus < 0) newStatus = ChargeStatus.CRASH;
// if (rawStatus >= 5) {
// logger.info("设备「" + msgStatus.getGroupId() + ", " + msgStatus.getDeviceId() + "」『"
@@ -64,7 +65,7 @@ Device handleMsgDeviceStatus(TcpMsgResponseStatus msgStatus) {
return device;
}
- if (rawStatus == 2 && newStatus == 3) {
+ if (rawStatus == ChargeStatus.CHARGING && newStatus == ChargeStatus.FULL && device.getRemainChargeTime() > 0) {
device.setRemainChargeTime(device.getRemainChargeTime() - 1);
}
device.setStatus(newStatus);
@@ -78,8 +79,8 @@ Device handleMsgDeviceStatus(TcpMsgResponseStatus msgStatus) {
/**
* 获取设备的集合
*
- * @param groupId 组 Id
- * @param deviceId 设备 Id
+ * @param groupId 组 Id
+ * @param deviceId 设备 Id
* @return 设备的集合
*/
List getDevices(int groupId, int deviceId) {
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/db/presenter/KyDbPresenter.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/db/presenter/KyDbPresenter.java
index c738327..f9d9f50 100644
--- a/clustermanage-server/src/main/java/cc/bitky/clustermanage/db/presenter/KyDbPresenter.java
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/db/presenter/KyDbPresenter.java
@@ -135,7 +135,7 @@ public Device handleMsgDeviceStatus(TcpMsgResponseStatus tcpMsgResponseStatus, b
logger.info("无指定设备对应的员工和考勤表,且无法自动创建");
}
long l5 = System.currentTimeMillis();
- logger.info("时间耗费:" + (l2 - l1) + "ms; " + (l3 - l2) + "ms; " + (l4 - l3) + "ms; " + (l5 - l4) + "ms");
+ logger.info("时间耗费:" + (l2 - l1) + "ms; " + (l3 - l2) + "ms; " + (l4 - l3) + "ms; " + (l5 - l4) + "ms");
return device;
}
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/global/ExSetting.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/global/ExSetting.java
index ea5a368..6761018 100644
--- a/clustermanage-server/src/main/java/cc/bitky/clustermanage/global/ExSetting.java
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/global/ExSetting.java
@@ -7,4 +7,5 @@ public class ExSetting {
public String 员工默认部门;
public int 部署剩余充电次数阈值;
public int 帧发送间隔;
+ public int 检错重发最大重复次数;
}
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/global/ServerSetting.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/global/ServerSetting.java
index b4c27dc..03537ae 100644
--- a/clustermanage-server/src/main/java/cc/bitky/clustermanage/global/ServerSetting.java
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/global/ServerSetting.java
@@ -48,11 +48,16 @@ public class ServerSetting {
*/
public static final int COMMAND_DELAY_WAITING_TIME = 30;
+ /**
+ * 检错重发最大次数,服务器向 TCP 通道发送 CAN 帧,最大重复发送次数
+ */
+ public static int AUTO_REPEAT_REQUEST_TIMES = 5;
+
//-----------------------接收到充电状态帧时的处理策略----------------------------
/**
* 项目版本号
*/
- public static final String VERSION = "0.9.2";
+ public static final String VERSION = "0.9.3";
/**
* 主机名
*/
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/bean/KyServerCenterHandler.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/bean/KyServerCenterHandler.java
index b76d6dc..4003174 100644
--- a/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/bean/KyServerCenterHandler.java
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/bean/KyServerCenterHandler.java
@@ -135,6 +135,10 @@ boolean marchConfirmCard(String cardNumber) {
return kyDbPresenter.marchConfirmCard(cardNumber);
}
+ /**
+ * 获取 CAN 帧发送队列的信息
+ * @return CAN帧发送队列信息集合
+ */
QueueInfo obtainQueueFrame() {
int size = getSendingMsgRepo().getLinkedBlockingDeque().size();
int capacity = ServerSetting.LINKED_DEQUE_LIMIT_CAPACITY;
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/bean/ServerTcpMessageHandler.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/bean/ServerTcpMessageHandler.java
index 874153d..9c0ac45 100644
--- a/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/bean/ServerTcpMessageHandler.java
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/bean/ServerTcpMessageHandler.java
@@ -20,19 +20,21 @@
import cc.bitky.clustermanage.server.message.web.WebMsgInitMarchConfirmCardResponse;
import cc.bitky.clustermanage.server.schedule.MsgKey;
import cc.bitky.clustermanage.server.schedule.SendingMsgRepo;
-import cc.bitky.clustermanage.tcp.server.netty.SendWebMessagesListener;
+import cc.bitky.clustermanage.tcp.TcpMediator;
import io.netty.util.internal.StringUtil;
@Service
public class ServerTcpMessageHandler {
private final KyDbPresenter kyDbPresenter;
+ private final TcpMediator tcpMediator;
private Logger logger = LoggerFactory.getLogger(getClass());
- private SendWebMessagesListener sendWebMessagesListener;
private KyServerCenterHandler kyServerCenterHandler;
@Autowired
- public ServerTcpMessageHandler(KyDbPresenter kyDbPresenter) {
+ public ServerTcpMessageHandler(KyDbPresenter kyDbPresenter, TcpMediator tcpMediator) {
this.kyDbPresenter = kyDbPresenter;
+ this.tcpMediator = tcpMediator;
+ tcpMediator.setServerTcpMessageHandler(this);
}
public SendingMsgRepo getSendingMsgRepo() {
@@ -54,6 +56,7 @@ public void handleResDeviceStatus(TcpMsgResponseStatus message) {
logger.info("收到:设备状态请求的回复");
long l1 = System.currentTimeMillis();
Device device = kyDbPresenter.handleMsgDeviceStatus(message, ServerSetting.AUTO_CREATE_DEVICE_EMPLOYEE);
+ //部署剩余充电次数
if (device != null) {
deployRemainChargeTimes(device);
}
@@ -63,7 +66,6 @@ public void handleResDeviceStatus(TcpMsgResponseStatus message) {
/**
* 其他功能消息处理方法
- *
*/
public void handleTcpMsg() {
@@ -74,11 +76,13 @@ public void handleTcpMsg() {
*
* @param device 处理后的 Device
*/
-
private void deployRemainChargeTimes(Device device) {
- if (device.getRemainChargeTime() <= ServerSetting.DEPLOY_REMAIN_CHARGE_TIMES) {
+
+ //当当前充电状态为「充满」,并且剩余充电次数小于或等于阈值时,部署剩余充电次数
+ if (device.getStatus() == 3 && device.getRemainChargeTime() <= ServerSetting.DEPLOY_REMAIN_CHARGE_TIMES) {
int remainTimes = device.getRemainChargeTime();
remainTimes = remainTimes > 0 ? remainTimes : 0;
+ remainTimes = remainTimes <= 100 ? remainTimes : 100;
sendMsgToTcpSpecial(new WebMsgDeployRemainChargeTimes(device.getGroupId(), device.getDeviceId(), remainTimes), true, true);
}
}
@@ -198,10 +202,6 @@ private void handleReceivedCard(IMessage message) {
}
}
- public void setSendWebMessagesListener(SendWebMessagesListener sendWebMessagesListener) {
- this.sendWebMessagesListener = sendWebMessagesListener;
- }
-
/**
* 「特殊的」将特殊的 Message 发送至 Netty 的处理通道
*
@@ -228,21 +228,7 @@ boolean sendMsgTrafficControl(IMessage message) {
.newTimeout(timeout -> sendMsgTrafficControl(message), ServerSetting.COMMAND_DELAY_WAITING_TIME, TimeUnit.SECONDS);
return true;
}
- return sendMsgToTcp(message);
- }
-
- /**
- * 直接将 Message 发送至 Netty 的处理通道
- *
- * @param message 普通消息 Message
- * @return 是否发送成功
- */
- private boolean sendMsgToTcp(IMessage message) {
- if (sendWebMessagesListener == null) {
- logger.warn("Server 模块未能与 Netty 模块建立连接,故不能发送消息集合");
- return false;
- }
- return sendWebMessagesListener.sendMessagesToTcp(message);
+ return tcpMediator.sendMsgToNetty(message);
}
void setKyServerCenterHandler(KyServerCenterHandler kyServerCenterHandler) {
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/bean/ServerWebMessageHandler.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/bean/ServerWebMessageHandler.java
index eb09c59..772c3d2 100644
--- a/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/bean/ServerWebMessageHandler.java
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/bean/ServerWebMessageHandler.java
@@ -14,6 +14,8 @@
import cc.bitky.clustermanage.server.message.web.WebMsgDeployEmployeeCardNumber;
import cc.bitky.clustermanage.server.message.web.WebMsgDeployEmployeeDepartment;
import cc.bitky.clustermanage.server.message.web.WebMsgDeployEmployeeName;
+import cc.bitky.clustermanage.server.message.web.WebMsgDeployRemainChargeTimes;
+import cc.bitky.clustermanage.web.bean.QueueDevice;
import cc.bitky.clustermanage.web.bean.QueueInfo;
@Service
@@ -94,62 +96,72 @@ public boolean saveCardNumber(String[] freeCards, CardType card) {
/**
* 从数据库中获取并更新设备的信息
*
- * @param groupId 设备组 ID
- * @param deviceId 设备 ID
- * @param name 是否更新姓名
- * @param department 是否更新部门
- * @param cardNumber 是否更新卡号
- * @param maxGroupId 若更新多个设备组,可指定更新设备组的 ID 范围为: 1 - maxgroupId
+ * @param groupId 设备组 ID
+ * @param deviceId 设备 ID
+ * @param queueDevice 需要部署的设备信息
+ * @param maxGroupId 若更新多个设备组,可指定更新设备组的 ID 范围为: 1 - maxGroupId
* @return 更新是否成功
*/
- public boolean obtainDeployDeviceMsg(int groupId, int deviceId, boolean name, boolean department, boolean cardNumber, int maxGroupId) {
+ public boolean obtainDeployDeviceMsg(int groupId, int deviceId, QueueDevice queueDevice, int maxGroupId) {
if (groupId == 255 || groupId == 0) {
if (maxGroupId == 0)
maxGroupId = kyDbPresenter.obtainDeviceGroupCount();
if (maxGroupId == 0) return false;
for (int i = 1; i <= maxGroupId; i++) {
- getDeviceInfo(i, deviceId).forEach(device -> deployEmployeeMsg(name, department, cardNumber, device));
+ getDeviceInfo(i, deviceId).forEach(device -> deployEmployeeMsg(queueDevice, device));
}
} else getDeviceInfo(groupId, deviceId)
- .forEach(device -> deployEmployeeMsg(name, department, cardNumber, device));
+ .forEach(device -> deployEmployeeMsg(queueDevice, device));
return true;
}
/**
* 部署员工的姓名,单位,卡号
*
- * @param name 员工的姓名
- * @param department 员工的部门
- * @param cardNumber 员工的卡号
- * @param device 员工对应的设备
+ * @param device 员工对应的设备
+ * @param queueDevice 需要部署的设备信息
*/
- private void deployEmployeeMsg(boolean name, boolean department, boolean cardNumber, Device device) {
+ private void deployEmployeeMsg(QueueDevice queueDevice, Device device) {
+ boolean name = queueDevice.isPostName();
+ boolean department = queueDevice.isPostDepartment();
+ boolean cardNumber = queueDevice.isPostCardNumber();
+ boolean remainChargeTime = queueDevice.isPostRemainChargeTime();
- boolean autoInit = ServerSetting.DEPLOY_DEVICES_INIT;
+ boolean AUTO_INIT = ServerSetting.DEPLOY_DEVICES_INIT;
if (device == null) return;
+ //部署卡号
if (cardNumber && device.getCardNumber() != null)
kyServerCenterHandler.sendMsgTrafficControl(new WebMsgDeployEmployeeCardNumber(device.getGroupId(), device.getDeviceId(), device.getCardNumber()));
- else if (cardNumber && autoInit)
+ else if (cardNumber && AUTO_INIT)
kyServerCenterHandler.sendMsgTrafficControl(new WebMsgDeployEmployeeCardNumber(device.getGroupId(), device.getDeviceId(), ServerSetting.DEFAULT_EMPLOYEE_CARD_NUMBER));
+ //部署剩余充电次数
+ if (remainChargeTime) {
+ int remainTimes = device.getRemainChargeTime();
+ remainTimes = remainTimes > 0 ? remainTimes : 0;
+ remainTimes = remainTimes <= 100 ? remainTimes : 100;
+ kyServerCenterHandler.sendMsgTrafficControl(new WebMsgDeployRemainChargeTimes(device.getGroupId(), device.getDeviceId(), remainTimes));
+ }
+ //部署姓名和单位
if (!(name || department)) return;
Employee employee = kyDbPresenter.obtainEmployeeByEmployeeObjectId(device.getEmployeeObjectId());
if (employee != null) {
if (name && employee.getName() != null)
kyServerCenterHandler.sendMsgTrafficControl(new WebMsgDeployEmployeeName(device.getGroupId(), device.getDeviceId(), employee.getName()));
- else if (name && autoInit)
+ else if (name && AUTO_INIT)
kyServerCenterHandler.sendMsgTrafficControl(new WebMsgDeployEmployeeName(device.getGroupId(), device.getDeviceId(), ServerSetting.DEFAULT_EMPLOYEE_NAME));
+
if (department && employee.getDepartment() != null)
kyServerCenterHandler.sendMsgTrafficControl(new WebMsgDeployEmployeeDepartment(device.getGroupId(), device.getDeviceId(), employee.getDepartment()));
- else if (department && autoInit)
+ else if (department && AUTO_INIT)
kyServerCenterHandler.sendMsgTrafficControl(new WebMsgDeployEmployeeDepartment(device.getGroupId(), device.getDeviceId(), ServerSetting.DEFAULT_EMPLOYEE_DEPARTMENT));
- } else if (autoInit) {
+ } else if (AUTO_INIT) {
if (name)
kyServerCenterHandler.sendMsgTrafficControl(new WebMsgDeployEmployeeName(device.getGroupId(), device.getDeviceId(), ServerSetting.DEFAULT_EMPLOYEE_NAME));
if (department)
@@ -159,6 +171,5 @@ else if (department && autoInit)
public QueueInfo obtainQueueFrame() {
return kyServerCenterHandler.obtainQueueFrame();
-
}
}
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/message/ChargeStatus.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/message/ChargeStatus.java
new file mode 100644
index 0000000..8fc2ef9
--- /dev/null
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/message/ChargeStatus.java
@@ -0,0 +1,44 @@
+package cc.bitky.clustermanage.server.message;
+
+public interface ChargeStatus {
+
+ /**
+ * 未初始化
+ */
+ int UNINIT = 0;
+
+ /**
+ * 使用中
+ */
+ int USING = 1;
+
+ /**
+ * 充电中
+ */
+ int CHARGING = 2;
+
+ /**
+ * 已充满
+ */
+ int FULL = 3;
+
+ /**
+ * 通信故障
+ */
+ int TRAFFIC_ERROR = 4;
+
+ /**
+ * 充电故障
+ */
+ int CHARGE_ERROR = 5;
+
+ /**
+ * 矿灯未挂好
+ */
+ int HUNG_ERROR = 6;
+
+ /**
+ * 多种故障
+ */
+ int CRASH = 50;
+}
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/schedule/SendingMsgRepo.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/schedule/SendingMsgRepo.java
index df69f3c..f3fa813 100644
--- a/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/schedule/SendingMsgRepo.java
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/server/schedule/SendingMsgRepo.java
@@ -3,8 +3,8 @@
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingDeque;
import cc.bitky.clustermanage.server.message.send.SendableMsg;
@@ -14,7 +14,7 @@
@Repository
public class SendingMsgRepo {
private final List channelPipelines = new ArrayList<>();
- private final HashMap MsgHashMap = new HashMap<>(65536);
+ private final ConcurrentHashMap MsgHashMap = new ConcurrentHashMap<>(65536);
private final HashedWheelTimer hashedWheelTimer = new HashedWheelTimer();
private final LinkedBlockingDeque linkedBlockingDeque = new LinkedBlockingDeque<>(655360);
@@ -22,7 +22,7 @@ public List getChannelPipelines() {
return channelPipelines;
}
- public HashMap getMsgHashMap() {
+ public ConcurrentHashMap getMsgHashMap() {
return MsgHashMap;
}
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/TcpMediator.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/TcpMediator.java
new file mode 100644
index 0000000..67c1e45
--- /dev/null
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/TcpMediator.java
@@ -0,0 +1,77 @@
+package cc.bitky.clustermanage.tcp;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+import cc.bitky.clustermanage.server.bean.ServerTcpMessageHandler;
+import cc.bitky.clustermanage.server.message.base.BaseTcpResponseMsg;
+import cc.bitky.clustermanage.server.message.base.IMessage;
+import cc.bitky.clustermanage.server.message.send.SendableMsg;
+import cc.bitky.clustermanage.server.message.tcp.TcpMsgResponseStatus;
+import cc.bitky.clustermanage.server.schedule.SendingMsgRepo;
+import cc.bitky.clustermanage.tcp.server.MsgToCanParser;
+import io.netty.channel.ChannelPipeline;
+
+/**
+ * Netty 模块和上层服务器的中介者
+ */
+@Service
+public class TcpMediator {
+
+ private Logger logger = LoggerFactory.getLogger(getClass());
+ private ServerTcpMessageHandler serverTcpMessageHandler;
+ private MsgToCanParser msgToCanParser;
+
+ public void setMsgToCanParser(MsgToCanParser msgToCanParser) {
+ this.msgToCanParser = msgToCanParser;
+ }
+
+
+ public SendingMsgRepo getSendingMsgRepo() {
+ return serverTcpMessageHandler.getSendingMsgRepo();
+ }
+
+ public void writeCanToTcp(SendableMsg sendableMsg) {
+ List channelPipelines = getSendingMsgRepo().getChannelPipelines();
+ if (channelPipelines.size() == 0) return;
+ channelPipelines.forEach(pipe -> pipe.writeAndFlush(sendableMsg));
+ }
+
+ /**
+ * 直接将 Message 发送至 Netty 的处理通道
+ *
+ * @param message 普通消息 Message
+ * @return 是否发送成功
+ */
+ public boolean sendMsgToNetty(IMessage message) {
+ if (getSendingMsgRepo().getChannelPipelines().size() > 0) {
+ msgToCanParser.write(message);
+ return true;
+ }
+ logger.warn("没有可用的 TCP 连接,故该信息无法发送");
+ return false;
+ }
+
+ public void setServerTcpMessageHandler(ServerTcpMessageHandler serverTcpMessageHandler) {
+ this.serverTcpMessageHandler = serverTcpMessageHandler;
+ }
+
+ public void handleTcpResponseMsg(BaseTcpResponseMsg msg) {
+ serverTcpMessageHandler.handleTcpResponseMsg(msg);
+ }
+
+ public void handleResDeviceStatus(TcpMsgResponseStatus msg) {
+ serverTcpMessageHandler.handleResDeviceStatus(msg);
+ }
+
+ public void handleTcpInitMsg(IMessage msg) {
+ serverTcpMessageHandler.handleTcpInitMsg(msg);
+ }
+
+ public void handleTcpMsg() {
+ serverTcpMessageHandler.handleTcpMsg();
+ }
+}
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/WebMsgOutBoundHandler.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/MsgToCanParser.java
similarity index 87%
rename from clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/WebMsgOutBoundHandler.java
rename to clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/MsgToCanParser.java
index 7975f68..4a03679 100644
--- a/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/WebMsgOutBoundHandler.java
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/MsgToCanParser.java
@@ -1,4 +1,4 @@
-package cc.bitky.clustermanage.tcp.server.channelhandler;
+package cc.bitky.clustermanage.tcp.server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -19,24 +19,27 @@
import cc.bitky.clustermanage.server.message.web.WebMsgInitMarchConfirmCardResponse;
import cc.bitky.clustermanage.server.message.web.WebMsgObtainDeviceStatus;
import cc.bitky.clustermanage.server.message.web.WebMsgOperateBoxUnlock;
+import cc.bitky.clustermanage.tcp.TcpMediator;
import cc.bitky.clustermanage.tcp.util.TcpMsgBuilder;
-import io.netty.channel.ChannelHandler;
+/**
+ * 服务器 Message 消息解析为 TCP 通道的 CAN 帧
+ */
@Service
-@ChannelHandler.Sharable
-public class WebMsgOutBoundHandler {
+public class MsgToCanParser {
private final TcpMsgBuilder tcpMsgBuilder;
- private final QueuingOutBoundHandler queuingOutBoundHandler;
+ private final PolicyCanTransmitter policyCanTransmitter;
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
- public WebMsgOutBoundHandler(TcpMsgBuilder tcpMsgBuilder, QueuingOutBoundHandler queuingOutBoundHandler) {
+ public MsgToCanParser(TcpMsgBuilder tcpMsgBuilder, PolicyCanTransmitter policyCanTransmitter, TcpMediator tcpMediator) {
this.tcpMsgBuilder = tcpMsgBuilder;
- this.queuingOutBoundHandler = queuingOutBoundHandler;
+ this.policyCanTransmitter = policyCanTransmitter;
+ tcpMediator.setMsgToCanParser(this);
}
- void write(IMessage message) {
+ public void write(IMessage message) {
logger.info("Netty 通道获取 Message「" + message.getGroupId() + ", " + message.getDeviceId() + ", " + message.getMsgId() + "」");
if (message.getMsgId() == MsgType.SERVER_SEND_SPECIAL) {
@@ -49,7 +52,7 @@ void write(IMessage message) {
for (int k = 1; k <= msgSpecial.getMaxGroupId(); k++) {
baseMsgSpecial.setDeviceId(j);
baseMsgSpecial.setGroupId(k);
- unpackComplexMsgToTcp( baseMsgSpecial, msgSpecial.isUrgent(), msgSpecial.isResponsive());
+ unpackComplexMsgToTcp(baseMsgSpecial, msgSpecial.isUrgent(), msgSpecial.isResponsive());
}
}
} else {
@@ -59,10 +62,10 @@ void write(IMessage message) {
}
}
} else {
- unpackComplexMsgToTcp( baseMsgSpecial, msgSpecial.isUrgent(), msgSpecial.isResponsive());
+ unpackComplexMsgToTcp(baseMsgSpecial, msgSpecial.isUrgent(), msgSpecial.isResponsive());
}
} else {
- unpackComplexMsgToTcp( message, false, true);
+ unpackComplexMsgToTcp(message, false, true);
}
}
@@ -71,7 +74,7 @@ void write(IMessage message) {
*
* @param message 信息 bean
*/
- private void unpackComplexMsgToTcp( IMessage message, boolean urgent, boolean responsive) {
+ private void unpackComplexMsgToTcp(IMessage message, boolean urgent, boolean responsive) {
switch (message.getMsgId()) {
case MsgType.SERVER_SET_EMPLOYEE_DEPARTMENT_1:
byte[] bytesDepartment = buildByMessage(message);
@@ -79,8 +82,8 @@ private void unpackComplexMsgToTcp( IMessage message, boolean urgent, boolean re
byte[] bytesD2 = new byte[13];
System.arraycopy(bytesDepartment, 0, bytesD1, 0, 13);
System.arraycopy(bytesDepartment, 13, bytesD2, 0, 13);
- deployWriteTcpSpecial( bytesD1, urgent, responsive);
- deployWriteTcpSpecial( bytesD2, urgent, responsive);
+ deployWriteTcpSpecial(bytesD1, urgent, responsive);
+ deployWriteTcpSpecial(bytesD2, urgent, responsive);
return;
case MsgType.SERVER_SET_FREE_CARD_NUMBER:
@@ -90,7 +93,7 @@ private void unpackComplexMsgToTcp( IMessage message, boolean urgent, boolean re
byte[] bytesF = new byte[13];
System.arraycopy(bytesFree, 13 * i, bytesF, 0, 13);
bytesF[0] += 8;
- deployWriteTcpSpecial( bytesF, urgent, responsive);
+ deployWriteTcpSpecial(bytesF, urgent, responsive);
}
return;
}
@@ -99,7 +102,6 @@ private void unpackComplexMsgToTcp( IMessage message, boolean urgent, boolean re
/**
* 「特殊的的」将 byte[] 转化为 SendableMsg 并传入下一级写出通道
- *
*/
private void deployWriteTcpSpecial(byte[] bytes, boolean urgent, boolean responsive) {
if (bytes == null || bytes.length == 0) {
@@ -109,7 +111,7 @@ private void deployWriteTcpSpecial(byte[] bytes, boolean urgent, boolean respons
SendableMsg sendableMsg = new SendableMsg(bytes);
sendableMsg.setUrgent(urgent);
sendableMsg.setResponsive(responsive);
- queuingOutBoundHandler.write(sendableMsg);
+ policyCanTransmitter.write(sendableMsg);
}
private byte[] buildByMessage(IMessage message) {
@@ -161,6 +163,7 @@ private byte[] buildByMessage(IMessage message) {
WebMsgInitClearDeviceStatus clearDeviceStatus = (WebMsgInitClearDeviceStatus) message;
logger.info("生成帧:清除设备的初始化状态");
return tcpMsgBuilder.buildClearDeviceStatus(clearDeviceStatus);
+
default:
logger.info("未匹配功能位「" + message.getMsgId() + "」,无法生成 CAN 帧");
break;
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/QueuingOutBoundHandler.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/PolicyCanTransmitter.java
similarity index 63%
rename from clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/QueuingOutBoundHandler.java
rename to clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/PolicyCanTransmitter.java
index fb61ce0..e308297 100644
--- a/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/QueuingOutBoundHandler.java
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/PolicyCanTransmitter.java
@@ -1,37 +1,35 @@
-package cc.bitky.clustermanage.tcp.server.channelhandler;
+package cc.bitky.clustermanage.tcp.server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import cc.bitky.clustermanage.global.ServerSetting;
-import cc.bitky.clustermanage.server.bean.ServerTcpMessageHandler;
import cc.bitky.clustermanage.server.message.send.SendableMsg;
import cc.bitky.clustermanage.server.message.tcp.TcpMsgResponseStatus;
import cc.bitky.clustermanage.server.schedule.MsgKey;
-import io.netty.channel.ChannelHandler;
+import cc.bitky.clustermanage.tcp.TcpMediator;
import io.netty.util.HashedWheelTimer;
+/**
+ * 包含检错重发策略的 CAN 帧发送器
+ */
@Service
-@ChannelHandler.Sharable
-public class QueuingOutBoundHandler {
- private ServerChannelInitializer serverChannelInitializer;
+public class PolicyCanTransmitter {
+ private final TcpMediator tcpMediator;
private ScheduledExecutorService scheduledExecutorService;
-
private Logger logger = LoggerFactory.getLogger(getClass());
- void setServerChannelInitializer(ServerChannelInitializer serverChannelInitializer) {
- this.serverChannelInitializer = serverChannelInitializer;
- }
-
- private ServerTcpMessageHandler getServerTcpMessageHandler() {
- return serverChannelInitializer.getServerTcpMessageHandler();
+ @Autowired
+ public PolicyCanTransmitter(TcpMediator tcpMediator) {
+ this.tcpMediator = tcpMediator;
}
void write(SendableMsg message) {
@@ -47,14 +45,14 @@ private void initTimer() {
if (scheduledExecutorService == null) {
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleWithFixedDelay(() -> {
- if (!getLinkedBlockingDeque().isEmpty()) {
- SendableMsg message = getLinkedBlockingDeque().poll();
- getMsgHashMap().put(message.getMsgKey(), message.getBytes());
- serverChannelInitializer.writeToTcp(message);
- if (message.isResponsive())
- setWheelTask(message);
- }
- }, 0, ServerSetting.FRAME_SEND_INTERVAL, TimeUnit.MILLISECONDS);
+ if (!getLinkedBlockingDeque().isEmpty()) {
+ SendableMsg message = getLinkedBlockingDeque().poll();
+ getMsgHashMap().put(message.getMsgKey(), message.getBytes());
+ tcpMediator.writeCanToTcp(message);
+ if (message.isResponsive())
+ setWheelTask(message);
+ }
+ }, 0, ServerSetting.FRAME_SEND_INTERVAL, TimeUnit.MILLISECONDS);
}
}
@@ -66,10 +64,10 @@ private void setWheelTask(SendableMsg message) {
if (getMsgHashMap().get(msgKey) != null) {
logger.info("时间轮「3」:出错");
message.increaseSendTimes();
- if (message.getSendTimes() >= 3) {
+ if (message.getSendTimes() >= ServerSetting.AUTO_REPEAT_REQUEST_TIMES) {
getMsgHashMap().remove(msgKey);
logger.info("时间轮「4」:记录");
- getServerTcpMessageHandler().handleResDeviceStatus(
+ tcpMediator.handleResDeviceStatus(
new TcpMsgResponseStatus(msgKey.getGroupId(), msgKey.getDeviceId(), 5, TcpMsgResponseStatus.ResSource.SERVER));
} else {
logger.info("时间轮「4」:重新设置");
@@ -85,14 +83,14 @@ private void setWheelTask(SendableMsg message) {
}
private HashedWheelTimer getHashedWheelTimer() {
- return getServerTcpMessageHandler().getSendingMsgRepo().getHashedWheelTimer();
+ return tcpMediator.getSendingMsgRepo().getHashedWheelTimer();
}
- private HashMap getMsgHashMap() {
- return getServerTcpMessageHandler().getSendingMsgRepo().getMsgHashMap();
+ private ConcurrentHashMap getMsgHashMap() {
+ return tcpMediator.getSendingMsgRepo().getMsgHashMap();
}
private LinkedBlockingDeque getLinkedBlockingDeque() {
- return getServerTcpMessageHandler().getSendingMsgRepo().getLinkedBlockingDeque();
+ return tcpMediator.getSendingMsgRepo().getLinkedBlockingDeque();
}
}
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/ConfigInBoundHandler.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/ConfigHandler.java
similarity index 67%
rename from clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/ConfigInBoundHandler.java
rename to clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/ConfigHandler.java
index 46fc24f..6d26d93 100644
--- a/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/ConfigInBoundHandler.java
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/ConfigHandler.java
@@ -2,10 +2,12 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
+import cc.bitky.clustermanage.tcp.TcpMediator;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
@@ -13,20 +15,21 @@
@Service
@ChannelHandler.Sharable
-public class ConfigInBoundHandler extends ChannelInboundHandlerAdapter {
- private ServerChannelInitializer serverChannelInitializer;
- private Logger logger = LoggerFactory.getLogger(ConfigInBoundHandler.class);
+public class ConfigHandler extends ChannelInboundHandlerAdapter {
+ private final TcpMediator tcpMediator;
+ private Logger logger = LoggerFactory.getLogger(ConfigHandler.class);
private int i = 0;
- void setServerChannelInitializer(ServerChannelInitializer serverChannelInitializer) {
- this.serverChannelInitializer = serverChannelInitializer;
+ @Autowired
+ public ConfigHandler(TcpMediator tcpMediator) {
+ this.tcpMediator = tcpMediator;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
logger.info("通道重置");
- List channelPipelines = serverChannelInitializer.getServerTcpMessageHandler().getSendingMsgRepo().getChannelPipelines();
+ List channelPipelines = tcpMediator.getSendingMsgRepo().getChannelPipelines();
channelPipelines.add(ctx.pipeline());
channelPipelines.removeIf(channel -> {
i++;
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/ParsedMessageInBoundHandler.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/ParsedMessageInBoundHandler.java
index 834f612..f8feabe 100644
--- a/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/ParsedMessageInBoundHandler.java
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/ParsedMessageInBoundHandler.java
@@ -1,11 +1,12 @@
package cc.bitky.clustermanage.tcp.server.channelhandler;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-import cc.bitky.clustermanage.server.bean.ServerTcpMessageHandler;
import cc.bitky.clustermanage.server.message.base.BaseTcpResponseMsg;
import cc.bitky.clustermanage.server.message.base.IMessage;
import cc.bitky.clustermanage.server.message.tcp.TcpMsgResponseStatus;
+import cc.bitky.clustermanage.tcp.TcpMediator;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
@@ -13,14 +14,12 @@
@Service
@ChannelHandler.Sharable
public class ParsedMessageInBoundHandler extends SimpleChannelInboundHandler {
- private ServerChannelInitializer serverChannelInitializer;
- void setServerChannelInitializer(ServerChannelInitializer serverChannelInitializer) {
- this.serverChannelInitializer = serverChannelInitializer;
- }
+ private final TcpMediator tcpMediator;
- private ServerTcpMessageHandler getServerTcpMessageHandler() {
- return serverChannelInitializer.getServerTcpMessageHandler();
+ @Autowired
+ public ParsedMessageInBoundHandler(TcpMediator tcpMediator) {
+ this.tcpMediator = tcpMediator;
}
@Override
@@ -31,17 +30,17 @@ protected void channelRead0(ChannelHandlerContext ctx, IMessage msg) {
//将常规回复帧信息传入「常规回复信息处理方法」
if (msg.getMsgId() > 0x40 && msg.getMsgId() <= 0x4F) {
- getServerTcpMessageHandler().handleTcpResponseMsg((BaseTcpResponseMsg) msg);
+ tcpMediator.handleTcpResponseMsg((BaseTcpResponseMsg) msg);
return;
}
if (msg.getMsgId() >= ((byte) 0x80) && msg.getMsgId() <= ((byte) 0x8F)) {
- getServerTcpMessageHandler().handleTcpResponseMsg((BaseTcpResponseMsg) msg);
+ tcpMediator.handleTcpResponseMsg((BaseTcpResponseMsg) msg);
return;
}
if (msg.getMsgId() == 0x40) {
- getServerTcpMessageHandler().handleResDeviceStatus((TcpMsgResponseStatus) msg);
+ tcpMediator.handleResDeviceStatus((TcpMsgResponseStatus) msg);
return;
}
@@ -49,11 +48,11 @@ protected void channelRead0(ChannelHandlerContext ctx, IMessage msg) {
byte a0 = (byte) 0xA0;
byte af = (byte) 0xAF;
if (msg.getMsgId() >= a0 && msg.getMsgId() <= af) {
- getServerTcpMessageHandler().handleTcpInitMsg(msg);
+ tcpMediator.handleTcpInitMsg(msg);
return;
}
//将其余功能帧信息传入「功能信息处理方法」
- getServerTcpMessageHandler().handleTcpMsg();
+ tcpMediator.handleTcpMsg();
}
}
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/ServerChannelInitializer.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/ServerChannelInitializer.java
index d05ae7c..e2e2c1f 100644
--- a/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/ServerChannelInitializer.java
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/server/channelhandler/ServerChannelInitializer.java
@@ -3,71 +3,37 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-import java.util.List;
-
-import cc.bitky.clustermanage.server.bean.ServerTcpMessageHandler;
-import cc.bitky.clustermanage.server.message.send.SendableMsg;
import io.netty.channel.ChannelInitializer;
-import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
@Service
public class ServerChannelInitializer extends ChannelInitializer {
- private final ConfigInBoundHandler configInBoundHandler;
+ private final ConfigHandler configHandler;
private final CanFrameChannelInboundHandler canFrameChannelInboundHandler;
private final ParsedMessageInBoundHandler parsedMessageInBoundHandler;
- private final WebMsgOutBoundHandler webMsgOutBoundHandler;
private final SendingOutBoundHandler sendingOutBoundHandler;
- private final ServerTcpMessageHandler serverTcpMessageHandler;
@Autowired
- public ServerChannelInitializer(ServerTcpMessageHandler serverTcpMessageHandler,
- ConfigInBoundHandler configInBoundHandler,
+ public ServerChannelInitializer(ConfigHandler configHandler,
CanFrameChannelInboundHandler canFrameChannelInboundHandler,
ParsedMessageInBoundHandler parsedMessageInBoundHandler,
- WebMsgOutBoundHandler webMsgOutBoundHandler,
- QueuingOutBoundHandler queuingOutBoundHandler,
SendingOutBoundHandler sendingOutBoundHandler) {
- this.serverTcpMessageHandler = serverTcpMessageHandler;
- this.configInBoundHandler = configInBoundHandler;
+ this.configHandler = configHandler;
this.canFrameChannelInboundHandler = canFrameChannelInboundHandler;
this.parsedMessageInBoundHandler = parsedMessageInBoundHandler;
- this.webMsgOutBoundHandler = webMsgOutBoundHandler;
this.sendingOutBoundHandler = sendingOutBoundHandler;
-
- queuingOutBoundHandler.setServerChannelInitializer(this);
- parsedMessageInBoundHandler.setServerChannelInitializer(this);
- configInBoundHandler.setServerChannelInitializer(this);
- }
-
- ServerTcpMessageHandler getServerTcpMessageHandler() {
- return serverTcpMessageHandler;
}
- void writeToTcp(SendableMsg sendableMsg) {
- List channelPipelines = getServerTcpMessageHandler().getSendingMsgRepo().getChannelPipelines();
- if (channelPipelines.size() == 0) return;
- channelPipelines.forEach(pipe -> pipe.writeAndFlush(sendableMsg));
- }
@Override
protected void initChannel(NioSocketChannel ch) {
ch.pipeline().addLast(new LoggingHandler("kyOutlineLogger", LogLevel.INFO));
- ch.pipeline().addLast(configInBoundHandler);
+ ch.pipeline().addLast(configHandler);
ch.pipeline().addLast(canFrameChannelInboundHandler);
ch.pipeline().addLast(parsedMessageInBoundHandler);
ch.pipeline().addLast(sendingOutBoundHandler);
-
- getServerTcpMessageHandler().setSendWebMessagesListener(iMessages -> {
- if (getServerTcpMessageHandler().getSendingMsgRepo().getChannelPipelines().size() > 0) {
- webMsgOutBoundHandler.write(iMessages);
- return true;
- }
- return false;
- }
- );
}
}
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/util/TcpMsgBuilder.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/util/TcpMsgBuilder.java
index 5ff1387..56ade99 100644
--- a/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/util/TcpMsgBuilder.java
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/tcp/util/TcpMsgBuilder.java
@@ -18,7 +18,7 @@
@Component
public class TcpMsgBuilder {
- private Charset charset_GB2312 = Charset.forName("EUC-CN");
+ private Charset charset_GB2312 = Charset.forName("EUC-CN");
public static String byteArrayToString(byte[] cards) {
StringBuilder builder = new StringBuilder();
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/web/OperateRestController.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/web/OperateRestController.java
index 6dece74..aaf367a 100644
--- a/clustermanage-server/src/main/java/cc/bitky/clustermanage/web/OperateRestController.java
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/web/OperateRestController.java
@@ -12,6 +12,7 @@
import cc.bitky.clustermanage.server.message.CardType;
import cc.bitky.clustermanage.server.message.web.WebMsgInitClearDeviceStatus;
import cc.bitky.clustermanage.server.message.web.WebMsgOperateBoxUnlock;
+import cc.bitky.clustermanage.web.bean.QueueDevice;
@RestController
@RequestMapping(value = "/operate")
@@ -32,6 +33,7 @@ public OperateRestController(ServerWebMessageHandler serverWebMessageHandler) {
* @param name 是否更新姓名
* @param department 是否更新部门
* @param cardnumber 是否更新卡号
+ * @param remainchargetime 是否更新剩余充电次数
* @param maxgroupid 若更新多个设备组,可指定更新设备组的 ID 范围为: 1 - maxgroupId
* @return 更新是否成功
*/
@@ -41,8 +43,9 @@ public String updateDevices(@PathVariable int groupId,
@RequestParam(required = false) boolean name,
@RequestParam(required = false) boolean department,
@RequestParam(required = false) boolean cardnumber,
+ @RequestParam(required = false) boolean remainchargetime,
@RequestParam(defaultValue = "0") int maxgroupid) {
- if (serverWebMessageHandler.obtainDeployDeviceMsg(groupId, deviceId, name, department, cardnumber, maxgroupid))
+ if (serverWebMessageHandler.obtainDeployDeviceMsg(groupId, deviceId, new QueueDevice(name, department, cardnumber, remainchargetime), maxgroupid))
return "success";
else return "error";
}
diff --git a/clustermanage-server/src/main/java/cc/bitky/clustermanage/web/bean/QueueDevice.java b/clustermanage-server/src/main/java/cc/bitky/clustermanage/web/bean/QueueDevice.java
new file mode 100644
index 0000000..1a295a8
--- /dev/null
+++ b/clustermanage-server/src/main/java/cc/bitky/clustermanage/web/bean/QueueDevice.java
@@ -0,0 +1,64 @@
+package cc.bitky.clustermanage.web.bean;
+
+/**
+ * 选择是否部署设备中的信息
+ */
+public class QueueDevice {
+
+ /**
+ * 部署姓名
+ */
+ private boolean postName;
+ /**
+ * 部署单位
+ */
+ private boolean postDepartment;
+ /**
+ * 部署卡号
+ */
+ private boolean postCardNumber;
+ /**
+ * 部署剩余充电次数
+ */
+ private boolean postRemainChargeTime;
+
+ public QueueDevice(boolean postName, boolean postDepartment, boolean postCardNumber, boolean postRemainChargeTime) {
+ this.postName = postName;
+ this.postDepartment = postDepartment;
+ this.postCardNumber = postCardNumber;
+ this.postRemainChargeTime = postRemainChargeTime;
+ }
+
+
+ public boolean isPostName() {
+ return postName;
+ }
+
+ public void setPostName(boolean postName) {
+ this.postName = postName;
+ }
+
+ public boolean isPostDepartment() {
+ return postDepartment;
+ }
+
+ public void setPostDepartment(boolean postDepartment) {
+ this.postDepartment = postDepartment;
+ }
+
+ public boolean isPostCardNumber() {
+ return postCardNumber;
+ }
+
+ public void setPostCardNumber(boolean postCardNumber) {
+ this.postCardNumber = postCardNumber;
+ }
+
+ public boolean isPostRemainChargeTime() {
+ return postRemainChargeTime;
+ }
+
+ public void setPostRemainChargeTime(boolean postRemainChargeTime) {
+ this.postRemainChargeTime = postRemainChargeTime;
+ }
+}
diff --git a/hardware/SingleDeviceTestNET/.gitignore b/hardware/SingleDeviceTestNET/.gitignore
new file mode 100644
index 0000000..cc49c60
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/.gitignore
@@ -0,0 +1,275 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+*.vcxproj.filters
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+project.fragment.lock.json
+artifacts/
+**/Properties/launchSettings.json
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/
\ No newline at end of file
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTest.sln b/hardware/SingleDeviceTestNET/SingleDeviceTest.sln
new file mode 100644
index 0000000..ee87fdc
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTest.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SingleDeviceTestNET", "SingleDeviceTestNET\SingleDeviceTestNET.csproj", "{5E0C4B0F-13FF-47E3-B951-A2457DF0BC25}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {5E0C4B0F-13FF-47E3-B951-A2457DF0BC25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5E0C4B0F-13FF-47E3-B951-A2457DF0BC25}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5E0C4B0F-13FF-47E3-B951-A2457DF0BC25}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5E0C4B0F-13FF-47E3-B951-A2457DF0BC25}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/App.config b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/App.config
new file mode 100644
index 0000000..72a71af
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Form1.Designer.cs b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Form1.Designer.cs
new file mode 100644
index 0000000..990ad70
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Form1.Designer.cs
@@ -0,0 +1,600 @@
+namespace SocketServer
+{
+ partial class FormSocketServer
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows 窗体设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要修改
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent()
+ {
+ this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.groupBox8 = new System.Windows.Forms.GroupBox();
+ this.btnClearControlText = new System.Windows.Forms.Button();
+ this.btnClearCommunicateText = new System.Windows.Forms.Button();
+ this.groupBox7 = new System.Windows.Forms.GroupBox();
+ this.label3 = new System.Windows.Forms.Label();
+ this.label1 = new System.Windows.Forms.Label();
+ this.comboBaudrate = new System.Windows.Forms.ComboBox();
+ this.comboPortName = new System.Windows.Forms.ComboBox();
+ this.btnSerialPortOpenClose = new System.Windows.Forms.Button();
+ this.groupBox5 = new System.Windows.Forms.GroupBox();
+ this.label4 = new System.Windows.Forms.Label();
+ this.label2 = new System.Windows.Forms.Label();
+ this.labelServerStartOrEnd = new System.Windows.Forms.Label();
+ this.MessageIPAndPort = new System.Windows.Forms.Label();
+ this.groupBox6 = new System.Windows.Forms.GroupBox();
+ this.lstControlText = new System.Windows.Forms.ListBox();
+ this.lstServerCommunicationText = new System.Windows.Forms.ListBox();
+ this.groupBox2 = new System.Windows.Forms.GroupBox();
+ this.btnUpdateDeviceId = new System.Windows.Forms.Button();
+ this.LabelUpdateDeviceId = new System.Windows.Forms.Label();
+ this.labelUpdateChargeStatus = new System.Windows.Forms.Label();
+ this.btnUpdateChargeStatus = new System.Windows.Forms.Button();
+ this.labelUpdateUnLock = new System.Windows.Forms.Label();
+ this.btnUpdateUnLock = new System.Windows.Forms.Button();
+ this.labelUpdateName = new System.Windows.Forms.Label();
+ this.btnUpdateName = new System.Windows.Forms.Button();
+ this.labelUpdateDepartment = new System.Windows.Forms.Label();
+ this.btnUpdateDepartment = new System.Windows.Forms.Button();
+ this.labelUpdateCardNumber = new System.Windows.Forms.Label();
+ this.btnUpdateCardNumber = new System.Windows.Forms.Button();
+ this.labelUpdateFreeCard = new System.Windows.Forms.Label();
+ this.btnUpdateFreeCard = new System.Windows.Forms.Button();
+ this.labelUpdateDepartment2 = new System.Windows.Forms.Label();
+ this.btnUpdateDepartment2 = new System.Windows.Forms.Button();
+ this.labelRemainTimes = new System.Windows.Forms.Label();
+ this.btnRemainTimes = new System.Windows.Forms.Button();
+ this.labelRemainTimes2 = new System.Windows.Forms.Label();
+ this.btnRemainTimes2 = new System.Windows.Forms.Button();
+ this.groupBox1.SuspendLayout();
+ this.groupBox8.SuspendLayout();
+ this.groupBox7.SuspendLayout();
+ this.groupBox5.SuspendLayout();
+ this.groupBox6.SuspendLayout();
+ this.groupBox2.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // groupBox1
+ //
+ this.groupBox1.Controls.Add(this.groupBox8);
+ this.groupBox1.Controls.Add(this.groupBox7);
+ this.groupBox1.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.groupBox1.Location = new System.Drawing.Point(12, 12);
+ this.groupBox1.Name = "groupBox1";
+ this.groupBox1.Size = new System.Drawing.Size(224, 398);
+ this.groupBox1.TabIndex = 2;
+ this.groupBox1.TabStop = false;
+ this.groupBox1.Text = "功能区";
+ //
+ // groupBox8
+ //
+ this.groupBox8.Controls.Add(this.btnClearControlText);
+ this.groupBox8.Controls.Add(this.btnClearCommunicateText);
+ this.groupBox8.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.groupBox8.Location = new System.Drawing.Point(6, 172);
+ this.groupBox8.Name = "groupBox8";
+ this.groupBox8.Size = new System.Drawing.Size(209, 112);
+ this.groupBox8.TabIndex = 4;
+ this.groupBox8.TabStop = false;
+ this.groupBox8.Text = "信息清空";
+ //
+ // btnClearControlText
+ //
+ this.btnClearControlText.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnClearControlText.Location = new System.Drawing.Point(82, 66);
+ this.btnClearControlText.Name = "btnClearControlText";
+ this.btnClearControlText.Size = new System.Drawing.Size(110, 35);
+ this.btnClearControlText.TabIndex = 1;
+ this.btnClearControlText.Text = "清空控制信息";
+ this.btnClearControlText.UseVisualStyleBackColor = true;
+ this.btnClearControlText.Click += new System.EventHandler(this.btnClearControlText_Click);
+ //
+ // btnClearCommunicateText
+ //
+ this.btnClearCommunicateText.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnClearCommunicateText.Location = new System.Drawing.Point(82, 25);
+ this.btnClearCommunicateText.Name = "btnClearCommunicateText";
+ this.btnClearCommunicateText.Size = new System.Drawing.Size(110, 35);
+ this.btnClearCommunicateText.TabIndex = 2;
+ this.btnClearCommunicateText.Text = "清空通信信息";
+ this.btnClearCommunicateText.UseVisualStyleBackColor = true;
+ this.btnClearCommunicateText.Click += new System.EventHandler(this.btnClearText_Click);
+ //
+ // groupBox7
+ //
+ this.groupBox7.Controls.Add(this.label3);
+ this.groupBox7.Controls.Add(this.label1);
+ this.groupBox7.Controls.Add(this.comboBaudrate);
+ this.groupBox7.Controls.Add(this.comboPortName);
+ this.groupBox7.Controls.Add(this.btnSerialPortOpenClose);
+ this.groupBox7.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.groupBox7.Location = new System.Drawing.Point(6, 26);
+ this.groupBox7.Name = "groupBox7";
+ this.groupBox7.Size = new System.Drawing.Size(209, 140);
+ this.groupBox7.TabIndex = 4;
+ this.groupBox7.TabStop = false;
+ this.groupBox7.Text = "串口控制";
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.label3.Location = new System.Drawing.Point(5, 64);
+ this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(69, 20);
+ this.label3.TabIndex = 8;
+ this.label3.Text = "波特率:";
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.label1.Location = new System.Drawing.Point(5, 28);
+ this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(69, 20);
+ this.label1.TabIndex = 7;
+ this.label1.Text = "串口名:";
+ //
+ // comboBaudrate
+ //
+ this.comboBaudrate.BackColor = System.Drawing.Color.White;
+ this.comboBaudrate.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.comboBaudrate.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
+ this.comboBaudrate.FormattingEnabled = true;
+ this.comboBaudrate.Items.AddRange(new object[] {
+ "2400",
+ "4800",
+ "9600",
+ "19200",
+ "38400",
+ "57600",
+ "115200"});
+ this.comboBaudrate.Location = new System.Drawing.Point(82, 61);
+ this.comboBaudrate.Margin = new System.Windows.Forms.Padding(4);
+ this.comboBaudrate.Name = "comboBaudrate";
+ this.comboBaudrate.Size = new System.Drawing.Size(110, 28);
+ this.comboBaudrate.TabIndex = 6;
+ //
+ // comboPortName
+ //
+ this.comboPortName.BackColor = System.Drawing.Color.White;
+ this.comboPortName.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.comboPortName.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
+ this.comboPortName.FormattingEnabled = true;
+ this.comboPortName.Location = new System.Drawing.Point(82, 25);
+ this.comboPortName.Margin = new System.Windows.Forms.Padding(4);
+ this.comboPortName.Name = "comboPortName";
+ this.comboPortName.Size = new System.Drawing.Size(110, 28);
+ this.comboPortName.TabIndex = 5;
+ //
+ // btnSerialPortOpenClose
+ //
+ this.btnSerialPortOpenClose.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnSerialPortOpenClose.Location = new System.Drawing.Point(95, 99);
+ this.btnSerialPortOpenClose.Name = "btnSerialPortOpenClose";
+ this.btnSerialPortOpenClose.Size = new System.Drawing.Size(97, 35);
+ this.btnSerialPortOpenClose.TabIndex = 1;
+ this.btnSerialPortOpenClose.Text = "打开串口";
+ this.btnSerialPortOpenClose.UseVisualStyleBackColor = true;
+ this.btnSerialPortOpenClose.Click += new System.EventHandler(this.buttonOpenClose_Click);
+ //
+ // groupBox5
+ //
+ this.groupBox5.Controls.Add(this.label4);
+ this.groupBox5.Controls.Add(this.label2);
+ this.groupBox5.Controls.Add(this.labelServerStartOrEnd);
+ this.groupBox5.Controls.Add(this.MessageIPAndPort);
+ this.groupBox5.Location = new System.Drawing.Point(12, 313);
+ this.groupBox5.Name = "groupBox5";
+ this.groupBox5.Size = new System.Drawing.Size(215, 90);
+ this.groupBox5.TabIndex = 4;
+ this.groupBox5.TabStop = false;
+ this.groupBox5.Text = "信息";
+ //
+ // label4
+ //
+ this.label4.AutoSize = true;
+ this.label4.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.label4.Location = new System.Drawing.Point(6, 23);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(84, 20);
+ this.label4.TabIndex = 3;
+ this.label4.Text = "服务状态:";
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.label2.Location = new System.Drawing.Point(8, 53);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(69, 20);
+ this.label2.TabIndex = 1;
+ this.label2.Text = "客户端:";
+ //
+ // labelServerStartOrEnd
+ //
+ this.labelServerStartOrEnd.AutoSize = true;
+ this.labelServerStartOrEnd.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.labelServerStartOrEnd.Location = new System.Drawing.Point(96, 23);
+ this.labelServerStartOrEnd.Name = "labelServerStartOrEnd";
+ this.labelServerStartOrEnd.Size = new System.Drawing.Size(84, 20);
+ this.labelServerStartOrEnd.TabIndex = 2;
+ this.labelServerStartOrEnd.Text = "服务未开启";
+ //
+ // MessageIPAndPort
+ //
+ this.MessageIPAndPort.AutoSize = true;
+ this.MessageIPAndPort.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.MessageIPAndPort.Location = new System.Drawing.Point(96, 53);
+ this.MessageIPAndPort.Name = "MessageIPAndPort";
+ this.MessageIPAndPort.Size = new System.Drawing.Size(84, 20);
+ this.MessageIPAndPort.TabIndex = 0;
+ this.MessageIPAndPort.Text = "无状态信息";
+ //
+ // groupBox6
+ //
+ this.groupBox6.Controls.Add(this.lstControlText);
+ this.groupBox6.Location = new System.Drawing.Point(12, 416);
+ this.groupBox6.Name = "groupBox6";
+ this.groupBox6.Size = new System.Drawing.Size(345, 125);
+ this.groupBox6.TabIndex = 4;
+ this.groupBox6.TabStop = false;
+ this.groupBox6.Text = "控制信息";
+ //
+ // lstControlText
+ //
+ this.lstControlText.FormattingEnabled = true;
+ this.lstControlText.HorizontalScrollbar = true;
+ this.lstControlText.ItemHeight = 20;
+ this.lstControlText.Location = new System.Drawing.Point(6, 26);
+ this.lstControlText.Name = "lstControlText";
+ this.lstControlText.Size = new System.Drawing.Size(333, 124);
+ this.lstControlText.TabIndex = 0;
+ //
+ // lstServerCommunicationText
+ //
+ this.lstServerCommunicationText.FormattingEnabled = true;
+ this.lstServerCommunicationText.HorizontalScrollbar = true;
+ this.lstServerCommunicationText.ItemHeight = 20;
+ this.lstServerCommunicationText.Location = new System.Drawing.Point(6, 26);
+ this.lstServerCommunicationText.Name = "lstServerCommunicationText";
+ this.lstServerCommunicationText.Size = new System.Drawing.Size(365, 624);
+ this.lstServerCommunicationText.TabIndex = 0;
+ //
+ // groupBox2
+ //
+ this.groupBox2.Controls.Add(this.lstServerCommunicationText);
+ this.groupBox2.Location = new System.Drawing.Point(443, 12);
+ this.groupBox2.Name = "groupBox2";
+ this.groupBox2.Size = new System.Drawing.Size(377, 529);
+ this.groupBox2.TabIndex = 3;
+ this.groupBox2.TabStop = false;
+ this.groupBox2.Text = "通信信息";
+ //
+ // btnUpdateDeviceId
+ //
+ this.btnUpdateDeviceId.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnUpdateDeviceId.Location = new System.Drawing.Point(242, 26);
+ this.btnUpdateDeviceId.Name = "btnUpdateDeviceId";
+ this.btnUpdateDeviceId.Size = new System.Drawing.Size(115, 33);
+ this.btnUpdateDeviceId.TabIndex = 1;
+ this.btnUpdateDeviceId.Text = "更换柜号";
+ this.btnUpdateDeviceId.UseVisualStyleBackColor = true;
+ this.btnUpdateDeviceId.Click += new System.EventHandler(this.btnUpdateDeviceId_Click);
+ //
+ // LabelUpdateDeviceId
+ //
+ this.LabelUpdateDeviceId.AutoSize = true;
+ this.LabelUpdateDeviceId.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.LabelUpdateDeviceId.Location = new System.Drawing.Point(363, 32);
+ this.LabelUpdateDeviceId.Name = "LabelUpdateDeviceId";
+ this.LabelUpdateDeviceId.Size = new System.Drawing.Size(33, 20);
+ this.LabelUpdateDeviceId.TabIndex = 2;
+ this.LabelUpdateDeviceId.Text = " ";
+ //
+ // labelUpdateChargeStatus
+ //
+ this.labelUpdateChargeStatus.AutoSize = true;
+ this.labelUpdateChargeStatus.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.labelUpdateChargeStatus.Location = new System.Drawing.Point(363, 383);
+ this.labelUpdateChargeStatus.Name = "labelUpdateChargeStatus";
+ this.labelUpdateChargeStatus.Size = new System.Drawing.Size(33, 20);
+ this.labelUpdateChargeStatus.TabIndex = 2;
+ this.labelUpdateChargeStatus.Text = " ";
+ //
+ // btnUpdateChargeStatus
+ //
+ this.btnUpdateChargeStatus.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnUpdateChargeStatus.Location = new System.Drawing.Point(242, 377);
+ this.btnUpdateChargeStatus.Name = "btnUpdateChargeStatus";
+ this.btnUpdateChargeStatus.Size = new System.Drawing.Size(115, 33);
+ this.btnUpdateChargeStatus.TabIndex = 1;
+ this.btnUpdateChargeStatus.Text = "获取充电状态";
+ this.btnUpdateChargeStatus.UseVisualStyleBackColor = true;
+ this.btnUpdateChargeStatus.Click += new System.EventHandler(this.btnUpdateChargeStatus_Click);
+ //
+ // labelUpdateUnLock
+ //
+ this.labelUpdateUnLock.AutoSize = true;
+ this.labelUpdateUnLock.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.labelUpdateUnLock.Location = new System.Drawing.Point(363, 344);
+ this.labelUpdateUnLock.Name = "labelUpdateUnLock";
+ this.labelUpdateUnLock.Size = new System.Drawing.Size(33, 20);
+ this.labelUpdateUnLock.TabIndex = 2;
+ this.labelUpdateUnLock.Text = " ";
+ //
+ // btnUpdateUnLock
+ //
+ this.btnUpdateUnLock.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnUpdateUnLock.Location = new System.Drawing.Point(242, 338);
+ this.btnUpdateUnLock.Name = "btnUpdateUnLock";
+ this.btnUpdateUnLock.Size = new System.Drawing.Size(115, 33);
+ this.btnUpdateUnLock.TabIndex = 1;
+ this.btnUpdateUnLock.Text = "远程开锁";
+ this.btnUpdateUnLock.UseVisualStyleBackColor = true;
+ this.btnUpdateUnLock.Click += new System.EventHandler(this.btnUpdateUnLock_Click);
+ //
+ // labelUpdateName
+ //
+ this.labelUpdateName.AutoSize = true;
+ this.labelUpdateName.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.labelUpdateName.Location = new System.Drawing.Point(363, 71);
+ this.labelUpdateName.Name = "labelUpdateName";
+ this.labelUpdateName.Size = new System.Drawing.Size(33, 20);
+ this.labelUpdateName.TabIndex = 2;
+ this.labelUpdateName.Text = " ";
+ //
+ // btnUpdateName
+ //
+ this.btnUpdateName.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnUpdateName.Location = new System.Drawing.Point(242, 65);
+ this.btnUpdateName.Name = "btnUpdateName";
+ this.btnUpdateName.Size = new System.Drawing.Size(115, 33);
+ this.btnUpdateName.TabIndex = 1;
+ this.btnUpdateName.Text = "更新姓名";
+ this.btnUpdateName.UseVisualStyleBackColor = true;
+ this.btnUpdateName.Click += new System.EventHandler(this.btnUpdateName_Click);
+ //
+ // labelUpdateDepartment
+ //
+ this.labelUpdateDepartment.AutoSize = true;
+ this.labelUpdateDepartment.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.labelUpdateDepartment.Location = new System.Drawing.Point(363, 110);
+ this.labelUpdateDepartment.Name = "labelUpdateDepartment";
+ this.labelUpdateDepartment.Size = new System.Drawing.Size(33, 20);
+ this.labelUpdateDepartment.TabIndex = 2;
+ this.labelUpdateDepartment.Text = " ";
+ //
+ // btnUpdateDepartment
+ //
+ this.btnUpdateDepartment.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnUpdateDepartment.Location = new System.Drawing.Point(242, 104);
+ this.btnUpdateDepartment.Name = "btnUpdateDepartment";
+ this.btnUpdateDepartment.Size = new System.Drawing.Size(115, 33);
+ this.btnUpdateDepartment.TabIndex = 1;
+ this.btnUpdateDepartment.Text = "更新单位1";
+ this.btnUpdateDepartment.UseVisualStyleBackColor = true;
+ this.btnUpdateDepartment.Click += new System.EventHandler(this.btnUpdateDepartment_Click);
+ //
+ // labelUpdateCardNumber
+ //
+ this.labelUpdateCardNumber.AutoSize = true;
+ this.labelUpdateCardNumber.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.labelUpdateCardNumber.Location = new System.Drawing.Point(363, 188);
+ this.labelUpdateCardNumber.Name = "labelUpdateCardNumber";
+ this.labelUpdateCardNumber.Size = new System.Drawing.Size(33, 20);
+ this.labelUpdateCardNumber.TabIndex = 2;
+ this.labelUpdateCardNumber.Text = " ";
+ //
+ // btnUpdateCardNumber
+ //
+ this.btnUpdateCardNumber.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnUpdateCardNumber.Location = new System.Drawing.Point(242, 182);
+ this.btnUpdateCardNumber.Name = "btnUpdateCardNumber";
+ this.btnUpdateCardNumber.Size = new System.Drawing.Size(115, 33);
+ this.btnUpdateCardNumber.TabIndex = 1;
+ this.btnUpdateCardNumber.Text = "更新卡号";
+ this.btnUpdateCardNumber.UseVisualStyleBackColor = true;
+ this.btnUpdateCardNumber.Click += new System.EventHandler(this.btnUpdateCardNumber_Click);
+ //
+ // labelUpdateFreeCard
+ //
+ this.labelUpdateFreeCard.AutoSize = true;
+ this.labelUpdateFreeCard.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.labelUpdateFreeCard.Location = new System.Drawing.Point(363, 227);
+ this.labelUpdateFreeCard.Name = "labelUpdateFreeCard";
+ this.labelUpdateFreeCard.Size = new System.Drawing.Size(33, 20);
+ this.labelUpdateFreeCard.TabIndex = 2;
+ this.labelUpdateFreeCard.Text = " ";
+ //
+ // btnUpdateFreeCard
+ //
+ this.btnUpdateFreeCard.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnUpdateFreeCard.Location = new System.Drawing.Point(242, 221);
+ this.btnUpdateFreeCard.Name = "btnUpdateFreeCard";
+ this.btnUpdateFreeCard.Size = new System.Drawing.Size(115, 33);
+ this.btnUpdateFreeCard.TabIndex = 1;
+ this.btnUpdateFreeCard.Text = "更新万能卡号";
+ this.btnUpdateFreeCard.UseVisualStyleBackColor = true;
+ this.btnUpdateFreeCard.Click += new System.EventHandler(this.btnUpdateFreeCard_Click);
+ //
+ // labelUpdateDepartment2
+ //
+ this.labelUpdateDepartment2.AutoSize = true;
+ this.labelUpdateDepartment2.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.labelUpdateDepartment2.Location = new System.Drawing.Point(363, 149);
+ this.labelUpdateDepartment2.Name = "labelUpdateDepartment2";
+ this.labelUpdateDepartment2.Size = new System.Drawing.Size(33, 20);
+ this.labelUpdateDepartment2.TabIndex = 2;
+ this.labelUpdateDepartment2.Text = " ";
+ //
+ // btnUpdateDepartment2
+ //
+ this.btnUpdateDepartment2.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnUpdateDepartment2.Location = new System.Drawing.Point(242, 143);
+ this.btnUpdateDepartment2.Name = "btnUpdateDepartment2";
+ this.btnUpdateDepartment2.Size = new System.Drawing.Size(115, 33);
+ this.btnUpdateDepartment2.TabIndex = 1;
+ this.btnUpdateDepartment2.Text = "更新单位2";
+ this.btnUpdateDepartment2.UseVisualStyleBackColor = true;
+ this.btnUpdateDepartment2.Click += new System.EventHandler(this.btnUpdateDepartment2_Click);
+ //
+ // labelRemainTimes
+ //
+ this.labelRemainTimes.AutoSize = true;
+ this.labelRemainTimes.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.labelRemainTimes.Location = new System.Drawing.Point(363, 266);
+ this.labelRemainTimes.Name = "labelRemainTimes";
+ this.labelRemainTimes.Size = new System.Drawing.Size(33, 20);
+ this.labelRemainTimes.TabIndex = 2;
+ this.labelRemainTimes.Text = " ";
+ //
+ // btnRemainTimes
+ //
+ this.btnRemainTimes.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnRemainTimes.Location = new System.Drawing.Point(242, 260);
+ this.btnRemainTimes.Name = "btnRemainTimes";
+ this.btnRemainTimes.Size = new System.Drawing.Size(115, 33);
+ this.btnRemainTimes.TabIndex = 1;
+ this.btnRemainTimes.Text = "充电次数17";
+ this.btnRemainTimes.UseVisualStyleBackColor = true;
+ this.btnRemainTimes.Click += new System.EventHandler(this.btnRemainTimes_Click);
+ //
+ // labelRemainTimes2
+ //
+ this.labelRemainTimes2.AutoSize = true;
+ this.labelRemainTimes2.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.labelRemainTimes2.Location = new System.Drawing.Point(363, 305);
+ this.labelRemainTimes2.Name = "labelRemainTimes2";
+ this.labelRemainTimes2.Size = new System.Drawing.Size(33, 20);
+ this.labelRemainTimes2.TabIndex = 2;
+ this.labelRemainTimes2.Text = " ";
+ //
+ // btnRemainTimes2
+ //
+ this.btnRemainTimes2.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.btnRemainTimes2.Location = new System.Drawing.Point(242, 299);
+ this.btnRemainTimes2.Name = "btnRemainTimes2";
+ this.btnRemainTimes2.Size = new System.Drawing.Size(115, 33);
+ this.btnRemainTimes2.TabIndex = 1;
+ this.btnRemainTimes2.Text = "充电次数88";
+ this.btnRemainTimes2.UseVisualStyleBackColor = true;
+ this.btnRemainTimes2.Click += new System.EventHandler(this.btnRemainTimes2_Click);
+ //
+ // FormSocketServer
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+ this.AutoSize = true;
+ this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ this.ClientSize = new System.Drawing.Size(832, 553);
+ this.Controls.Add(this.groupBox6);
+ this.Controls.Add(this.btnUpdateUnLock);
+ this.Controls.Add(this.groupBox5);
+ this.Controls.Add(this.labelUpdateUnLock);
+ this.Controls.Add(this.btnUpdateName);
+ this.Controls.Add(this.labelUpdateName);
+ this.Controls.Add(this.btnRemainTimes2);
+ this.Controls.Add(this.labelRemainTimes2);
+ this.Controls.Add(this.btnRemainTimes);
+ this.Controls.Add(this.labelRemainTimes);
+ this.Controls.Add(this.btnUpdateFreeCard);
+ this.Controls.Add(this.labelUpdateFreeCard);
+ this.Controls.Add(this.btnUpdateCardNumber);
+ this.Controls.Add(this.labelUpdateCardNumber);
+ this.Controls.Add(this.btnUpdateDepartment2);
+ this.Controls.Add(this.labelUpdateDepartment2);
+ this.Controls.Add(this.btnUpdateDepartment);
+ this.Controls.Add(this.labelUpdateDepartment);
+ this.Controls.Add(this.btnUpdateChargeStatus);
+ this.Controls.Add(this.labelUpdateChargeStatus);
+ this.Controls.Add(this.btnUpdateDeviceId);
+ this.Controls.Add(this.LabelUpdateDeviceId);
+ this.Controls.Add(this.groupBox2);
+ this.Controls.Add(this.groupBox1);
+ this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.MaximizeBox = false;
+ this.Name = "FormSocketServer";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "充电柜单板测试";
+ this.Load += new System.EventHandler(this.Form1_Load);
+ this.groupBox1.ResumeLayout(false);
+ this.groupBox8.ResumeLayout(false);
+ this.groupBox7.ResumeLayout(false);
+ this.groupBox7.PerformLayout();
+ this.groupBox5.ResumeLayout(false);
+ this.groupBox5.PerformLayout();
+ this.groupBox6.ResumeLayout(false);
+ this.groupBox2.ResumeLayout(false);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.GroupBox groupBox1;
+ private System.Windows.Forms.Label labelServerStartOrEnd;
+ private System.Windows.Forms.GroupBox groupBox5;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.Label MessageIPAndPort;
+ private System.Windows.Forms.GroupBox groupBox6;
+ private System.Windows.Forms.ListBox lstControlText;
+ private System.Windows.Forms.GroupBox groupBox7;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.ComboBox comboBaudrate;
+ private System.Windows.Forms.ComboBox comboPortName;
+ private System.Windows.Forms.Button btnSerialPortOpenClose;
+ private System.Windows.Forms.Button btnClearCommunicateText;
+ private System.Windows.Forms.ListBox lstServerCommunicationText;
+ private System.Windows.Forms.GroupBox groupBox2;
+ private System.Windows.Forms.GroupBox groupBox8;
+ private System.Windows.Forms.Button btnClearControlText;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.Button btnUpdateDeviceId;
+ private System.Windows.Forms.Label LabelUpdateDeviceId;
+ private System.Windows.Forms.Label labelUpdateChargeStatus;
+ private System.Windows.Forms.Button btnUpdateChargeStatus;
+ private System.Windows.Forms.Label labelUpdateUnLock;
+ private System.Windows.Forms.Button btnUpdateUnLock;
+ private System.Windows.Forms.Label labelUpdateName;
+ private System.Windows.Forms.Button btnUpdateName;
+ private System.Windows.Forms.Label labelUpdateDepartment;
+ private System.Windows.Forms.Button btnUpdateDepartment;
+ private System.Windows.Forms.Label labelUpdateCardNumber;
+ private System.Windows.Forms.Button btnUpdateCardNumber;
+ private System.Windows.Forms.Label labelUpdateFreeCard;
+ private System.Windows.Forms.Button btnUpdateFreeCard;
+ private System.Windows.Forms.Label labelUpdateDepartment2;
+ private System.Windows.Forms.Button btnUpdateDepartment2;
+ private System.Windows.Forms.Label labelRemainTimes;
+ private System.Windows.Forms.Button btnRemainTimes;
+ private System.Windows.Forms.Label labelRemainTimes2;
+ private System.Windows.Forms.Button btnRemainTimes2;
+ }
+}
+
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Form1.cs b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Form1.cs
new file mode 100644
index 0000000..5a34a1d
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Form1.cs
@@ -0,0 +1,271 @@
+using System;
+using System.Collections.Generic;
+using System.IO.Ports;
+using System.Text;
+using System.Threading;
+using System.Windows.Forms;
+
+namespace SocketServer
+{
+ public partial class FormSocketServer : Form
+ {
+ //串口设置
+ private SerialPort _comm = new SerialPort();
+
+ private readonly StringBuilder _builder = new StringBuilder(); //避免在事件处理方法中反复的创建,定义到外面。
+
+ public FormSocketServer()
+ {
+ InitializeComponent();
+ }
+
+ private void Form1_Load(object sender, EventArgs e)
+ {
+ CheckForIllegalCrossThreadCalls = false;
+ //初始化下拉串口名称列表框
+ var ports = SerialPort.GetPortNames();
+ Array.Sort(ports);
+ comboPortName.Items.AddRange(ports);
+ comboPortName.SelectedIndex = comboPortName.Items.Count > 0 ? 0 : -1;
+ comboBaudrate.SelectedIndex = comboBaudrate.Items.IndexOf("115200");
+ //初始化SerialPort对象
+ _comm.NewLine = "\r\n";
+ _comm.RtsEnable = true; //根据实际情况吧。
+
+ //添加事件注册
+ _comm.DataReceived += comm_DataReceived;
+ }
+
+ private void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
+ {
+ Thread.Sleep(10);
+ var n = _comm.BytesToRead; //先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致
+ var buf = new byte[n]; //声明一个临时数组存储当前来的串口数据
+ _comm.Read(buf, 0, n); //读取缓冲数据
+ _builder.Clear(); //清除字符串构造器的内容
+ //因为要访问ui资源,所以需要使用invoke方式同步ui。
+ Invoke((EventHandler) (delegate
+ {
+ var strings = new string[13];
+ for (int i = 0; i < buf.Length; i++)
+ {
+ var s = Convert.ToString(buf[i], 16);
+ if (s.Length == 1) s = "0" + s;
+ if (i < 13)
+ {
+ strings[i] = s;
+ }
+ _builder.Append(s + " ");
+ }
+ //追加的形式添加到文本框末端,并滚动到最后。
+ communicateMessageShow(_builder.ToString());
+
+ successReceiveFrame(strings);
+ }));
+ }
+
+ private int _countDeviceId;
+ private int _countName;
+ private int _countDepartment;
+ private int _countDepartment2;
+ private int _countCardNumber;
+ private int _countFreeCard;
+ private int _countRemainTimes;
+ private int _countRemainTimes2;
+ private int _countUnLock;
+ private int _countChargeStatus;
+
+ private void successReceiveFrame(IList strs)
+ {
+ var frameType = strs[1];
+
+ if ("45".Equals(frameType)) updateLabel(LabelUpdateDeviceId, ref _countDeviceId);
+ if ("46".Equals(frameType)) updateLabel(labelUpdateName, ref _countName);
+ if ("47".Equals(frameType)) updateLabel(labelUpdateDepartment, ref _countDepartment);
+ if ("48".Equals(frameType)) updateLabel(labelUpdateDepartment2, ref _countDepartment2);
+ if ("49".Equals(frameType)) updateLabel(labelUpdateCardNumber, ref _countCardNumber);
+ if ("80".Equals(frameType)) updateLabel(labelUpdateFreeCard, ref _countFreeCard);
+ if ("41".Equals(frameType))
+ {
+ if (_countRemainTimes <= _countRemainTimes2)
+ updateLabel(labelRemainTimes, ref _countRemainTimes);
+ else
+ updateLabel(labelRemainTimes2, ref _countRemainTimes2);
+ }
+ if ("4a".Equals(frameType)) updateLabel(labelUpdateUnLock, ref _countUnLock);
+
+ if ("40".Equals(frameType))
+ {
+ var type = strs[3];
+ if ("01".Equals(type)) updateLabel(labelUpdateChargeStatus, ref _countChargeStatus, "使用中");
+ if ("02".Equals(type)) updateLabel(labelUpdateChargeStatus, ref _countChargeStatus, "充电中");
+ if ("03".Equals(type)) updateLabel(labelUpdateChargeStatus, ref _countChargeStatus, "已充满");
+ if ("04".Equals(type)) updateLabel(labelUpdateChargeStatus, ref _countChargeStatus, "已过流");
+ if ("06".Equals(type)) updateLabel(labelUpdateChargeStatus, ref _countChargeStatus, "未放好");
+ if ("50".Equals(type)) updateLabel(labelUpdateChargeStatus, ref _countChargeStatus, "严重故障");
+ }
+ }
+
+
+ private void updateLabel(Control label, ref int value, string extra = null)
+ {
+ if (extra == null)
+ {
+ label.Text = @"成功「" + ++value + @"」";
+ }
+ else
+ {
+ label.Text = @"成功「" + ++value + @"」" +"\r\n"+ extra;
+ }
+ }
+
+ private void buttonOpenClose_Click(object sender, EventArgs e)
+ {
+ //根据当前串口对象,来判断操作
+ if (_comm.IsOpen)
+ {
+ //打开时点击,则关闭串口
+ _comm.Close();
+ labelServerStartOrEnd.Text = @"串口已关闭";
+ controlMessageShow(@"串口已关闭");
+ MessageIPAndPort.Text = @"无状态信息";
+ }
+ else
+ {
+ //关闭时点击,则设置好端口,波特率后打开
+ _comm.PortName = comboPortName.Text;
+ _comm.BaudRate = int.Parse(comboBaudrate.Text);
+ try
+ {
+ _comm.Open();
+ labelServerStartOrEnd.Text = @"串口已打开";
+ controlMessageShow(@"串口已打开");
+ MessageIPAndPort.Text = comboPortName.SelectedItem.ToString();
+ }
+ catch (Exception ex)
+ {
+ //捕获到异常信息,创建一个新的comm对象,之前的不能用了。
+ _comm = new SerialPort();
+ //现实异常信息给客户。
+ MessageBox.Show(ex.Message);
+ }
+ }
+ //设置按钮的状态
+ btnSerialPortOpenClose.Text = _comm.IsOpen ? @"关闭串口" : @"打开串口";
+ }
+
+ private void controlMessageShow(string message)
+ {
+ lstControlText.Items.Add(message);
+ lstControlText.SetSelected(lstControlText.Items.Count - 1, true);
+ }
+
+ private void communicateMessageShow(string message)
+ {
+ lstServerCommunicationText.Items.Add(message);
+ lstServerCommunicationText.SetSelected(lstServerCommunicationText.Items.Count - 1, true);
+ }
+
+ private void btnClearText_Click(object sender, EventArgs e)
+ {
+ _countDeviceId = 0;
+ _countName = 0;
+ _countDepartment = 0;
+ _countDepartment2 = 0;
+ _countCardNumber = 0;
+ _countFreeCard = 0;
+ _countRemainTimes = 0;
+ _countRemainTimes2 = 0;
+ _countUnLock = 0;
+ _countChargeStatus = 0;
+
+ lstServerCommunicationText.Items.Clear();
+ LabelUpdateDeviceId.Text = "";
+ labelUpdateName.Text = "";
+ labelUpdateDepartment.Text = "";
+ labelUpdateDepartment2.Text = "";
+ labelUpdateCardNumber.Text = "";
+ labelUpdateFreeCard.Text = "";
+ labelRemainTimes.Text = "";
+ labelRemainTimes2.Text = "";
+ labelUpdateUnLock.Text = "";
+ labelUpdateChargeStatus.Text = "";
+ }
+
+ private void btnClearControlText_Click(object sender, EventArgs e)
+ {
+ lstControlText.Items.Clear();
+ }
+
+ private void btnUpdateUnLock_Click(object sender, EventArgs e)
+ {
+ const string str = "fc 12 1a 00 00 00 00 00 00 00 00 00 b9";
+ sendFrame(str);
+ }
+
+ private void btnUpdateDeviceId_Click(object sender, EventArgs e)
+ {
+ const string str = "fc 01 15 00 12 00 00 00 00 00 00 00 3c";
+ sendFrame(str);
+ }
+
+ private void sendFrame(string str)
+ {
+ string[] strs = str.Split(' ');
+ byte[] bytes = new byte[13];
+ for (var i = 0; i < 13; i++)
+ {
+ bytes[i] = Convert.ToByte(strs[i], 16);
+ }
+ _comm.Write(bytes, 0, 13);
+ }
+
+ private void btnUpdateName_Click(object sender, EventArgs e)
+ {
+ const string str = "fc 12 16 00 d0 d5 c3 fb 00 00 00 00 71";
+ sendFrame(str);
+ }
+
+ private void btnUpdateDepartment_Click(object sender, EventArgs e)
+ {
+ const string str = "fc 12 17 00 b5 a5 ce bb 00 00 00 00 78";
+ sendFrame(str);
+ }
+
+ private void btnUpdateDepartment2_Click(object sender, EventArgs e)
+ {
+ const string str = "fc 12 18 00 00 00 00 00 00 00 00 00 3c";
+ sendFrame(str);
+ }
+
+ private void btnUpdateCardNumber_Click(object sender, EventArgs e)
+ {
+ const string str = "fc 12 19 08 01 00 00 01 5F 91 9D 55 4e";
+ sendFrame(str);
+ }
+
+ private void btnUpdateFreeCard_Click(object sender, EventArgs e)
+ {
+ const string str = "fc 12 70 08 01 00 00 01 83 40 8C B9 d4";
+ sendFrame(str);
+ }
+
+ private void btnRemainTimes_Click(object sender, EventArgs e)
+ {
+ const string str = "fc 12 11 01 11 00 00 00 00 00 00 00 67";
+ sendFrame(str);
+ }
+
+ private void btnRemainTimes2_Click(object sender, EventArgs e)
+ {
+ const string str = "fc 12 11 01 58 00 00 00 00 00 00 00 47";
+ sendFrame(str);
+ }
+
+ private void btnUpdateChargeStatus_Click(object sender, EventArgs e)
+ {
+ const string str = "fc 12 10 00 00 00 00 00 00 00 00 00 1a";
+ sendFrame(str);
+ }
+ }
+}
\ No newline at end of file
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Form1.resx b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Form1.resx
new file mode 100644
index 0000000..61bc649
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Form1.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ True
+
+
\ No newline at end of file
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Program.cs b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Program.cs
new file mode 100644
index 0000000..74f4b68
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Program.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Windows.Forms;
+
+namespace SocketServer
+{
+ static class Program
+ {
+ ///
+ /// 应用程序的主入口点。
+ ///
+ [STAThread]
+ private static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new FormSocketServer());
+ }
+ }
+}
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Properties/AssemblyInfo.cs b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..bfbcec8
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("SocketSever")]
+[assembly: AssemblyDescription("SocketSever for .net3.5")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("SocketSever")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+//将 ComVisible 设置为 false 将使此程序集中的类型
+//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("5e0c4b0f-13ff-47e3-b951-a2457df0bc25")]
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
+// 方法是按如下所示使用“*”: :
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Properties/Resources.Designer.cs b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..93c6880
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace SingleDeviceTest.Properties {
+ using System;
+
+
+ ///
+ /// 一个强类型的资源类,用于查找本地化的字符串等。
+ ///
+ // 此类是由 StronglyTypedResourceBuilder
+ // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+ // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+ // (以 /str 作为命令选项),或重新生成 VS 项目。
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// 返回此类使用的缓存的 ResourceManager 实例。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SingleDeviceTest.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// 使用此强类型资源类,为所有资源查找
+ /// 重写当前线程的 CurrentUICulture 属性。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Properties/Resources.resx b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Properties/Settings.Designer.cs b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..cc17860
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace SingleDeviceTest.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Properties/Settings.settings b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Properties/Settings.settings
new file mode 100644
index 0000000..3964565
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/SingleDeviceTestNET.csproj b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/SingleDeviceTestNET.csproj
new file mode 100644
index 0000000..0300659
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/SingleDeviceTestNET.csproj
@@ -0,0 +1,144 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {5E0C4B0F-13FF-47E3-B951-A2457DF0BC25}
+ WinExe
+ Properties
+ SingleDeviceTest
+ SingleDeviceTest
+ v4.0
+ 512
+ true
+ false
+
+ C:\Users\lml08\Desktop\SocketServer\4.5\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 2
+ 1.0.0.%2a
+ false
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ false
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ false
+
+
+ 679A5D77139F31B18BCA379843E2751A3DDAF5B0
+
+
+ SocketSeverDotnet4.5_TemporaryKey.pfx
+
+
+ true
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ Form1.cs
+
+
+
+
+
+
+
+
+
+
+ Form1.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
+
+ False
+ Microsoft .NET Framework 4.5.2 %28x86 和 x64%29
+ true
+
+
+ False
+ .NET Framework 3.5 SP1
+ false
+
+
+
+
+
\ No newline at end of file
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/message/WebMsgOperateBoxUnlock.cs b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/message/WebMsgOperateBoxUnlock.cs
new file mode 100644
index 0000000..e3b1815
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/message/WebMsgOperateBoxUnlock.cs
@@ -0,0 +1,13 @@
+using SocketServer.message.@base;
+using SocketServer.utils;
+
+namespace SocketServer.message
+{
+ public class WebMsgOperateBoxUnlock : BaseMessage
+ {
+ public WebMsgOperateBoxUnlock(int groupId, int boxId) : base(groupId, boxId)
+ {
+ setMsgId(MsgType.ServerRemoteUnlock);
+ }
+ }
+}
\ No newline at end of file
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/message/base/BaseMessage.cs b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/message/base/BaseMessage.cs
new file mode 100644
index 0000000..d27aa4d
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/message/base/BaseMessage.cs
@@ -0,0 +1,51 @@
+namespace SocketServer.message.@base
+{
+ public class BaseMessage : IMessage
+ {
+ private int _msgId = -1;
+ private int _groupId = -1;
+ private int _deviceId = -1;
+
+ protected BaseMessage(int groupId)
+ {
+ this._groupId = groupId;
+ }
+
+ protected BaseMessage(int groupId, int deviceId) : this(groupId)
+ {
+ this._deviceId = deviceId;
+ }
+
+ public int getMsgId()
+ {
+ return _msgId;
+ }
+
+ protected void setMsgId(int msgId)
+ {
+ this._msgId = msgId;
+ }
+
+ public int getGroupId()
+ {
+ return _groupId;
+ }
+
+ public void setGroupId(int groupId)
+ {
+ this._groupId = groupId;
+ }
+
+
+ public int getDeviceId()
+ {
+ return _deviceId;
+ }
+
+
+ public void setDeviceId(int deviceId)
+ {
+ this._deviceId = deviceId;
+ }
+ }
+}
\ No newline at end of file
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/message/base/IMessage.cs b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/message/base/IMessage.cs
new file mode 100644
index 0000000..c1ff5ba
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/message/base/IMessage.cs
@@ -0,0 +1,15 @@
+namespace SocketServer.message.@base
+{
+ public interface IMessage
+ {
+ int getMsgId();
+
+ int getDeviceId();
+
+ void setDeviceId(int deviceId);
+
+ int getGroupId();
+
+ void setGroupId(int groupId);
+ }
+}
\ No newline at end of file
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/utils/CanBuilder.cs b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/utils/CanBuilder.cs
new file mode 100644
index 0000000..b9904e7
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/utils/CanBuilder.cs
@@ -0,0 +1,70 @@
+using System;
+using SocketServer.message;
+using SocketServer.message.@base;
+
+namespace SocketServer.utils
+{
+ class CanBuilder
+ {
+ private static TcpMsgBuilder _tcpMsgBuilder=new TcpMsgBuilder();
+
+ public static byte[] buildByMessage(IMessage message)
+ {
+ switch (message.getMsgId())
+ {
+// case MsgType.SERVER_REQUSET_STATUS:
+// WebMsgObtainDeviceStatus obtainDeviceStatus = (WebMsgObtainDeviceStatus) message;
+// Console.WriteLine("生成帧:请求设备当前状态");
+// return tcpMsgBuilder.buildRequestDeviceStatus(obtainDeviceStatus);
+//
+// case MsgType.SERVER_SET_REMAIN_CHARGE_TIMES:
+// WebMsgDeployRemainChargeTimes remainChargeTimes = (WebMsgDeployRemainChargeTimes) message;
+// Console.WriteLine("生成帧:设置设备剩余充电次数: " + remainChargeTimes.getTimes());
+// return tcpMsgBuilder.buildRemainChargeTimes(remainChargeTimes);
+//
+// case MsgType.SERVER_SET_DEVICE_ID:
+// WebMsgDeployEmployeeDeviceId deployEmployeeDeviceId = (WebMsgDeployEmployeeDeviceId) message;
+// Console.WriteLine("生成帧:设置设备 ID: " + deployEmployeeDeviceId.getUpdatedDeviceId());
+// return tcpMsgBuilder.buildDeviceId(deployEmployeeDeviceId);
+//
+// case MsgType.SERVER_SET_EMPLOYEE_NAME:
+// WebMsgDeployEmployeeName deployEmployeeName = (WebMsgDeployEmployeeName) message;
+// Console.WriteLine("生成帧:设置员工姓名: " + deployEmployeeName.getValue());
+// return tcpMsgBuilder.buildEmployeeName(deployEmployeeName);
+//
+// case MsgType.SERVER_SET_EMPLOYEE_DEPARTMENT_1:
+// WebMsgDeployEmployeeDepartment deployEmployeeDepartment = (WebMsgDeployEmployeeDepartment) message;
+// Console.WriteLine("生成帧:设置员工单位: " + deployEmployeeDepartment.getValue());
+// return tcpMsgBuilder.buildEmployeeDepartment(deployEmployeeDepartment);
+//
+// case MsgType.SERVER_SET_EMPLOYEE_CARD_NUMBER:
+// WebMsgDeployEmployeeCardNumber deployEmployeeCardNumber = (WebMsgDeployEmployeeCardNumber) message;
+// Console.WriteLine("生成帧:设置员工卡号: " + deployEmployeeCardNumber.getCardNumber());
+// return tcpMsgBuilder.buildEmployeeCardNumber(deployEmployeeCardNumber);
+
+ case MsgType.ServerRemoteUnlock:
+ Console.WriteLine("生成帧:解锁单个设备");
+ return _tcpMsgBuilder.buildWebUnlock((WebMsgOperateBoxUnlock) message);
+
+// case MsgType.SERVER_SET_FREE_CARD_NUMBER:
+// Console.WriteLine("生成帧:设置万能卡号");
+// return tcpMsgBuilder.buildFreeCardNumber((WebMsgDeployFreeCardNumber) message);
+//
+// case MsgType.INITIALIZE_SERVER_MARCH_CONFIRM_CARD_RESPONSE:
+// WebMsgInitMarchConfirmCardResponse marchConfirmCard = (WebMsgInitMarchConfirmCardResponse) message;
+// Console.WriteLine("生成初始化帧:匹配确认卡号状态:" + marchConfirmCard.isSuccessful());
+// return tcpMsgBuilder.buildInitMarchConfirmCardSuccessful(marchConfirmCard);
+//
+// case MsgType.INITIALIZE_SERVER_CLEAR_INITIALIZE_MESSAGE:
+// WebMsgInitClearDeviceStatus clearDeviceStatus = (WebMsgInitClearDeviceStatus) message;
+// Console.WriteLine("生成帧:清除设备的初始化状态");
+// return tcpMsgBuilder.buildClearDeviceStatus(clearDeviceStatus);
+
+ default:
+ Console.WriteLine("未匹配功能位「" + message.getMsgId() + "」,无法生成 CAN 帧");
+ break;
+ }
+ return new byte[0];
+ }
+ }
+}
\ No newline at end of file
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/utils/MsgType.cs b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/utils/MsgType.cs
new file mode 100644
index 0000000..cd63b35
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/utils/MsgType.cs
@@ -0,0 +1,126 @@
+namespace SocketServer.utils
+{
+ class MsgType
+ {
+ public const byte HeartBeat = 0x01;
+
+ public const byte Error = 0x05;
+
+ /**
+ * 成组地发送消息
+ */
+ public const byte ServerSendGrouped = 0x0A;
+
+ /**
+ * 紧急发送该消息
+ */
+ public const byte ServerSendSpecial = 0x0B;
+
+
+ //-------------------服务器下发-----------------------
+
+ /**
+ * 获取充电状态
+ */
+ public const byte ServerRequsetStatus = 0x10;
+
+ /**
+ * 设置剩余充电次数
+ */
+ public const byte ServerSetRemainChargeTimes = 0x11;
+
+ /**
+ * 设置设备ID
+ */
+ public const byte ServerSetDeviceId = 0x15;
+
+ /**
+ * 设置员工姓名
+ */
+ public const byte ServerSetEmployeeName = 0x16;
+
+ /**
+ * 设置员工单位第一帧
+ */
+ public const byte ServerSetEmployeeDepartment1 = 0x17;
+
+ /**
+ * 设置员工卡号
+ */
+ public const byte ServerSetEmployeeCardNumber = 0x19;
+
+ /**
+ * 服务器远程开锁
+ */
+ public const byte ServerRemoteUnlock = 0x1A;
+
+ /**
+ * 万能卡号设置
+ */
+ public const byte ServerSetFreeCardNumber = 0x70;
+
+ //-------------------设备回复-----------------------
+
+ /**
+ * 设备回复自己的状态
+ */
+ public const byte DeviceResponseStatus = 0x40;
+
+ /**
+ * 设置剩余充电次数的回复
+ */
+ public const byte DeviceResponseRemainChargeTimes = 0x41;
+
+ /**
+ * 设置设备ID的回复
+ */
+ public const byte DeviceResponseDeviceId = 0x45;
+
+ /**
+ * 设置员工姓名的回复
+ */
+ public const byte DeviceResponseEmployeeName = 0x46;
+
+ /**
+ * 设置员工单位的回复「1」
+ */
+ public const byte DeviceResponseEmployeeDepartment1 = 0x47;
+
+ /**
+ * 设置员工单位的回复「2」
+ */
+ public const byte DeviceResponseEmployeeDepartment2 = 0x48;
+
+ /**
+ * 设置员工卡号的回复
+ */
+ public const byte DeviceResponseEmployeeCardNumber = 0x49;
+
+ /**
+ * 服务器远程开锁的回复
+ */
+ public const byte DeviceResponseRemoteUnlock = 0x4A;
+
+ /**
+ * 万能卡号设置的回复
+ */
+ public const byte DeviceResponseFreeCardNumber = (byte) 0x80;
+
+ //-------------------初始化流程信息-----------------------
+
+ /**
+ * 设备主动发送卡号,包括员工卡号和确认卡号
+ */
+ public const byte InitializeDeviceResponseCard = (byte) 0xAA;
+
+ /**
+ * 服务器匹配确认卡号回复
+ */
+ public const byte InitializeServerMarchConfirmCardResponse = (byte) 0xAB;
+
+ /**
+ * 服务器清除设备的初始化状态
+ */
+ public const byte InitializeServerClearInitializeMessage = (byte) 0xAD;
+ }
+}
\ No newline at end of file
diff --git a/hardware/SingleDeviceTestNET/SingleDeviceTestNET/utils/TcpMsgBuilder.cs b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/utils/TcpMsgBuilder.cs
new file mode 100644
index 0000000..a48e737
--- /dev/null
+++ b/hardware/SingleDeviceTestNET/SingleDeviceTestNET/utils/TcpMsgBuilder.cs
@@ -0,0 +1,272 @@
+using System;
+using System.Text;
+using SocketServer.message;
+using SocketServer.message.@base;
+
+namespace SocketServer.utils
+{
+ public class TcpMsgBuilder
+ {
+// public static string byteArrayToString(byte[] cards)
+// {
+// var builder = new StringBuilder();
+//
+// foreach (var b in cards)
+// {
+// var s =Integer.toHexString(b & 0xFF).toUpperCase();
+// if (s.Length == 1)
+// {
+// builder.Append('0').Append(s);
+// }
+// else builder.Append(s);
+// }
+// return builder.ToString();
+// }
+
+ public static byte[] stringToByteArray(string cards)
+ {
+ if (cards.Length > 16) cards = cards.Substring(0, 16);
+ if (cards.Length < 16)
+ {
+ var count = 16 - cards.Length;
+ var builder = new StringBuilder();
+ for (var i = 0; i < count; i++)
+ {
+ builder.Append("0");
+ }
+ builder.Append(cards);
+ cards = builder.ToString();
+ }
+
+ var bytes = new byte[8];
+ cards = cards.ToUpper();
+ var hexChars = cards.ToCharArray();
+ for (var i = 0; i < 8; i++)
+ {
+ var pos = i * 2;
+ bytes[i] = (byte)(charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
+ }
+ return bytes;
+ }
+
+ private static byte charToByte(char c)
+ {
+ return (byte)"0123456789ABCDEF".IndexOf(c);
+ }
+
+// /**
+// * 构建获取设备状态的 CAN 帧
+// *
+// * @param webMsgObtainDeviceStatus 获取设备状态 bean
+// * @return 获取设备状态的 CAN 帧
+// */
+// public byte[] buildRequestDeviceStatus(WebMsgObtainDeviceStatus webMsgObtainDeviceStatus)
+// {
+// return buildMsgOutline(webMsgObtainDeviceStatus);
+// }
+//
+// /**
+// * 构建剩余充电次数的 CAN 帧
+// *
+// * @param webMsgDeployRemainChargeTimes 剩余充电次数 bean
+// * @return 剩余充电次数的 CAN 帧
+// */
+// public byte[] buildRemainChargeTimes(WebMsgDeployRemainChargeTimes webMsgDeployRemainChargeTimes)
+// {
+// byte[] bytes = buildMsgOutline(webMsgDeployRemainChargeTimes);
+// bytes[0] += 1;
+// bytes[5] = (byte)webMsgDeployRemainChargeTimes.getTimes();
+// return bytes;
+// }
+//
+// /**
+// * 构建设备 ID 的CAN帧
+// *
+// * @param webMsgDeployEmployeeDeviceId 设备ID bean
+// * @return 设备ID的 CAN 帧
+// */
+// public byte[] buildDeviceId(WebMsgDeployEmployeeDeviceId webMsgDeployEmployeeDeviceId)
+// {
+// byte[] bytes = buildMsgOutline(webMsgDeployEmployeeDeviceId);
+// bytes[0] += 1;
+// bytes[5] = (byte)webMsgDeployEmployeeDeviceId.getUpdatedDeviceId();
+// return bytes;
+// }
+//
+// /**
+// * 构建员工姓名的 CAN 帧
+// *
+// * @param webMsgDeployEmployeeName 员工姓名 bean
+// * @return 员工姓名的 CAN 帧
+// */
+// public byte[] buildEmployeeName(WebMsgDeployEmployeeName webMsgDeployEmployeeName)
+// {
+// byte[] bytes = buildMsgOutline(webMsgDeployEmployeeName);
+//
+// byte[] bytesBody = webMsgDeployEmployeeName.getValue().getBytes(charset_GB2312);
+// bytes[0] += bytesBody.length > 8 ? 8 : bytesBody.length;
+// addMessageBody(bytes, bytesBody, 0);
+// return bytes;
+// }
+//
+// /**
+// * 构建员工单位的 CAN 帧
+// *
+// * @param webMsgDeployEmployeeDepartment 员工单位 bean
+// * @return 员工单位的 CAN 帧
+// */
+// public byte[] buildEmployeeDepartment(WebMsgDeployEmployeeDepartment webMsgDeployEmployeeDepartment)
+// {
+// byte[] bytes = buildMsgOutline(webMsgDeployEmployeeDepartment);
+// byte[] bytesBody = webMsgDeployEmployeeDepartment.getValue().getBytes(charset_GB2312);
+//
+// byte[] bytes2 = bytes.clone();
+// bytes2[2] += 1;
+// addMessageBody(bytes, bytesBody, 0);
+// addMessageBody(bytes2, bytesBody, 8);
+//
+// if (bytesBody.length > 8)
+// {
+// bytes[0] += 8;
+// bytes2[0] += (bytesBody.length - 8) > 8 ? 8 : (bytesBody.length - 8);
+// }
+// else
+// {
+// bytes[0] += bytesBody.length;
+// }
+//
+// byte[] bytes3 = new byte[13 * 2];
+// System.arraycopy(bytes, 0, bytes3, 0, 13);
+// System.arraycopy(bytes2, 0, bytes3, 13, 13);
+// return bytes3;
+// }
+//
+// /**
+// * 构建员工卡号的 CAN 帧
+// *
+// * @param webMsgDeployEmployeeCardNumber 员工卡号 bean
+// * @return 员工卡号的 CAN 帧
+// */
+// public byte[] buildEmployeeCardNumber(WebMsgDeployEmployeeCardNumber webMsgDeployEmployeeCardNumber)
+// {
+// byte[] bytes = buildMsgOutline(webMsgDeployEmployeeCardNumber);
+// bytes[0] += 8;
+// byte[] byteCardNum = stringToByteArray(webMsgDeployEmployeeCardNumber.getCardNumber());
+// addMessageBody(bytes, byteCardNum, 0);
+// return bytes;
+// }
+
+ /**
+ * 构建开锁用的 CAN 帧
+ *
+ * @param webMsgOperateBoxUnlock 开锁 bean
+ * @return 开锁用的 CAN 帧
+ */
+ public byte[] buildWebUnlock(WebMsgOperateBoxUnlock webMsgOperateBoxUnlock)
+ {
+ return buildMsgOutline(webMsgOperateBoxUnlock);
+ }
+
+// /**
+// * 构建万能卡号 CAN 帧
+// *
+// * @param webMsgDeployFreeCardNumber 万能卡号 bean
+// * @return 万能卡号的 CAN 帧
+// */
+// public byte[] buildFreeCardNumber(WebMsgDeployFreeCardNumber webMsgDeployFreeCardNumber)
+// {
+// string[] cards = webMsgDeployFreeCardNumber.getCardNumbers();
+// int count = cards.length < 16 ? cards.length : 16;
+// byte[] bytesSend = new byte[13 * count];
+//
+// for (int i = 0; i < count; i++)
+// {
+// byte[] bytes = buildMsgOutline(webMsgDeployFreeCardNumber);
+// bytes[2] += i;
+// addMessageBody(bytes, stringToByteArray(cards[i]), 0);
+// System.arraycopy(bytes, 0, bytesSend, 13 * i, 13);
+// }
+// return bytesSend;
+// }
+//
+// /**
+// * 「初始化」服务器匹配确认卡号成功
+// *
+// * @param marchConfirmCardSuccessful 匹配确认卡号成功 bean
+// * @return 「匹配确认卡号成功」的 CAN 帧
+// */
+// public byte[] buildInitMarchConfirmCardSuccessful(WebMsgInitMarchConfirmCardResponse marchConfirmCardSuccessful)
+// {
+// byte[] bytes = buildMsgOutline(marchConfirmCardSuccessful);
+// bytes[0] += 1;
+// bytes[5] = (byte)(marchConfirmCardSuccessful.isSuccessful() ? 1 : 0);
+// return bytes;
+// }
+//
+//
+// /**
+// * 构建清除设备初始化状态的 CAN 帧
+// *
+// * @param clearDeviceStatus 清除设备初始化状态 bean
+// * @return 清除设备初始化状态的 CAN 帧
+// */
+// public byte[] buildClearDeviceStatus(WebMsgInitClearDeviceStatus clearDeviceStatus)
+// {
+// return buildMsgOutline(clearDeviceStatus);
+// }
+
+ /**
+ * 构建 CAN 帧的轮廓,只需再填入数据位即可
+ *
+ * @param message 欲构建为 CAN 帧的 bean
+ * @return 轮廓 CAN 帧
+ */
+ private byte[] buildMsgOutline(BaseMessage message)
+ {
+ byte[] bytes = new byte[13];
+ bytes[0] = (byte)0x80;
+ bytes[2] = (byte)message.getMsgId();
+ bytes[3] = (byte)message.getDeviceId();
+ bytes[4] = (byte)message.getGroupId();
+ return bytes;
+ }
+
+ /**
+ * 在轮廓CAN帧中添加数据位
+ *
+ * @param bytes 轮廓CAN帧
+ * @param bytesBody 数据位
+ * @param offset 数据位的偏移量,offset位开始操作8个字节
+ */
+ private void addMessageBody(byte[] bytes, byte[] bytesBody, int offset)
+ {
+ int max = (bytesBody.Length - offset) > 8 ? 8 : (bytesBody.Length - offset);
+ for (int i = 0; i < max; i++)
+ {
+ bytes[i + 5] = bytesBody[i + offset];
+ }
+ }
+
+ private long byteArrayToLong(byte[] bytes)
+ {
+ long num = 0;
+ for (int i = 0; i <= 7; i++)
+ {
+ num += (bytes[i] & 0xffL) << ((7 - i) * 8);
+ }
+ return num;
+ }
+
+ private byte[] longToByteArray(long num)
+ {
+ byte[] bytes = new byte[8];
+ for (int i = 0; i <= 7; i++)
+ {
+ bytes[i] = (byte)((num >> ((7 - i) * 8)) & 0xff);
+ }
+ return bytes;
+ }
+
+
+ }
+}
\ No newline at end of file