TcpServer.java 8.9 KB
package com.myproject.mina;

import com.google.common.base.Strings;
import com.myproject.bean.CodeBean;
import com.myproject.bean.update.Barcode;
import com.myproject.bean.update.Component;
import com.myproject.bean.update.StoragePos;
import com.myproject.manager.IBarcodeManager;
import com.myproject.manager.IComponentManager;
import com.myproject.manager.IStoragePosManager;
import com.myproject.util.StorageConstants;
import com.myproject.util.XmlUtil;
import com.myproject.webapp.controller.webService.DataCache;
import com.myproject.webapp.controller.webService.ITaskService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by sunke on 2019/4/17.
 */
@Service
public class TcpServer {


    protected final static Logger log = LogManager.getLogger();

    private static NioSocketAcceptor acceptor;
    private static final int port = 9999;

    @Autowired
    private DataCache dataCache;

    @Autowired
    private IBarcodeManager barcodeManager;

    @Autowired
    private IComponentManager componentManager;

    @Autowired
    private IStoragePosManager storagePosManager;

    @Autowired
    private ITaskService taskService;

    @PostConstruct
    public void init(){
        dataCache.getSettings();
        if(dataCache.isProductionFor(DataCache.CUSTOMER.PANACIM)){
            start();
        }
    }

    public void start(){

        try {
            // 创建一个非堵塞的server端的Socket
            acceptor = new NioSocketAcceptor();
            // 设置过滤器
            ProtocolCodecFactory codec = new TextLineCodecFactory(Charset.defaultCharset(),"\03","\03");
            acceptor.getFilterChain().addLast(
                    "serverCodec",new ProtocolCodecFilter(codec));
            acceptor.getFilterChain().addLast("ServerFilter",
                    new ExecutorFilter());
            acceptor.getSessionConfig().setReadBufferSize(2048);
            // 读写通道10秒内无操作进入空暇状态
            acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
            // 加入逻辑处理器
            acceptor.setHandler(new ServerHandler());
            // 绑定端口
            try {
                acceptor.bind(new InetSocketAddress(port));
                log.info("PanaCM TCP Server start on port " + port);
            } catch (Exception e) {
            }
        } catch (Exception e) {
            log.error("TCP Server start error:",e);
        }

    }
    // 停止MINA服务
    public void stop() {
        try {
            log.info("stopping the TCP Server");
            acceptor.unbind();
            acceptor.dispose();
        } catch (Exception e) {
            log.error("TCP Server stop error:",e);
        }
    }


    public static void main(String args[]){
        new TcpServer().start();
    }


    //https://192.168.10.1:5000 root panasonic123

    private class ServerHandler extends IoHandlerAdapter {

        @Override
        public void sessionOpened(IoSession session) throws Exception {
            log.info("TCP Client["+session.getRemoteAddress()+"] connected!");
        }

        @Override
        public void sessionClosed(IoSession session) throws Exception {
            log.info("TCP Client["+session.getRemoteAddress()+"] Closed!");
        }

        @Override
        public void messageReceived(IoSession session, Object message) throws Exception {
            String msg = message.toString();
            log.info("Received msg:" + msg);
            if(msg.contains("PING_REQ")){
                //Ping消息
                session.write("\02"+8+"\01"+"PING_RSP");
                return;
            }
            String type = XmlUtil.getNodeAttribute("header","messageClass",msg);
            if("510".equals(type)){
                //F12进入移动模式,选择物料核对,点击上方M1-Font改为M2-Rear,扫描条码后反馈
                //detail中part为PN,lot为批次,vendor为供应商 userdata为自定义数据(userdata1,userdata2)
                log.info("收到510 料号请求");
                String reelId = XmlUtil.getNodeAttribute("material","id",msg);
                CodeBean codeBean = dataCache.resolveSingleCode(reelId);
                if(codeBean.isValid()){
                    Barcode barcode = codeBean.getBarcode();
                    //回消息
                    String header = XmlUtil.getElementByNode("header", msg);
                    String resultMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <message>\n" +
                            header + "\n" +
                            "<body>\n" +
                            "<result errorCode=\"0\" errorText=\"\" actionCode=\"0\"/>\n" +
                            "<material id=\""+barcode.getBarcode() +"\" state=\"0\" prevReelId=\"\" splicedReelId=\"\" >\n" +
                            "<detail part=\""+barcode.getPartNumber()+"\" qty=\""+barcode.getAmount()+"\" lot=\"\" vendor=\"\" userdata=\"\" partclass=\"R100\"/> </material>\n" +
                            "</body>" +
                            "</message>";
                    log.info("收到510料号["+reelId+"]请求,返回:" + resultMsg);
                    int msgLength = resultMsg.length();
                    session.write("\02"+msgLength+"\01"+resultMsg);
                }else{
                    log.info("条码:" + reelId + "无效");
                }
            }else if("530".equals(type) || "550".equals(type) || "590".equals(type) || "620".equals(type)){
                List<String> materials = XmlUtil.getElementsByNode("material", msg);
                for (String material : materials) {
                    //更新数量
                    Map<String, String> attributeMap = XmlUtil.getNodeAttributes("material", material);
                    String reelId = attributeMap.get("id");
                    String qty = attributeMap.get("qty");
                    if(reelId != null && qty!= null){
                        log.info(type + " 更新["+reelId+"]的数量为:" + qty);
                        CodeBean codeBean = dataCache.resolveSingleCode(reelId);
                        if(codeBean.isValid()){
                            Barcode barcode = codeBean.getBarcode();
                            int amount = -1;
                            try{
                                amount = Integer.valueOf(qty);
                                barcode.setAmount(amount);
                                //未补过料
                                if(Strings.isNullOrEmpty(barcode.getNextBarcode())){
                                    Component component = componentManager.findOneByPn(barcode.getPartNumber());
                                    int alarmAmount = component.getAlarmAmount();
                                    if(amount <= alarmAmount){
                                        StoragePos pos = storagePosManager.findPartNumberPos(null,barcode.getPartNumber(),new ArrayList<String>(), StorageConstants.CHECKOUT_TYPE.FIFO);
                                        if(pos != null){
                                            taskService.checkout(pos, null, false);
                                            barcode.setNextBarcode(pos.getBarcode().getBarcode());
                                            log.info("当前数量【"+ amount +"】小于预警值["+alarmAmount+"],出库["+pos.getPosName()+"]一盘新的物料【"+pos.getBarcode().getBarcode()+"】");
                                        }else{
                                            log.warn("小于预警值,但库存中无【"+barcode.getPartNumber()+"】对应的物料");
                                        }
                                    }
                                }
                                barcodeManager.save(barcode);

                            }catch (Exception e){
                                log.info("条码:" + reelId + "更新数量["+qty+"]失败:", e);
                            }
                        }else{
                            log.info("条码:" + reelId + "无效");
                        }
                    }
                }
            }else if("620".equals(type)){
                log.info("收到620");
            }
        }

        @Override
        public void messageSent(IoSession session, Object message) throws Exception {
        }
    }
}