Apache mina:思源科安虹膜识别设备KAIris100 Socket 通信 SDK

注意:该SDK是本人为北京思源科安信息技术有限公司虹膜识别设备KAIris100开发的基于Apache mina框架的Socket通信协议编解码器,虽非官方产品,却填补官方空白。

同系列文章:

依赖关系:

编解码器源代码出售:

sell
价格:壹仟元人民币
微信号:splashcn

SDK及测试程序下载:

MinaKAIrisClientDemo-Java-20160104.zip
注意:演示程序由于使用了JavaFX技术,需要JDK8运行环境

演示程序界面:
MinaKAIrisClientDemo

源代码
消息对象:KAIrisMessage.java

/* ----------------------------------------------------------
 * 文件名称:KAIrisMessage.java
 * 
 * 作者:秦建辉
 * 
 * QQ:36748897
 * 
 * 博客:http://www.firstsolver.com/wordpress/
 * 
 * 开发环境:
 *      NetBeans 8.1
 *      JDK 8u66
 *      
 * 版本历史:
 *      V1.0    2015年12月28日
 *              思源科安 KAIris100 Socket 通信消息对象
------------------------------------------------------------ */
package Com.FirstSolver.KAIris;

import java.io.Serializable;

public class KAIrisMessage implements Serializable {
    // 包头
    private final String mHeader;
    
    // 包体,包体可以为null
    private final String mBody;     
    
    // 构造函数
    public KAIrisMessage(String header, String body) {
        mHeader = header;
        mBody = body;
    }
    
    // 获取包头
    public String getHeader() { return mHeader; }
    
    // 获取包体
    public String getBody() { return mBody; }
    
    // 获取版本
    public String getVersion() { return mHeader.substring(0,2).trim(); }
    
    // 获取命令
    public String getCommand() { return mHeader.substring(12,16).trim(); }
    
    // 获取多包标识
    public String getFlowMark() { return mHeader.substring(16,17).trim(); }
    
    // 获取错误代码
    public String getErrorCode() { return mHeader.substring(17,21).trim(); }
}

客户端消息处理器:FXMLDocumentController.java

/* ----------------------------------------------------------
 * 文件名称:FXMLDocumentController.java
 * 
 * 作者:秦建辉
 * 
 * QQ:36748897
 * 
 * 博客:http://www.firstsolver.com/wordpress/
 * 
 * 开发环境:
 *      NetBeans 8.1
 *      JDK 8u66
 *      
 * 版本历史:
 *      V1.0    2015年12月28日
 *              思源科安 KAIris100 Socket 通信客户端消息处理器
------------------------------------------------------------ */

package Splash;

import Com.FirstSolver.KAIris.KAIrisMessage;
import Com.FirstSolver.KAIris.KAIrisProtocolCodecFactory;
import java.net.InetSocketAddress;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;

public class FXMLDocumentController extends IoHandlerAdapter implements Initializable {   
    // 线程池
    public ExecutorService mPool;
    
    private FXMLDocumentController mController;
    
    @FXML
    private TextField textFieldServerIP;
    
    @FXML
    private TextField textFieldServerPort;
     
    @FXML
    private TextField textFieldQueryCommand;
            
    @FXML
    private TextArea textAreaRecords;

    @FXML
    private void handleButtonExecuteCommand(ActionEvent event) throws Exception { 
        // 加入线程池队列
        mPool.execute(new PoolHandler(textFieldServerIP.getText(), Integer.parseInt(textFieldServerPort.getText()), textFieldQueryCommand.getText()));
    }
    
    @FXML
    private void handleButtonClearAction(ActionEvent event) {
        textAreaRecords.clear();
    }    
   
    // 接收消息处理器,其中message为KAIrisMessage对象实例
    @Override
    public void messageReceived(IoSession session, Object message) throws Exception {
        if (message instanceof KAIrisMessage) {
            // 处理消息
            KAIrisMessage Source = (KAIrisMessage)message;
            
            // 显示包头
            textAreaRecords.appendText("包头:\r\n");
            textAreaRecords.appendText(Source.getHeader() + "\r\n");
            
            // 显示包体
            textAreaRecords.appendText("包体:\r\n");
            textAreaRecords.appendText(Source.getBody() + "\r\n");
        }
        
        // 采用短连接,消息处理完后就断开连接
        session.close(true);
    }
    
