From da3133945cb73e243431b4524621feaad4dc0951 Mon Sep 17 00:00:00 2001 From: kaizhi.wu Date: Sun, 21 Mar 2021 22:56:29 +0800 Subject: [PATCH] feat: 重构客户端 1,增加experiment的模块; 2,为client、experiment增加工厂,用于读取系统已有的模块; 3,统一命名为matrix; 4,为client增加client manager,由manager统一管理和创建client; --- src/main/java/com/example/mina/client/base/AbstractClient.java | 135 --------------------------------------------------------------------------------------------------------------------------------------- src/main/java/com/example/mina/client/base/AbstractClientFactory.java | 38 ++++++++++++++++++++++++++++++++++++++ src/main/java/com/example/mina/client/base/AbstractMatrixIoHandler.java | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/example/mina/client/base/AbstractVirtualBoxClientHandler.java | 79 ------------------------------------------------------------------------------- src/main/java/com/example/mina/client/base/BaseRequest.java | 28 ---------------------------- src/main/java/com/example/mina/client/base/BaseResponse.java | 9 --------- src/main/java/com/example/mina/client/base/BoxConnectConfig.java | 30 ------------------------------ src/main/java/com/example/mina/client/base/BoxConstants.java | 13 ------------- src/main/java/com/example/mina/client/base/ClientManager.java | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/example/mina/client/base/DownloadListener.java | 17 ----------------- src/main/java/com/example/mina/client/base/Experiment.java | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/example/mina/client/base/ExperimentFactory.java | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/example/mina/client/base/ExperimentOptions.java | 24 ++++++++++++++++++++++++ src/main/java/com/example/mina/client/base/ExperimentProgressListner.java | 21 +++++++++++++++++++++ src/main/java/com/example/mina/client/base/MatrixClient.java | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/example/mina/client/base/MatrixCommand.java | 21 +++++++++++++++++++++ src/main/java/com/example/mina/client/base/MatrixConnectConfig.java | 30 ++++++++++++++++++++++++++++++ src/main/java/com/example/mina/client/base/MatrixConstants.java | 23 +++++++++++++++++++++++ src/main/java/com/example/mina/client/base/MatrixDataProxy.java | 33 +++++++++++++++++++++++++++++++++ src/main/java/com/example/mina/client/base/MatrixResponse.java | 4 ++++ src/main/java/com/example/mina/client/base/request/ResetRequest.java | 17 ----------------- src/main/java/com/example/mina/client/base/response/ResetResponse.java | 7 ------- src/main/java/com/example/mina/client/box/aeroflex/AeroFlexClientFactory.java | 15 +++++++++++++++ src/main/java/com/example/mina/client/box/aeroflex/AeroflexClient.java | 23 ----------------------- src/main/java/com/example/mina/client/box/aeroflex/AeroflexClientHandler.java | 22 ---------------------- src/main/java/com/example/mina/client/box/aeroflex/AeroflexClientIoHandler.java | 22 ++++++++++++++++++++++ src/main/java/com/example/mina/client/box/lte3000/Lte3000Client.java | 21 --------------------- src/main/java/com/example/mina/client/box/lte3000/Lte3000ClientFactory.java | 15 +++++++++++++++ src/main/java/com/example/mina/client/box/lte3000/Lte3000ClientHandler.java | 105 --------------------------------------------------------------------------------------------------------- src/main/java/com/example/mina/client/box/lte3000/Lte3000ClientIoHandler.java | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/example/mina/client/experiment/HandoverExperiment.java | 23 +++++++++++++++++++++++ 31 files changed, 828 insertions(+), 506 deletions(-) delete mode 100644 src/main/java/com/example/mina/client/base/AbstractClient.java create mode 100644 src/main/java/com/example/mina/client/base/AbstractClientFactory.java create mode 100644 src/main/java/com/example/mina/client/base/AbstractMatrixIoHandler.java delete mode 100644 src/main/java/com/example/mina/client/base/AbstractVirtualBoxClientHandler.java delete mode 100644 src/main/java/com/example/mina/client/base/BaseRequest.java delete mode 100644 src/main/java/com/example/mina/client/base/BaseResponse.java delete mode 100644 src/main/java/com/example/mina/client/base/BoxConnectConfig.java delete mode 100644 src/main/java/com/example/mina/client/base/BoxConstants.java create mode 100644 src/main/java/com/example/mina/client/base/ClientManager.java delete mode 100644 src/main/java/com/example/mina/client/base/DownloadListener.java create mode 100644 src/main/java/com/example/mina/client/base/Experiment.java create mode 100644 src/main/java/com/example/mina/client/base/ExperimentFactory.java create mode 100644 src/main/java/com/example/mina/client/base/ExperimentOptions.java create mode 100644 src/main/java/com/example/mina/client/base/ExperimentProgressListner.java create mode 100644 src/main/java/com/example/mina/client/base/MatrixClient.java create mode 100644 src/main/java/com/example/mina/client/base/MatrixCommand.java create mode 100644 src/main/java/com/example/mina/client/base/MatrixConnectConfig.java create mode 100644 src/main/java/com/example/mina/client/base/MatrixConstants.java create mode 100644 src/main/java/com/example/mina/client/base/MatrixDataProxy.java create mode 100644 src/main/java/com/example/mina/client/base/MatrixResponse.java delete mode 100644 src/main/java/com/example/mina/client/base/request/ResetRequest.java delete mode 100644 src/main/java/com/example/mina/client/base/response/ResetResponse.java create mode 100644 src/main/java/com/example/mina/client/box/aeroflex/AeroFlexClientFactory.java delete mode 100644 src/main/java/com/example/mina/client/box/aeroflex/AeroflexClient.java delete mode 100644 src/main/java/com/example/mina/client/box/aeroflex/AeroflexClientHandler.java create mode 100644 src/main/java/com/example/mina/client/box/aeroflex/AeroflexClientIoHandler.java delete mode 100644 src/main/java/com/example/mina/client/box/lte3000/Lte3000Client.java create mode 100644 src/main/java/com/example/mina/client/box/lte3000/Lte3000ClientFactory.java delete mode 100644 src/main/java/com/example/mina/client/box/lte3000/Lte3000ClientHandler.java create mode 100644 src/main/java/com/example/mina/client/box/lte3000/Lte3000ClientIoHandler.java create mode 100644 src/main/java/com/example/mina/client/experiment/HandoverExperiment.java diff --git a/src/main/java/com/example/mina/client/base/AbstractClient.java b/src/main/java/com/example/mina/client/base/AbstractClient.java deleted file mode 100644 index 8bac343..0000000 --- a/src/main/java/com/example/mina/client/base/AbstractClient.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.example.mina.client.base; - -import lombok.extern.slf4j.Slf4j; -import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; -import org.apache.mina.core.future.ConnectFuture; -import org.apache.mina.core.service.IoConnector; -import org.apache.mina.core.session.IoSession; -import org.apache.mina.filter.codec.ProtocolCodecFilter; -import org.apache.mina.transport.socket.nio.NioSocketConnector; - -import java.net.InetSocketAddress; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - -/** - * @author dy - * @date 2021/3/10 - */ -@Slf4j -public abstract class AbstractClient { - - /** - * 客户端与设备端连接的配置信息 - */ - protected BoxConnectConfig boxConnectConfig; - - /** - * 存储客户端的请求指令的队列 - */ - protected LinkedBlockingQueue requestsPool; - - protected IoSession ioSession; - - private CommandSender sender; - - public AbstractClient(BoxConnectConfig connectConfig) { - this.boxConnectConfig = connectConfig; - this.requestsPool = new LinkedBlockingQueue<>(); - this.sender = new CommandSender(this, this.requestsPool); - } - - /** - *获取设备的类型 - */ - public String getDeviceType() { - return boxConnectConfig.getDeviceType(); - } - - /** - * 获取设备ID - */ - public String getDeviceId() { - return boxConnectConfig.getDeviceId(); - } - - /** - * 获取设备名称 - */ - public String getDeviceName() { - return boxConnectConfig.getDeviceName(); - } - - /** - * 返回客户端对响应的Handler - * @return - */ - abstract protected AbstractVirtualBoxClientHandler getIoHandler(); - - /** - * 返回该盒子的编解码器,默认为tcp的协议,如果是其它协议,可以在自类中重写改方法 - * @return - */ - protected void setFilterChain(DefaultIoFilterChainBuilder filterChainBuilder) { - filterChainBuilder.addLast("codec", new ProtocolCodecFilter(new ByteProtocolFactory())); - } - - public void start() { - //1、创建客户端IoService - IoConnector connector = new NioSocketConnector(); - //客户端链接超时时间 - connector.setConnectTimeoutMillis(30000); - //2、客户端过滤器 - setFilterChain(connector.getFilterChain()); - //3、客户端IoHandler,发生消息 - connector.setHandler(getIoHandler()); - - //连接服务端 - ConnectFuture connectFuture = connector.connect(new InetSocketAddress(boxConnectConfig.getHost(), - boxConnectConfig.getPort())); - // 等待建立连接 - connectFuture.awaitUninterruptibly(); - // 获取连接会话 - this.ioSession = connectFuture.getSession(); - this.ioSession.setAttribute(BoxConstants.SESSION_CONFIG_NAME, boxConnectConfig); - //将数据发送线程启动 - this.sender.start(); - } - - /** - * 执行指令 - * @param request - */ - public , R extends BaseResponse> R execute(Q request) { - requestsPool.offer(request); - ioSession.write(request); - - return request.execute(); - } - - /** - * 客户端启动的时候自动为每个客户端启动一个发送线程,将缓存的指令发送出去 - */ - private static class CommandSender extends Thread { - private AbstractClient client; - private LinkedBlockingQueue commands; - - public CommandSender(AbstractClient client, LinkedBlockingQueue commands ) { - this.client = client; - this.commands = commands; - } - - @Override - public void run() { - while (true) { - try { - BaseRequest command = commands.poll(5, TimeUnit.SECONDS); - - client.ioSession.write(command); - }catch (Exception e) { - log.error("error occurred when send the request to device, device: " + client.boxConnectConfig, e); - } - } - } - } -} diff --git a/src/main/java/com/example/mina/client/base/AbstractClientFactory.java b/src/main/java/com/example/mina/client/base/AbstractClientFactory.java new file mode 100644 index 0000000..6d4ce54 --- /dev/null +++ b/src/main/java/com/example/mina/client/base/AbstractClientFactory.java @@ -0,0 +1,38 @@ +package com.example.mina.client.base; + +import lombok.extern.slf4j.Slf4j; +import org.apache.mina.core.filterchain.IoFilterChain; +import org.apache.mina.filter.codec.ProtocolCodecFilter; + +@Slf4j +public abstract class AbstractClientFactory { + + protected MatrixDataProxy matrixDataProxy; + + public void setMatrixDataProxy(MatrixDataProxy matrixDataProxy) { + this.matrixDataProxy = matrixDataProxy; + } + + abstract public AbstractMatrixIoHandler getClientHandler(); + + public void buildFilterChain(IoFilterChain ioFilterChain){ + ioFilterChain.addLast("codec", new ProtocolCodecFilter(new ByteProtocolFactory())); + } + + public MatrixClient createClient(MatrixConnectConfig connectConfig){ + + + try{ + + MatrixClient client = new MatrixClient(connectConfig); + + //TODO initiate the client + buildFilterChain(client.getFilterChain()); + client.setClientHandler(getClientHandler()); + return client; + }catch (Exception e) { + log.error("Can not create the client, error: ", e); + throw new RuntimeException("create client error!"); + } + } +} diff --git a/src/main/java/com/example/mina/client/base/AbstractMatrixIoHandler.java b/src/main/java/com/example/mina/client/base/AbstractMatrixIoHandler.java new file mode 100644 index 0000000..d94f91c --- /dev/null +++ b/src/main/java/com/example/mina/client/base/AbstractMatrixIoHandler.java @@ -0,0 +1,79 @@ +package com.example.mina.client.base; + + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.apache.mina.core.buffer.IoBuffer; +import org.apache.mina.core.service.IoHandlerAdapter; +import org.apache.mina.core.session.IdleStatus; +import org.apache.mina.core.session.IoSession; + +/** + * @author dy + */ +@Data +@Slf4j +public abstract class AbstractMatrixIoHandler extends IoHandlerAdapter { + + protected MatrixDataProxy matrixDataProxy; + + public AbstractMatrixIoHandler(MatrixDataProxy matrixDataProxy) { + this.matrixDataProxy = matrixDataProxy; + } + + protected MatrixConnectConfig getConnectConfig(IoSession session) { + Object boxConnectConfig = session.getAttribute(MatrixConstants.SESSION_CONFIG_NAME); + + if( boxConnectConfig instanceof MatrixConnectConfig) { + return (MatrixConnectConfig) boxConnectConfig; + } + return null; + } + + @Override + public void exceptionCaught(IoSession session, Throwable throwable) { + } + + @Override + public void messageReceived(IoSession session, Object message) { + if (!(message instanceof IoBuffer)) { + log.error("客户端接收到的消息不为定义的响应类! message:" + message); + throw new RuntimeException("Unsupported response message"); + } + + //TODO 客户端将数据服务器的字符串数组读取出来 + byte[] response = null; + log.info("the client recieved the device response, device:{}, response is: {}", + getConnectConfig(session), response); + handleCommandResponse(response); + } + + @Override + public void messageSent(IoSession session, Object message) { + } + + @Override + public void inputClosed(IoSession session) { + } + + @Override + public void sessionClosed(IoSession session) { + } + + @Override + public void sessionCreated(IoSession session) { + + } + + @Override + public void sessionIdle(IoSession session, IdleStatus status) { + log.info("the session with box was idle, device is {}", getConnectConfig(session)); + } + + @Override + public void sessionOpened(IoSession session) { + log.info("the system has connected to device, device is {}", getConnectConfig(session)); + } + + abstract public boolean handleCommandResponse(byte[] response); +} diff --git a/src/main/java/com/example/mina/client/base/AbstractVirtualBoxClientHandler.java b/src/main/java/com/example/mina/client/base/AbstractVirtualBoxClientHandler.java deleted file mode 100644 index 1554ccd..0000000 --- a/src/main/java/com/example/mina/client/base/AbstractVirtualBoxClientHandler.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.example.mina.client.base; - - -import lombok.Data; -import lombok.extern.slf4j.Slf4j; -import org.apache.mina.core.buffer.IoBuffer; -import org.apache.mina.core.service.IoHandlerAdapter; -import org.apache.mina.core.session.IdleStatus; -import org.apache.mina.core.session.IoSession; - -/** - * @author dy - */ -@Data -@Slf4j -public abstract class AbstractVirtualBoxClientHandler extends IoHandlerAdapter { - - protected DownloadListener downloadListener; - - public AbstractVirtualBoxClientHandler(DownloadListener downloadListener) { - this.downloadListener = downloadListener; - } - - protected BoxConnectConfig getConnectConfig(IoSession session) { - Object boxConnectConfig = session.getAttribute(BoxConstants.SESSION_CONFIG_NAME); - - if( boxConnectConfig instanceof BoxConnectConfig) { - return (BoxConnectConfig) boxConnectConfig; - } - return null; - } - - @Override - public void exceptionCaught(IoSession session, Throwable throwable) { - } - - @Override - public void messageReceived(IoSession session, Object message) { - if (!(message instanceof IoBuffer)) { - log.error("客户端接收到的消息不为定义的响应类! message:" + message); - throw new RuntimeException("Unsupported response message"); - } - - //TODO 客户端将数据服务器的字符串数组读取出来 - byte[] response = null; - log.info("the client recieved the device response, device:{}, response is: {}", - getConnectConfig(session), response); - handleCommandResponse(response); - } - - @Override - public void messageSent(IoSession session, Object message) { - } - - @Override - public void inputClosed(IoSession session) { - } - - @Override - public void sessionClosed(IoSession session) { - } - - @Override - public void sessionCreated(IoSession session) { - - } - - @Override - public void sessionIdle(IoSession session, IdleStatus status) { - log.info("the session with box was idle, device is {}", getConnectConfig(session)); - } - - @Override - public void sessionOpened(IoSession session) { - log.info("the system has connected to device, device is {}", getConnectConfig(session)); - } - - abstract public boolean handleCommandResponse(byte[] response); -} diff --git a/src/main/java/com/example/mina/client/base/BaseRequest.java b/src/main/java/com/example/mina/client/base/BaseRequest.java deleted file mode 100644 index cd1ec98..0000000 --- a/src/main/java/com/example/mina/client/base/BaseRequest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.example.mina.client.base; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.experimental.SuperBuilder; - -/** - * @author dy - * @date 2021/3/12 - */ -@SuperBuilder -@Data -@AllArgsConstructor -@NoArgsConstructor -public abstract class BaseRequest { - - protected AbstractClient client; - - /** - * 指令名称 - * @return - */ - abstract public String getCommandName(); - - abstract public R execute(); - -} diff --git a/src/main/java/com/example/mina/client/base/BaseResponse.java b/src/main/java/com/example/mina/client/base/BaseResponse.java deleted file mode 100644 index 725ebcd..0000000 --- a/src/main/java/com/example/mina/client/base/BaseResponse.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.example.mina.client.base; - -import lombok.Data; - -@Data -public abstract class BaseResponse { - private String responseType; - -} diff --git a/src/main/java/com/example/mina/client/base/BoxConnectConfig.java b/src/main/java/com/example/mina/client/base/BoxConnectConfig.java deleted file mode 100644 index 8b4bea8..0000000 --- a/src/main/java/com/example/mina/client/base/BoxConnectConfig.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.example.mina.client.base; - - -import lombok.Builder; -import lombok.Data; - -import java.util.Map; - -@Data -@Builder -public class BoxConnectConfig { - - private String deviceId; - - private String deviceType; - - private String deviceName; - - private String host; - - private Integer port; - - private Integer rows; - - private Integer cols; - - private Integer maxAttenuation; - - private Map options; -} diff --git a/src/main/java/com/example/mina/client/base/BoxConstants.java b/src/main/java/com/example/mina/client/base/BoxConstants.java deleted file mode 100644 index 9a105d7..0000000 --- a/src/main/java/com/example/mina/client/base/BoxConstants.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.mina.client.base; - -public class BoxConstants { - - public static final String SESSION_CONFIG_NAME = "SESSION_CONFIG"; - - public static final String DEVICE_TYPE_AERO = "AEROFLEX"; - - public static final String DEVICE_TYPE_LTE3000 = "LTE3000"; - - public static final String COMMAND_RESET = "RESET"; - -} diff --git a/src/main/java/com/example/mina/client/base/ClientManager.java b/src/main/java/com/example/mina/client/base/ClientManager.java new file mode 100644 index 0000000..4f0f6af --- /dev/null +++ b/src/main/java/com/example/mina/client/base/ClientManager.java @@ -0,0 +1,57 @@ +package com.example.mina.client.base; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +@Component +@Slf4j +public class ClientManager { + + private Map clientFactories; + + private Map clients; + + public ClientManager() { + this.clients = Collections.emptyMap(); + } + + public void setClientFactories(Map clientFactories) { + this.clientFactories = clientFactories; + } + + public Set getSupportedMatrix() { + return this.clientFactories.keySet(); + } + + public T getClientFactory(String name) { + return this.clientFactories.get(name); + } + + public MatrixClient getOrCreateClient(MatrixConnectConfig connectConfig) { + Assert.notNull(connectConfig, "matrix connect config is null"); + Assert.hasLength(connectConfig.getDeviceId(), "deviceId can not be empty"); + + String deviceId = connectConfig.getDeviceId(); + + if(clients.containsKey(deviceId)) { + return clients.get(deviceId); + } + + String deviceType = connectConfig.getDeviceType(); + //check the device type is supported by system + T clientFactory = getClientFactory(deviceType); + if(clientFactory == null) { + log.error("the matrix type is not supported by the system! matrix type is: " + deviceType); + throw new RuntimeException("the matrix type is not supported by the system! matrix type is: " + deviceType); + } + MatrixClient client = clientFactory.createClient(connectConfig); + + clients.put(deviceId, client); + return client; + } +} diff --git a/src/main/java/com/example/mina/client/base/DownloadListener.java b/src/main/java/com/example/mina/client/base/DownloadListener.java deleted file mode 100644 index 7aebbb1..0000000 --- a/src/main/java/com/example/mina/client/base/DownloadListener.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.example.mina.client.base; - -public class DownloadListener { - - /** - * 当从设备端将数据同步到客户端的时候,将数据直接存入数据中, - * 该类会在ioHandler及其子类中被调用 - * 设置attenuation的值,并将其存储到matrix_data的数据表中 - */ - public void setAttenuation(String deviceId, int row, int col, int val) { - //TODO 实现将数据写入到数据库的逻辑 - } - - private String getCurrentThreadId() { - return Thread.currentThread().getName(); - } -} diff --git a/src/main/java/com/example/mina/client/base/Experiment.java b/src/main/java/com/example/mina/client/base/Experiment.java new file mode 100644 index 0000000..aca7e1a --- /dev/null +++ b/src/main/java/com/example/mina/client/base/Experiment.java @@ -0,0 +1,81 @@ +package com.example.mina.client.base; + +import lombok.extern.slf4j.Slf4j; + +import java.time.ZonedDateTime; + +@Slf4j +public abstract class Experiment extends Thread{ + + protected T client; + protected O options; + protected int iteratedTimes; + + //this is used for stop the task manually + private volatile boolean isRunning; + + protected ExperimentProgressListner progressListner; + + public Experiment() { + } + + public Experiment(T client, O options) { + this.client = client; + this.options = options; + this.setName(getExperimentTaskName()); + this.iteratedTimes = 0; + } + + private String getExperimentTaskName() { + return String.format("%s-%s", this.client.getDeviceType(), this.client.getDeviceName()); + } + + public void setClient(T t) { + this.client = t; + } + public void setOptions(O options) { + this.options = options; + } + public void setProgressListner(ExperimentProgressListner experimentProgressListner) { + this.progressListner = experimentProgressListner; + } + + public String getExperimentId() { + return options.getExperimentId(); + } + + abstract public String getExperimentName(); + + abstract public void schedule(); + + public void sendCommand(MatrixCommand command){ + client.sendCommand(command); + } + + public boolean isContinue() { + return iteratedTimes < options.getMaxIterCount() && + ZonedDateTime.now().isBefore(options.getFinishAt()) && + isRunning; + } + + public void start() { + + progressListner.startExperiment(getExperimentId()); + while (isContinue()) { + try{ + schedule(); + iteratedTimes++ ; + progressListner.updateProgress(getExperimentId(), iteratedTimes); + Thread.sleep(options.getPause() * 1000); + }catch (Exception e) { + log.info("thread sleep error", e); + } + } + progressListner.stopExperiment(getExperimentId()); + } + + public void finish() { + isRunning = false; + } + +} diff --git a/src/main/java/com/example/mina/client/base/ExperimentFactory.java b/src/main/java/com/example/mina/client/base/ExperimentFactory.java new file mode 100644 index 0000000..489e2fa --- /dev/null +++ b/src/main/java/com/example/mina/client/base/ExperimentFactory.java @@ -0,0 +1,62 @@ +package com.example.mina.client.base; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.CollectionUtils; + +import java.util.Map; + +@Slf4j +public abstract class ExperimentFactory < T extends Experiment> { + + private Map experiments; + + public ExperimentFactory() { + experiments = CollectionUtils.newHashMap(10); + } + + public T getExperiment(String matrixId) { + + return experiments.getOrDefault(matrixId, null); + } + + public void stopExperiment(String matrixId) { + T t = getExperiment(matrixId); + + if( t != null && t.isContinue()){ + t.finish(); + experiments.remove(matrixId); + } + } + + abstract public boolean isSupport(); + + abstract Class getClazz(); + + public ExperimentProgressListner getListner() { + return null; //TODO 生成任务进度更新监听器 + } + + public T createExperiment(MatrixClient client, ExperimentOptions options){ + + if(isSupport()) { + log.error("the experiment is not supported by the matrix! matrix id: " + client.getDeviceId()); + throw new RuntimeException("the experiment is not supported by the matrix! matrix id: " + client.getDeviceId()); + } + + Class tClass = getClazz(); + + try{ + + T t = tClass.newInstance(); + + t.setClient(client); + t.setOptions(options); + t.setProgressListner(getListner()); + return t; + }catch (Exception e) { + log.error("create a experiment task is failed, matrix id: " + client.getDeviceId()); + throw new RuntimeException("create a experiment task is failed, matrix id: " + client.getDeviceId()); + } + } + +} diff --git a/src/main/java/com/example/mina/client/base/ExperimentOptions.java b/src/main/java/com/example/mina/client/base/ExperimentOptions.java new file mode 100644 index 0000000..20d2cd5 --- /dev/null +++ b/src/main/java/com/example/mina/client/base/ExperimentOptions.java @@ -0,0 +1,24 @@ +package com.example.mina.client.base; + +import lombok.Data; + +import java.time.ZonedDateTime; + +@Data +public abstract class ExperimentOptions { + private String experimentId; + + private int startAttenuation; + + private int endAttenuation; + + private int step; + + private int pause; + + private int maxIterCount; + + private ZonedDateTime finishAt; + + abstract boolean checkOptions(); +} diff --git a/src/main/java/com/example/mina/client/base/ExperimentProgressListner.java b/src/main/java/com/example/mina/client/base/ExperimentProgressListner.java new file mode 100644 index 0000000..9dac0ab --- /dev/null +++ b/src/main/java/com/example/mina/client/base/ExperimentProgressListner.java @@ -0,0 +1,21 @@ +package com.example.mina.client.base; + + +public interface ExperimentProgressListner { + + /** + * start the experiment + */ + void startExperiment(String experimentId); + + /** + * update iteration + */ + void updateProgress(String experimentId, int iters); + + + /** + * Stop the experiment + */ + void stopExperiment(String experimentId); +} diff --git a/src/main/java/com/example/mina/client/base/MatrixClient.java b/src/main/java/com/example/mina/client/base/MatrixClient.java new file mode 100644 index 0000000..b2b16e6 --- /dev/null +++ b/src/main/java/com/example/mina/client/base/MatrixClient.java @@ -0,0 +1,175 @@ +package com.example.mina.client.base; + +import lombok.extern.slf4j.Slf4j; +import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; +import org.apache.mina.core.filterchain.IoFilterChain; +import org.apache.mina.core.future.ConnectFuture; +import org.apache.mina.core.service.IoConnector; +import org.apache.mina.core.session.IoSession; +import org.apache.mina.filter.codec.ProtocolCodecFilter; +import org.apache.mina.transport.socket.nio.NioSocketConnector; +import org.springframework.util.Assert; + +import java.net.InetSocketAddress; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +/** + * @author dy + * @date 2021/3/10 + */ +@Slf4j +public class MatrixClient { + + /** + * 客户端与设备端连接的配置信息 + */ + protected MatrixConnectConfig matrixConnectConfig; + + /** + * 存储客户端的请求指令的队列 + */ + protected LinkedBlockingQueue requestsPool; + + protected AbstractMatrixIoHandler clientHandler; + + protected IoSession ioSession; + + private CommandSender sender; + + public MatrixClient(MatrixConnectConfig connectConfig) { + this.matrixConnectConfig = connectConfig; + this.requestsPool = new LinkedBlockingQueue<>(); + this.sender = new CommandSender(this, this.requestsPool); + + this.sender.start(); + } + + /** + *获取设备的类型 + */ + public String getDeviceType() { + return matrixConnectConfig.getDeviceType(); + } + + /** + * 获取设备ID + */ + public String getDeviceId() { + return matrixConnectConfig.getDeviceId(); + } + + /** + * 获取设备名称 + */ + public String getDeviceName() { + return matrixConnectConfig.getDeviceName(); + } + + /** + * 返回客户端对响应的Handler + * @return + */ + public void setClientHandler(AbstractMatrixIoHandler clientHandler) { + this.clientHandler = clientHandler; + } + + + /** + * 返回该盒子的编解码器,默认为tcp的协议,如果是其它协议,可以在自类中重写改方法 + * @return + */ + protected void setFilterChain(DefaultIoFilterChainBuilder filterChainBuilder) { + filterChainBuilder.addLast("codec", new ProtocolCodecFilter(new ByteProtocolFactory())); + } + + public IoFilterChain getFilterChain() { + return ioSession.getFilterChain(); + } + + public void start() { + //1、创建客户端IoService + IoConnector connector = new NioSocketConnector(); + //客户端链接超时时间 + connector.setConnectTimeoutMillis(30000); + //2、客户端过滤器 +// setFilterChain(connector.getFilterChain()); + //3、客户端IoHandler,发生消息 + Assert.notNull(clientHandler, "client handler must not be null"); + connector.setHandler(clientHandler); + + //连接服务端 + ConnectFuture connectFuture = connector.connect(new InetSocketAddress(matrixConnectConfig.getHost(), + matrixConnectConfig.getPort())); + // 等待建立连接 + connectFuture.awaitUninterruptibly(); + // 获取连接会话 + this.ioSession = connectFuture.getSession(); + this.ioSession.setAttribute(MatrixConstants.SESSION_CONFIG_NAME, matrixConnectConfig); + //将数据发送线程启动 + this.sender.start(); + } + + /** + * the belows method can be overrided by its child class + */ + public void resetAttenuations() { + MatrixCommand command = MatrixCommand.builder().command(MatrixConstants.COMMAND_RESET).build(); + + sendCommand(command); + } + + public void setAttenuation(int row, int col, int attn) { + MatrixCommand command = MatrixCommand.builder().command(MatrixConstants.COMMAND_SET_ATTN) + .col(col).row(row).attn(attn).build(); + + sendCommand(command); + } + + public void setOffset(int row, int offset) { + MatrixCommand command = MatrixCommand.builder().command(MatrixConstants.COMMAND_SET_OFFSET) + .row(row).offset(offset).build(); + + sendCommand(command); + } + + /** + * 执行命令 + */ + public boolean sendCommand(MatrixCommand command) { + try{ + requestsPool.put(command); + return true; + }catch (Exception e) { + log.error("error ocurred, when put a matrix command!", e); + return false; + } + } + + /** + * 客户端启动的时候自动为每个客户端启动一个发送线程,将缓存的指令发送出去 + */ + private static class CommandSender extends Thread { + private MatrixClient client; + private LinkedBlockingQueue commands; + + public CommandSender(MatrixClient client, LinkedBlockingQueue commands ) { + this.client = client; + this.commands = commands; + this.setName(String.format("Sender-%s-%s", client.getDeviceType(), client.getDeviceName())); + } + + @Override + public void run() { + while (true) { + try { + MatrixCommand command = commands.poll(5, TimeUnit.SECONDS); + + client.ioSession.write(command); + }catch (Exception e) { + log.error("error occurred when send the request to device, device: " + client.matrixConnectConfig, e); + } + } + } + } +} diff --git a/src/main/java/com/example/mina/client/base/MatrixCommand.java b/src/main/java/com/example/mina/client/base/MatrixCommand.java new file mode 100644 index 0000000..1658897 --- /dev/null +++ b/src/main/java/com/example/mina/client/base/MatrixCommand.java @@ -0,0 +1,21 @@ +package com.example.mina.client.base; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class MatrixCommand { + + private String matrixId; + + private Integer command; + + private Integer row; + + private Integer col; + + private Integer attn; + + private Integer offset; +} diff --git a/src/main/java/com/example/mina/client/base/MatrixConnectConfig.java b/src/main/java/com/example/mina/client/base/MatrixConnectConfig.java new file mode 100644 index 0000000..c69edb1 --- /dev/null +++ b/src/main/java/com/example/mina/client/base/MatrixConnectConfig.java @@ -0,0 +1,30 @@ +package com.example.mina.client.base; + + +import lombok.Builder; +import lombok.Data; + +import java.util.Map; + +@Data +@Builder +public class MatrixConnectConfig { + + private String deviceId; + + private String deviceType; + + private String deviceName; + + private String host; + + private Integer port; + + private Integer rows; + + private Integer cols; + + private Integer maxAttenuation; + + private Map options; +} diff --git a/src/main/java/com/example/mina/client/base/MatrixConstants.java b/src/main/java/com/example/mina/client/base/MatrixConstants.java new file mode 100644 index 0000000..53e4b18 --- /dev/null +++ b/src/main/java/com/example/mina/client/base/MatrixConstants.java @@ -0,0 +1,23 @@ +package com.example.mina.client.base; + +public class MatrixConstants { + + public static final String SESSION_CONFIG_NAME = "SESSION_CONFIG"; + + public static final String MATRIX_TYPE_AERO = "AEROFLEX"; + + public static final String MATRIX_TYPE_LTE3000 = "LTE3000"; + + public static final int COMMAND_RESET = 1; + + public static final int COMMAND_SET_ATTN = 2; + + public static final int COMMAND_GET_ATTN = 3; + + public static final int COMMAND_SET_OFFSET = 4; + + public static final int COMMAND_GET_OFFSET = 5; + + public static final String EXPERIMENT_HANDOVER = "HANDOVER"; + +} diff --git a/src/main/java/com/example/mina/client/base/MatrixDataProxy.java b/src/main/java/com/example/mina/client/base/MatrixDataProxy.java new file mode 100644 index 0000000..1f50f03 --- /dev/null +++ b/src/main/java/com/example/mina/client/base/MatrixDataProxy.java @@ -0,0 +1,33 @@ +package com.example.mina.client.base; + +public class MatrixDataProxy { + + /** + * 当从设备端将数据同步到客户端的时候,将数据直接存入数据中, + * 该类会在ioHandler及其子类中被调用 + * 设置attenuation的值,并将其存储到matrix_data的数据表中 + */ + public void setAttenuation(String deviceId, int row, int col, int val) { + //TODO 实现将数据写入到数据库的逻辑 + } + + public int getAttenuation(String deviceId, int row, int col) { + return -1; + } + + public void setOffset(int row, int val) { + + } + + public int getOffset(int row) { + return -1; + } + + public void resetAttenuation() { + + } + + private String getCurrentThreadId() { + return Thread.currentThread().getName(); + } +} diff --git a/src/main/java/com/example/mina/client/base/MatrixResponse.java b/src/main/java/com/example/mina/client/base/MatrixResponse.java new file mode 100644 index 0000000..b7aef8c --- /dev/null +++ b/src/main/java/com/example/mina/client/base/MatrixResponse.java @@ -0,0 +1,4 @@ +package com.example.mina.client.base; + +public class MatrixResponse { +} diff --git a/src/main/java/com/example/mina/client/base/request/ResetRequest.java b/src/main/java/com/example/mina/client/base/request/ResetRequest.java deleted file mode 100644 index 25ec226..0000000 --- a/src/main/java/com/example/mina/client/base/request/ResetRequest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.example.mina.client.base.request; - -import com.example.mina.client.base.BaseRequest; -import com.example.mina.client.base.BoxConstants; -import com.example.mina.client.base.response.ResetResponse; - -public class ResetRequest extends BaseRequest { - @Override - public String getCommandName() { - return BoxConstants.COMMAND_RESET; - } - - @Override - public ResetResponse execute() { - return null; - } -} diff --git a/src/main/java/com/example/mina/client/base/response/ResetResponse.java b/src/main/java/com/example/mina/client/base/response/ResetResponse.java deleted file mode 100644 index e556dab..0000000 --- a/src/main/java/com/example/mina/client/base/response/ResetResponse.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.example.mina.client.base.response; - -import com.example.mina.client.base.BaseResponse; - -public class ResetResponse extends BaseResponse { - -} diff --git a/src/main/java/com/example/mina/client/box/aeroflex/AeroFlexClientFactory.java b/src/main/java/com/example/mina/client/box/aeroflex/AeroFlexClientFactory.java new file mode 100644 index 0000000..b71ab27 --- /dev/null +++ b/src/main/java/com/example/mina/client/box/aeroflex/AeroFlexClientFactory.java @@ -0,0 +1,15 @@ +package com.example.mina.client.box.aeroflex; + +import com.example.mina.client.base.AbstractClientFactory; +import com.example.mina.client.base.AbstractMatrixIoHandler; +import com.example.mina.client.base.MatrixConstants; +import org.springframework.stereotype.Component; + +@Component(MatrixConstants.MATRIX_TYPE_AERO) +public class AeroFlexClientFactory extends AbstractClientFactory { + + @Override + public AbstractMatrixIoHandler getClientHandler() { + return null; + } +} diff --git a/src/main/java/com/example/mina/client/box/aeroflex/AeroflexClient.java b/src/main/java/com/example/mina/client/box/aeroflex/AeroflexClient.java deleted file mode 100644 index 064feae..0000000 --- a/src/main/java/com/example/mina/client/box/aeroflex/AeroflexClient.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.example.mina.client.box.aeroflex; - -import com.example.mina.client.base.AbstractClient; -import com.example.mina.client.base.AbstractVirtualBoxClientHandler; -import com.example.mina.client.base.BoxConnectConfig; - -/** - * @author dy - * @date 2021/3/10 - */ -public class AeroflexClient extends AbstractClient { - - public AeroflexClient(BoxConnectConfig boxConnectConfig) { - super(boxConnectConfig); - } - - @Override - protected AbstractVirtualBoxClientHandler getIoHandler() { - return null; - } - - -} diff --git a/src/main/java/com/example/mina/client/box/aeroflex/AeroflexClientHandler.java b/src/main/java/com/example/mina/client/box/aeroflex/AeroflexClientHandler.java deleted file mode 100644 index 6771817..0000000 --- a/src/main/java/com/example/mina/client/box/aeroflex/AeroflexClientHandler.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.example.mina.client.box.aeroflex; - -import com.example.mina.client.base.AbstractVirtualBoxClientHandler; -import com.example.mina.client.base.DownloadListener; - -/** - * @author dy - * @date 2021/3/10 - */ -public class AeroflexClientHandler extends AbstractVirtualBoxClientHandler { - - public AeroflexClientHandler(DownloadListener downloadListener) { - super(downloadListener); - } - - @Override - public boolean handleCommandResponse(byte[] response) { - - return false; - } - -} diff --git a/src/main/java/com/example/mina/client/box/aeroflex/AeroflexClientIoHandler.java b/src/main/java/com/example/mina/client/box/aeroflex/AeroflexClientIoHandler.java new file mode 100644 index 0000000..9f63648 --- /dev/null +++ b/src/main/java/com/example/mina/client/box/aeroflex/AeroflexClientIoHandler.java @@ -0,0 +1,22 @@ +package com.example.mina.client.box.aeroflex; + +import com.example.mina.client.base.AbstractMatrixIoHandler; +import com.example.mina.client.base.MatrixDataProxy; + +/** + * @author dy + * @date 2021/3/10 + */ +public class AeroflexClientIoHandler extends AbstractMatrixIoHandler { + + public AeroflexClientIoHandler(MatrixDataProxy matrixDataProxy) { + super(matrixDataProxy); + } + + @Override + public boolean handleCommandResponse(byte[] response) { + + return false; + } + +} diff --git a/src/main/java/com/example/mina/client/box/lte3000/Lte3000Client.java b/src/main/java/com/example/mina/client/box/lte3000/Lte3000Client.java deleted file mode 100644 index 4633202..0000000 --- a/src/main/java/com/example/mina/client/box/lte3000/Lte3000Client.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.example.mina.client.box.lte3000; - -import com.example.mina.client.base.AbstractClient; -import com.example.mina.client.base.AbstractVirtualBoxClientHandler; -import com.example.mina.client.base.BoxConnectConfig; - -/** - * @author dy - * @date 2021/3/10 - */ -public class Lte3000Client extends AbstractClient { - public Lte3000Client(BoxConnectConfig connectConfig) { - super(connectConfig); - } - - @Override - protected AbstractVirtualBoxClientHandler getIoHandler() { - return null; - } - -} diff --git a/src/main/java/com/example/mina/client/box/lte3000/Lte3000ClientFactory.java b/src/main/java/com/example/mina/client/box/lte3000/Lte3000ClientFactory.java new file mode 100644 index 0000000..bb0eace --- /dev/null +++ b/src/main/java/com/example/mina/client/box/lte3000/Lte3000ClientFactory.java @@ -0,0 +1,15 @@ +package com.example.mina.client.box.lte3000; + +import com.example.mina.client.base.AbstractClientFactory; +import com.example.mina.client.base.AbstractMatrixIoHandler; +import com.example.mina.client.base.MatrixConstants; +import org.springframework.stereotype.Component; + +@Component(MatrixConstants.MATRIX_TYPE_LTE3000) +public class Lte3000ClientFactory extends AbstractClientFactory { + + @Override + public AbstractMatrixIoHandler getClientHandler() { + return null; + } +} diff --git a/src/main/java/com/example/mina/client/box/lte3000/Lte3000ClientHandler.java b/src/main/java/com/example/mina/client/box/lte3000/Lte3000ClientHandler.java deleted file mode 100644 index f5270e2..0000000 --- a/src/main/java/com/example/mina/client/box/lte3000/Lte3000ClientHandler.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.example.mina.client.box.lte3000; - -import com.example.mina.client.base.AbstractVirtualBoxClientHandler; -import com.example.mina.client.base.DownloadListener; -import com.example.mina.server.util.Lte3000CommandHelper; -import lombok.extern.slf4j.Slf4j; - -/** - * @author dy - * @date 2021/3/10 - */ -@Slf4j -public class Lte3000ClientHandler extends AbstractVirtualBoxClientHandler { - - public Lte3000ClientHandler(DownloadListener downloadListener) { - super(downloadListener); - } - - protected boolean isSameValue(byte value, int expect) { - return ((0xFF & value) == expect); - } - - @Override - public boolean handleCommandResponse(byte[] response) { - int responseLen = response.length; - if (response[0] != Lte3000CommandHelper.ACK || responseLen < 6) { - return false; - } - //api document: "SRM - MRF - MRM - XRM - QRM - LTE Protocol v2.15 Rev FR.pdf" - - //O:Query Output Channel P.106 - //0x4F - if (responseLen == 9 && isSameValue(response[3], 0x4F)) { // 'O' -// 0x6 0x46 0x46 0x4F 0x30 0x32 0x38 0x3 0x70 - int col = Lte3000CommandHelper.getBcdPort(response[4], response[5], response[6]); - int row = Lte3000CommandHelper.getBcdPort(response[4], response[5], response[6]); - // limits only one set "ON" in a column, others should be OFF -// for (int i = 1; i <= responsePool.getMaxRow(); i++) { -// if (i == row) { -// responsePool.setAttenuation(i, col, 1); -// } else { -// responsePool.setAttenuation(i, col, 0); -// } -// } TODO 再次调用DownloadListener的方法来设置衰减值 - log.info("RESPONSE Ox4F. ROW = {}, COL = {}", row, col); - return true; - } - - //S: Set CrossPoint P.115 - //0x53 - if (responseLen == 6 && isSameValue(response[3], 0x53)) { - int col = Lte3000CommandHelper.getBcdPort(response[4], response[5], response[6]); - int row = Lte3000CommandHelper.getBcdPort(response[7], response[8], response[9]); - // limits only one set "ON" in a column, others should be OFF -// for (int i = 1; i <= responsePool.getMaxRow(); i++) { -// if (i == row) { -// responsePool.setAttenuation(i, col, 1); -// } else { -// responsePool.setAttenuation(i, col, 0); -// } -// } TODO 再次调用DownloadListener的方法来设置衰减值 - log.info("RESPONSE Ox53. ROW = {}, COL = {}", row, col); - return true; - } - - //XGMO: Set Gain Control to Manual Mode - Output p.137 - //0x58 0x47 0x4D 0x4F - if (responseLen == 9 && response[3] == 'X' && response[4] == 'G' && response[5] == 'M' && response[6] == 'O') { -// receive - 0x2 0x30 0x30 0x58 0x47 0x4D 0x4F 0x30 0x30 0x31 0x40 0x2D 0x36 0x33 0x2E 0x30 0x3 0x5B -// 00XGMO001@-63.0[ -// set col/attn 1/63 - - int col = Lte3000CommandHelper.getBcdPort(response[7], response[8], response[9]); - int attn = Lte3000CommandHelper.getBcdAttn(response[11], response[12], response[13], response[14], response[15]); - //responsePool.setOffset(col, attn); TODO 再次调用DownloadListener的方法来设置衰减值 - log.info("RESPONSE XGMO. ATTN = {}, COL = {}", attn, col); - return true; - } - - - //XGRO: Gain Control Read Status - Output P.139 - if (responseLen == 16 && response[3] == 'X' && response[4] == 'G' && response[5] == 'R' && response[6] == 'O') { - /* - Example Command: - 02 XX XX 58 46 52 4F 30 31 36 03 XX - STX ADR ADR X G R O O 1 6 ETX CHK - (Read attenuation control status of system output 16) - */ - /* - Example Response: - 06 XX XX 58 46 52 4F 4D 40 2D 31 33 2E 35 03 XX - ACK ADR ADR X G R O M @ - 1 3 . 5 ETX CHX - (Output set at -13.5 dB of attenuation in manual mode. ) - */ - int col = Lte3000CommandHelper.getBcdPort(response[7], response[8], response[9]); - int attn = Lte3000CommandHelper.getBcdAttn(response[9], response[10], response[11], response[12], response[13]); - //responsePool.setOffset(col, attn); TODO 再次调用DownloadListener的方法来设置衰减值 - log.info("RESPONSE XGRO. ATTN = {}, COL = {}", attn, col); - return true; - } - - log.info("收到服务器回传的消息了"); - return false; - } -} diff --git a/src/main/java/com/example/mina/client/box/lte3000/Lte3000ClientIoHandler.java b/src/main/java/com/example/mina/client/box/lte3000/Lte3000ClientIoHandler.java new file mode 100644 index 0000000..61a7a5e --- /dev/null +++ b/src/main/java/com/example/mina/client/box/lte3000/Lte3000ClientIoHandler.java @@ -0,0 +1,105 @@ +package com.example.mina.client.box.lte3000; + +import com.example.mina.client.base.AbstractMatrixIoHandler; +import com.example.mina.client.base.MatrixDataProxy; +import com.example.mina.server.util.Lte3000CommandHelper; +import lombok.extern.slf4j.Slf4j; + +/** + * @author dy + * @date 2021/3/10 + */ +@Slf4j +public class Lte3000ClientIoHandler extends AbstractMatrixIoHandler { + + public Lte3000ClientIoHandler(MatrixDataProxy matrixDataProxy) { + super(matrixDataProxy); + } + + protected boolean isSameValue(byte value, int expect) { + return ((0xFF & value) == expect); + } + + @Override + public boolean handleCommandResponse(byte[] response) { + int responseLen = response.length; + if (response[0] != Lte3000CommandHelper.ACK || responseLen < 6) { + return false; + } + //api document: "SRM - MRF - MRM - XRM - QRM - LTE Protocol v2.15 Rev FR.pdf" + + //O:Query Output Channel P.106 + //0x4F + if (responseLen == 9 && isSameValue(response[3], 0x4F)) { // 'O' +// 0x6 0x46 0x46 0x4F 0x30 0x32 0x38 0x3 0x70 + int col = Lte3000CommandHelper.getBcdPort(response[4], response[5], response[6]); + int row = Lte3000CommandHelper.getBcdPort(response[4], response[5], response[6]); + // limits only one set "ON" in a column, others should be OFF +// for (int i = 1; i <= responsePool.getMaxRow(); i++) { +// if (i == row) { +// responsePool.setAttenuation(i, col, 1); +// } else { +// responsePool.setAttenuation(i, col, 0); +// } +// } TODO 再次调用MatrixDataProxy的方法来设置衰减值 + log.info("RESPONSE Ox4F. ROW = {}, COL = {}", row, col); + return true; + } + + //S: Set CrossPoint P.115 + //0x53 + if (responseLen == 6 && isSameValue(response[3], 0x53)) { + int col = Lte3000CommandHelper.getBcdPort(response[4], response[5], response[6]); + int row = Lte3000CommandHelper.getBcdPort(response[7], response[8], response[9]); + // limits only one set "ON" in a column, others should be OFF +// for (int i = 1; i <= responsePool.getMaxRow(); i++) { +// if (i == row) { +// responsePool.setAttenuation(i, col, 1); +// } else { +// responsePool.setAttenuation(i, col, 0); +// } +// } TODO 再次调用MatrixDataProxy的方法来设置衰减值 + log.info("RESPONSE Ox53. ROW = {}, COL = {}", row, col); + return true; + } + + //XGMO: Set Gain Control to Manual Mode - Output p.137 + //0x58 0x47 0x4D 0x4F + if (responseLen == 9 && response[3] == 'X' && response[4] == 'G' && response[5] == 'M' && response[6] == 'O') { +// receive - 0x2 0x30 0x30 0x58 0x47 0x4D 0x4F 0x30 0x30 0x31 0x40 0x2D 0x36 0x33 0x2E 0x30 0x3 0x5B +// 00XGMO001@-63.0[ +// set col/attn 1/63 + + int col = Lte3000CommandHelper.getBcdPort(response[7], response[8], response[9]); + int attn = Lte3000CommandHelper.getBcdAttn(response[11], response[12], response[13], response[14], response[15]); + //responsePool.setOffset(col, attn); TODO 再次调用MatrixDataProxy的方法来设置衰减值 + log.info("RESPONSE XGMO. ATTN = {}, COL = {}", attn, col); + return true; + } + + + //XGRO: Gain Control Read Status - Output P.139 + if (responseLen == 16 && response[3] == 'X' && response[4] == 'G' && response[5] == 'R' && response[6] == 'O') { + /* + Example Command: + 02 XX XX 58 46 52 4F 30 31 36 03 XX + STX ADR ADR X G R O O 1 6 ETX CHK + (Read attenuation control status of system output 16) + */ + /* + Example Response: + 06 XX XX 58 46 52 4F 4D 40 2D 31 33 2E 35 03 XX + ACK ADR ADR X G R O M @ - 1 3 . 5 ETX CHX + (Output set at -13.5 dB of attenuation in manual mode. ) + */ + int col = Lte3000CommandHelper.getBcdPort(response[7], response[8], response[9]); + int attn = Lte3000CommandHelper.getBcdAttn(response[9], response[10], response[11], response[12], response[13]); + //responsePool.setOffset(col, attn); TODO 再次调用MatrixDataProxy的方法来设置衰减值 + log.info("RESPONSE XGRO. ATTN = {}, COL = {}", attn, col); + return true; + } + + log.info("收到服务器回传的消息了"); + return false; + } +} diff --git a/src/main/java/com/example/mina/client/experiment/HandoverExperiment.java b/src/main/java/com/example/mina/client/experiment/HandoverExperiment.java new file mode 100644 index 0000000..c80d262 --- /dev/null +++ b/src/main/java/com/example/mina/client/experiment/HandoverExperiment.java @@ -0,0 +1,23 @@ +package com.example.mina.client.experiment; + +import com.example.mina.client.base.MatrixClient; +import com.example.mina.client.base.MatrixConstants; +import com.example.mina.client.base.Experiment; +import com.example.mina.client.base.ExperimentOptions; + +public class HandoverExperiment extends Experiment { + + public HandoverExperiment(MatrixClient client, ExperimentOptions options) { + super(client, options); + } + + @Override + public String getExperimentName() { + return MatrixConstants.EXPERIMENT_HANDOVER; + } + + @Override + public void schedule() { + } + +} -- libgit2 0.21.2