使用mina框架,开发基于tcp/ip协议的门禁设备

package com.tyhuanledi.device;

public interface DoorDevice {
    /**
     * 启动门
     * v1.0 zhc 2016年1月13日下午2:33:16
     * void
     */
    public void startUp();

    /**
     * 开门
     * v1.0 zhc 2016年1月13日下午2:37:26
     * @param ip
     * @param port
     * @param doorNo 门号
     * void
     */
    public void openDoor(String ip, int port, int doorNo);

    /**
     * 关门
     * v1.0 zhc 2016年1月13日下午2:37:40
     * @param ip
     * @param port
     * @param doorNo 门号
     * void
     */
    public void closeDoor(String ip, int port, int doorNo);
}
package com.tyhuanledi.device.impl;

import java.io.InputStream;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tyhuanledi.device.DoorDevice;
import com.tyhuanledi.device.codec.DoorDecoder;
import com.tyhuanledi.device.codec.DoorEncoder;
import com.tyhuanledi.device.entity.DoorCommand;
import com.tyhuanledi.device.filter.ReConnectionFilter;
import com.tyhuanledi.device.filter.SessionManagerFilter;
import com.tyhuanledi.device.handle.DoorHandle;
import com.tyhuanledi.device.manager.SessionManager;

public class DoorDevice implements DoorDevice {
    private Logger log = LoggerFactory.getLogger(DoorDevice.class);

    @Override
    public void startUp() {
        final IoConnector connector = new NioSocketConnector();// 创建客户端连接
        connector.setConnectTimeoutMillis(5 * 1000);// 设置连接超时5秒
        connector.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10 * 1000);// 设置读写空闲10秒
        connector.getFilterChain().addFirst("reconnection", new ReConnectionFilter());// 添加断线重连过滤器
        connector.getFilterChain().addAfter("reconnection", "sessionManager", new SessionManagerFilter());// 添加session管理过滤器
        connector.getFilterChain().addAfter("sessionManager", "codec",
                new ProtocolCodecFilter(new DoorEncoder(), new DoorDecoder()));// 添加编解码过滤器
        connector.setHandler(new DoorHandle());// 添加业务处理