    @Override
    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
        textAreaRecords.appendText("异常:\r\n");
        textAreaRecords.appendText(cause.getMessage() + "\r\n");
        session.close(true);
    }
    
    @Override
    public void initialize(URL url, ResourceBundle rb) { 
        mController = this;
        
        // 创建一个单一线程的线程池
        mPool = Executors.newSingleThreadExecutor();  
    } 
    
    private class PoolHandler implements Runnable {	
        private final String mHost;
        private final int mPort;
        private final String mCommand;

        public PoolHandler(String host, int port, String command) {
            mHost = host;
            mPort = port;
            mCommand = command;
        }

        @Override
        public void run() {            
            IoConnector TcpClient = new NioSocketConnector();
            TcpClient.getFilterChain().addLast("codec", new ProtocolCodecFilter(new KAIrisProtocolCodecFactory()));
            TcpClient.setHandler(mController);
            
            ConnectFuture ConnFuture = TcpClient.connect(new InetSocketAddress(mHost, mPort));
            try {
                ConnFuture.await(30 * 1000);    
                ConnFuture.getSession().write(mCommand);
                ConnFuture.getSession().getCloseFuture().await(60 * 1000);
            } 
            catch (InterruptedException ex) {
                Alert alert = new Alert(Alert.AlertType.WARNING, ex.getMessage(), ButtonType.OK);
                alert.setTitle("MinaKAIrisClientDemo");
                alert.setHeaderText("错误");
                alert.showAndWait();
            }
            
            TcpClient.dispose(true);
        }
    }
}

客户端UI:FXMLDocument.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.text.*?>
<?import javafx.scene.effect.*?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" minWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Splash.FXMLDocumentController">
   <children>
      <GridPane minWidth="600.0">
        <columnConstraints>
            <ColumnConstraints />
        </columnConstraints>
        
        <rowConstraints>
          <RowConstraints />
          <RowConstraints />
          <RowConstraints />          
          <RowConstraints />
        </rowConstraints>
        
        <children>           
           <GridPane GridPane.hgrow="ALWAYS" GridPane.rowIndex="0">
               <columnConstraints>
                   <ColumnConstraints />
                   <ColumnConstraints hgrow="ALWAYS" />
               </columnConstraints>
               
               <rowConstraints>
                   <RowConstraints />
                   <RowConstraints />
               </rowConstraints>
               
              <children>                  
                  <Label text="设备地址" GridPane.columnIndex="0" GridPane.halignment="RIGHT" GridPane.rowIndex="0">
                     <GridPane.margin>
                        <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" />
                     </GridPane.margin>
                  </Label> 
                  
                  <Label text="设备端口" GridPane.columnIndex="0" GridPane.halignment="RIGHT" GridPane.rowIndex="1">
                     <GridPane.margin>
                        <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" />
                     </GridPane.margin>
                  </Label> 
                   
                  <TextField fx:id="textFieldServerIP" text="192.168.135.246" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.rowIndex="0" GridPane.vgrow="ALWAYS">
                     <GridPane.margin>
                        <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" />
                     </GridPane.margin>
                  </TextField>
                  
                  <TextField fx:id="textFieldServerPort" text="15001" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1">
                     <GridPane.margin>
                        <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" />
                     </GridPane.margin>
                  </TextField>
              </children>
               <GridPane.margin>
                  <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" />
               </GridPane.margin>
           </GridPane>
           
           <GridPane GridPane.hgrow="ALWAYS" GridPane.rowIndex="1">
               <columnConstraints>                  
                   <ColumnConstraints hgrow="ALWAYS" />
               </columnConstraints>
               
               <rowConstraints>
                   <RowConstraints />
                   <RowConstraints />   
               </rowConstraints>
               
              <children>                  
                  <Label text="查询命令:" GridPane.rowIndex="0">
                     <GridPane.margin>
                        <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" />
                     </GridPane.margin>
                  </Label>
                  
                  <TextField fx:id="textFieldQueryCommand" text="11        21100000000" GridPane.rowIndex="1">
                     <GridPane.margin>
                        <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" />
                     </GridPane.margin>
                  </TextField>     
              </children>
               <GridPane.margin>
                  <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" />
               </GridPane.margin>
           </GridPane>
                      
           <GridPane GridPane.rowIndex="2">
               <columnConstraints>
                   <ColumnConstraints />
                   <ColumnConstraints />
               </columnConstraints>

               <rowConstraints>
                  <RowConstraints />
               </rowConstraints>
               <children>
                   <Button fx:id="buttonClear" minHeight="40.0" minWidth="80.0" onAction="#handleButtonClearAction" text="清空" GridPane.columnIndex="0" GridPane.hgrow="ALWAYS">
                     <GridPane.margin>
                        <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" />
                     </GridPane.margin>
                   </Button> 
                   
                   <Button fx:id="buttonExecuteCommand" minHeight="40.0" minWidth="80.0" onAction="#handleButtonExecuteCommand" text="执行命令" GridPane.columnIndex="1" GridPane.halignment="RIGHT" GridPane.hgrow="ALWAYS">
                     <GridPane.margin>
                        <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" />
                     </GridPane.margin>
                   </Button>
               </children>               
           </GridPane> 
           
           <TextArea fx:id="textAreaRecords" editable="false" minHeight="400.0" minWidth="600.0" wrapText="true" GridPane.hgrow="ALWAYS" GridPane.rowIndex="3" GridPane.vgrow="ALWAYS">
               <GridPane.margin>
                  <Insets bottom="4.0" left="4.0" right="4.0" top="4.0" />
               </GridPane.margin>               
           </TextArea>
        </children> 
      </GridPane>
   </children>
</AnchorPane>

Comments are closed.