        List<Map<String, Object>> list = getList();
        for(final Map<String, Object> map : list){
            try {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        start(connector, map.get("ip").toString(), (Integer)map.get("port"));//启动设备
                    }
                }).start();

                Thread.sleep(1000);//睡眠1秒
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void start(IoConnector connector, String ip, int port) {
        while (true) {
            try {
                log.debug("开始连接门禁【" + ip + ":" + port + "】。");
                ConnectFuture future = connector.connect(new InetSocketAddress(ip, port));// 开始连接
                future.awaitUninterruptibly();// 等待连接创建成功
                IoSession session = future.getSession();// 获取会话
                if (session.isConnected()) {//如果连接成功
                    log.debug("连接门禁【" + ip + ":" + port + "】成功。");
                    break;
                }
            } catch (Exception e) {
                try {
                    e.printStackTrace();
                    log.debug("连接门禁【" + ip + ":" + port + "】失败,5秒后重试。");
                    Thread.sleep(5000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    @Override
    public void openDoor(String ip, int port, int doorNo) {
        IoSession session = SessionManager.get(ip, port);
        session.write(DoorCommand.createOpenCommand(doorNo));
    }

    @Override
    public void closeDoor(String ip, int port, int doorNo) {
        IoSession session = SessionManager.get(ip, port);
        session.write(DoorCommand.createCloseCommand(doorNo));
    }

    public List<Map<String, Object>> getList(){
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("ip", "192.168.8.31");
        map.put("port", 8000);
        map.put("doorNo", 1);
        list.add(map);

        Map<String, Object> map2 = new HashMap<String, Object>();
        map2.put("ip", "192.168.8.32");
        map2.put("port", 8000);
        map2.put("doorNo", 1);
        list.add(map2);
        return list;
    }

    public static void main(String[] args) {
        DoorDevice door = new DoorDevice();
        door.startUp();
        while (true) {
            try {
                InputStream in = System.in;
                int readKey = in.read();
                if (readKey == 49) {
                    door.openDoor("192.168.8.31", 8000, 1);
                }
                if (readKey == 50) {
                    door.closeDoor("192.168.8.31", 8000, 1);
                }
                if (readKey == 52) {
                    door.openDoor("192.168.8.32", 8000, 1);
                }
                if (readKey == 53) {
                    door.closeDoor("192.168.8.32", 8000, 1);
                } 
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
package com.tyhuanledi.device.filter;

import java.net.InetSocketAddress;

import org.apache.mina.core.filterchain.IoFilterAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tyhuanledi.device.impl.DoorDevice;

public class ReConnectionFilter extends IoFilterAdapter {
    private Logger log = LoggerFactory.getLogger(ReConnectionFilter.class);

    @Override
    public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) throws Exception {
        InetSocketAddress address = (InetSocketAddress) session.getServiceAddress();
        String ip = address.getHostName();
        int port = address.getPort();
        session.close(true);
        log.debug("门禁【" + ip + ":" + port + "】连接异常,连接自动断开。");

        super.exceptionCaught(nextFilter, session, cause);
    }

    @Override
    public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception {
        InetSocketAddress address = (InetSocketAddress) session.getServiceAddress();
        String ip = address.getHostName();
        int port = address.getPort();
        session.close(true);

        NioSocketConnector connector = (NioSocketConnector) session.getService();
        int bothIdleTime = connector.getSessionConfig().getBothIdleTime();
        log.debug("连接门禁【" + ip + ":" + port + "】连接超时"+bothIdleTime+"秒,连接自动断开。");

        super.sessionIdle(nextFilter, session, status);
    }

    @Override
    public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {
        super.sessionClosed(nextFilter, session);

        final NioSocketConnector connector = (NioSocketConnector) session.getService();
        InetSocketAddress address = (InetSocketAddress) session.getServiceAddress();
        final String ip = address.getHostName();
        final int port = address.getPort();
        log.debug("门禁【" + ip + ":" + port + "】连接被关闭,5秒后重新连接。");

        try {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(5 * 1000);
                        new DoorDevice().start(connector, ip, port);//启动设备
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.tyhuanledi.device.filter;

import java.net.InetSocketAddress;

import org.apache.mina.core.filterchain.IoFilterAdapter;
import org.apache.mina.core.session.IoSession;

import com.tyhuanledi.device.manager.SessionManager;

public class SessionManagerFilter extends IoFilterAdapter{
    @Override
    public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
        InetSocketAddress address = (InetSocketAddress) session.getServiceAddress();
        SessionManager.put(address.getHostName(), address.getPort(), session);
        super.sessionCreated(nextFilter, session);
    }

    @Override
    public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {
        InetSocketAddress address = (InetSocketAddress) session.getServiceAddress();
        SessionManager.remove(address.getHostName(), address.getPort());
        super.sessionClosed(nextFilter, session);
    }
}
package com.tyhuanledi.device.codec;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tyhuanledi.device.entity.Door;
import com.tyhuanledi.device.entity.DoorCommand;

public class DoorDecoder extends CumulativeProtocolDecoder{
    private static final Logger log = LoggerFactory.getLogger(DoorDecoder.class);

    @Override
    protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
        //接受数据
        byte[] data = new byte[in.limit()];
        in.get(data);
//      log.debug("收到消息:" + ByteUtil.toHexStr(data));

        //校验数据
        boolean validate = DoorCommand.validate(data);
        if(!validate){
            log.debug("校验数据失败");
            Door Door = new Door();
            Door.setCommand((byte)0x00);
            return true;
        }

        //解析数据
        out.write(new Door(data));
        return true;
    }
}
package com.tyhuanledi.device.codec;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;

public class DoorEncoder extends ProtocolEncoderAdapter {
//  private static final Logger log = LoggerFactory.getLogger(DoorEncoder.class);

    @Override
    public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
        byte[] data = (byte[]) message;
//      log.debug("发送消息:" + ByteUtil.toHexStr(data));
        IoBuffer buffer = IoBuffer.allocate(data.length);
        buffer.put(data);
        buffer.flip();
        out.write(buffer);
    }
}
package com.tyhuanledi.device.handle;

import java.net.InetSocketAddress;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tyhuanledi.device.entity.Door;
import com.tyhuanledi.device.entity.DoorCommand;

public class DoorHandle extends IoHandlerAdapter{
    private Logger log = LoggerFactory.getLogger(DoorHandle.class);

    @Override
    public void messageReceived(IoSession session, Object message) throws Exception {
        Door door = (Door) message;
        InetSocketAddress address = (InetSocketAddress) session.getServiceAddress();
        String ip = address.getHostName();
        int port = address.getPort();

        //如果是心跳指令
        if(door.getCommand() == DoorCommand.HEART){
            session.write(DoorCommand.createHeartCommand());
            return;
        }

        //如果是开门指令
        if(door.getCommand() == DoorCommand.OPEN){
            if(door.getData()[0] == DoorCommand.OPEN_SUCC){
                log.debug("门禁【" + ip + ":" + port + "】开门成功。");
                return;
            }

            log.debug("门禁【" + ip + ":" + port + "】开门失败。");
        }

        //如果是关门指令
        if(door.getCommand() == DoorCommand.CLOSE){
            if(door.getData()[0] == DoorCommand.OPEN_SUCC){
                log.debug("门禁【" + ip + ":" + port + "】关门成功。");
                return;
            }

            log.debug("门禁【" + ip + ":" + port + "】关门失败。");
        }
    }
}
package com.tyhuanledi.device.manager;

import java.util.HashMap;
import java.util.Map;

import org.apache.mina.core.session.IoSession;

public class SessionManager {
    private static final Map<String, IoSession> map = new HashMap<String, IoSession>();

    public static void put(String ip, int port, IoSession session) {
        map.put(ip + port, session);
    }

    public static void remove(String ip, int port) {
        map.remove(ip + port);
    }

    public static IoSession get(String ip, int port) {
        return map.get(ip + port);
    }
}
package com.tyhuanledi.device.entity;

import java.util.Arrays;

import com.tyhuanledi.util.ByteUtil;

public class Door {
    byte stx = 0x02;// 开始位 0x02
    byte rand = 0x00;// 随机数 保留
    byte command;// 指令
    byte address = 0x00;// 控制器地址 保留
    byte door;// 门编号 1-4
    byte lengthL; // 数据长度低位
    byte lengthH; // 数据长度高位
    byte[] data;//
    byte cs;// 校验
    byte etx = 0x03;// 结束 0x03

    public Door() {

    }
    public Door(byte[] data) {
        command = data[2];
        address = data[4];
        lengthL = data[5];
        lengthH = data[6];
        int dataLen = ByteUtil.getLength(lengthL, lengthH);
        if (dataLen > 0) {
            this.data = Arrays.copyOfRange(data, 7, 7 + dataLen);
        }
        cs = data[data.length - 2];
        etx = data[data.length - 1];
    }

    public byte getStx() {
        return stx;
    }

    public void setStx(byte stx) {
        this.stx = stx;
    }

    public byte getRand() {
        return rand;
    }

    public void setRand(byte rand) {
        this.rand = rand;
    }

    public byte getCommand() {
        return command;
    }

    public void setCommand(byte command) {
        this.command = command;
    }

    public byte getAddress() {
        return address;
    }

    public void setAddress(byte address) {
        this.address = address;
    }

    public byte getDoor() {
        return door;
    }

    public void setDoor(byte door) {
        this.door = door;
    }

    public byte getLengthL() {
        return lengthL;
    }

    public void setLengthL(byte lengthL) {
        this.lengthL = lengthL;
    }

    public byte getLengthH() {
        return lengthH;
    }

    public void setLengthH(byte lengthH) {
        this.lengthH = lengthH;
    }

    public byte[] getData() {
        return data;
    }

    public void setData(byte[] data) {
        this.data = data;
    }

    public byte getCs() {
        return cs;
    }

    public void setCs(byte cs) {
        this.cs = cs;
    }

    public byte getEtx() {
        return etx;
    }

    public void setEtx(byte etx) {
        this.etx = etx;
    }
}
package com.tyhuanledi.device.entity;

import java.util.Arrays;

import com.tyhuanledi.util.ByteUtil;

public class DoorCommand {
    public static final byte HEART = 0x56;//心跳命令
    public static final byte OPEN = 0x2C;//开门命令
    public static final byte OPEN_SUCC = 0x06;//开门成功
    public static final byte CLOSE = 0x2E;//关门命令

    public static byte[] buildCommand(byte command, int doorNo, byte[] data) {
        if(data == null){
            data = new byte[0];
        }

        byte[] message = new byte[9 + data.length];
        message[0] = 0x02;
        message[1] = 0x00;
        message[2] = command;
        message[3] = 0x00;
        message[4] = (byte) doorNo;
        message[5] = ByteUtil.getLower(data.length);
        message[6] = ByteUtil.getHigh(data.length);
        if(data != null && data.length > 0){
            System.arraycopy(message, 7, data, 0, data.length);
        }
        message[message.length - 2] = getCs(Arrays.copyOfRange(message, 0, message.length - 2));
        message[message.length - 1] = 0x03;
        return message;
    }

    public static byte getCs(byte[] data){
        byte cs = 0;
        for(byte b : data){
            cs ^= b;
        }
        return cs;
    }

    public static byte[] createHeartCommand() {
        return buildCommand(HEART, 1, null);
    }

    public static Object createOpenCommand(int doorNo) {
        return buildCommand(OPEN, doorNo, null);
    }

    public static Object createCloseCommand(int doorNo) {
        return buildCommand(CLOSE, doorNo, null);
    }

    public static boolean validate(byte[] data){
        byte checkCode = getCs(Arrays.copyOfRange(data, 0, data.length - 2));
        byte checkCode1 = data[data.length - 2];
        return checkCode == checkCode1;
    }

}
package com.tyhuanledi.util;

public class ByteUtil {

    /**
     * 获取高地位长度 v1.0 zhc 2016年1月13日下午3:30:01
     * 
     * @param lengthH
     * @param LengthL
     * @return int
     */
    public static int getLength(byte lengthH, byte LengthL) {
        return lengthH << 8 | LengthL;
    }

    /**
     * 获取高位 v1.0 zhc 2016年1月13日下午4:08:31
     * 
     * @param length
     * @return byte
     */
    public static byte getLower(int num) {
        return (byte) (num >> 8);
    }

    /**
     * 获取低位 v1.0 zhc 2016年1月13日下午4:11:14
     * 
     * @param length
     * @return byte
     */
    public static byte getHigh(int num) {
        return (byte) (num & 0xff00);
    }

    public static String toHexStr(byte[] data) {
        final String HEX = "0123456789ABCDEF";
        StringBuilder sb = new StringBuilder(data.length * 2);
        for (byte b : data) {
            if(sb.length() > 0){
                sb.append(",");
            }
            sb.append(HEX.charAt((b >> 4) & 0x0f));
            sb.append(HEX.charAt(b & 0x0f));

        }

        return sb.toString();
    }
}

jar包:
log4j-1.2.17.jar
mina-core-2.0.9.jar
slf4j-api-1.7.12.jar
slf4j-log4j12-1.7.12.jar

配置文件:
log4j.properties

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值