java PJLink 工具类

挖井人地址:点我

 

要是问起PJLink是啥,回答如下:

PJLINK CLASS 1是由日本向务机器和信息系统行业公会制定的一种标准协议,用来控制网络兼容的投影仪,这是他们投影仪控制协议标准工作的一部分。

更多请点击:点这儿(偷懒大法)

测试环境搭建:

没有现成的投影机提供测试,于是写了一个PJLink的测试类,首先看下协议内容(实际交互数据):

[2020.05.28 14:44:59.167] Connect TCP
[2020.05.28 14:44:59.176] RECV:PJLINK 0
[2020.05.28 14:44:59.197] SEND:%1POWR ?
[2020.05.28 14:44:59.205] RECV:%1POWR=0
[2020.05.28 14:44:59.315] SEND:%1INPT ?
[2020.05.28 14:44:59.320] RECV:%1INPT=ERR3
[2020.05.28 14:44:59.427] SEND:%1AVMT ?
[2020.05.28 14:44:59.432] RECV:%1AVMT=ERR3
[2020.05.28 14:44:59.549] SEND:%1ERST ?
[2020.05.28 14:44:59.554] RECV:%1ERST=000000
[2020.05.28 14:44:59.661] SEND:%1LAMP ?
[2020.05.28 14:44:59.668] RECV:%1LAMP=422 0
[2020.05.28 14:44:59.784] SEND:%1INST ?
[2020.05.28 14:44:59.789] RECV:%1INST=11 12 32 33 41 52
[2020.05.28 14:44:59.906] SEND:%1NAME ?
[2020.05.28 14:44:59.915] RECV:%1NAME=EBDFE9AE
[2020.05.28 14:44:59.919] 45 42 44 46 45 39 41 45
[2020.05.28 14:45:00.033] SEND:%1INFO ?
[2020.05.28 14:45:00.038] RECV:%1INFO=102.102.---
[2020.05.28 14:45:00.146] SEND:%1INF1 ?
[2020.05.28 14:45:00.152] RECV:%1INF1=EPSON
[2020.05.28 14:45:00.265] SEND:%1INF2 ?
[2020.05.28 14:45:00.269] RECV:%1INF2=EPSON L500
[2020.05.28 14:45:00.378] SEND:%1CLSS ?
[2020.05.28 14:45:00.380] RECV:%1CLSS=2
[2020.05.28 14:45:00.482] SEND:%2INPT ?
[2020.05.28 14:45:00.488] RECV:%2INPT=ERR3
[2020.05.28 14:45:00.594] SEND:%2INST ?
[2020.05.28 14:45:00.598] RECV:%2INST=11 12 32 33 41 52
[2020.05.28 14:45:00.702] SEND:%2SNUM ?
[2020.05.28 14:45:00.708] RECV:%2SNUM=X5TE89056L
[2020.05.28 14:45:00.812] SEND:%2SVER ?
[2020.05.28 14:45:00.818] RECV:%2SVER=87009470FJWV102
[2020.05.28 14:45:00.921] SEND:%2INNM ?11
[2020.05.28 14:45:00.927] RECV:%2INNM=Computer1
[2020.05.28 14:45:00.930] 43 6F 6D 70 75 74 65 72 31
[2020.05.28 14:45:01.033] SEND:%2IRES ?
[2020.05.28 14:45:01.037] RECV:%2IRES=ERR3
[2020.05.28 14:45:01.140] SEND:%2RRES ?
[2020.05.28 14:45:01.146] RECV:%2RRES=1280x800
[2020.05.28 14:45:01.249] SEND:%2FILT ?
[2020.05.28 14:45:01.251] RECV:%2FILT=0
[2020.05.28 14:45:01.360] SEND:%2RLMP ?
[2020.05.28 14:45:01.365] RECV:%2RLMP=ERR1
[2020.05.28 14:45:01.470] SEND:%2RFIL ?
[2020.05.28 14:45:01.475] RECV:%2RFIL=ELPA56
[2020.05.28 14:45:01.594] SEND:%2FREZ ?
[2020.05.28 14:45:01.599] RECV:%2FREZ=ERR3
[2020.05.28 14:45:31.592] Close TCP socket(Server).

根据这些,测试类如下:

package http;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class PJLINKServer {

	public static final int PORT = 5555;

	public static void main(String[] args) {
		try {
			new PJLINKServer();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public PJLINKServer() throws IOException {
		ServerSocket ss = new ServerSocket(PORT);
		InetAddress ia = InetAddress.getByName(null);

		System.out.println("Server@" + ia + " start!");

		try {
			while (true) {
				Socket s = ss.accept();// listen PORT;
				try {
					new ServerOne(s);
				} catch (IOException e) {
					s.close();
				}
			}
		} finally {
			ss.close();
			System.out.println("Server stop!");
		}
	}
}

class ServerOne extends Thread {
	private Socket s;
	private BufferedReader in;
	private PrintWriter out;

	public ServerOne(Socket s) throws IOException {
		this.s = s;
		in = new BufferedReader(new InputStreamReader(s.getInputStream()));
		out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(s.getOutputStream())), true);
		start();
	}

	public void run() {
		try {
			out.println("PJLINK 0");
			while (true) {
				String str = in.readLine();
				System.out.println("Server:" + str);
				if (str == null) {
					break;
				}
				// out.println("Echo: "+str);
				if ("%1POWR ?".equals(str)) {
					out.println("%1POWR=0");
				} else if ("%1INPT ?".equals(str)) {
					out.println("%1INPT=ERR3");
				} else if ("%1AVMT ?".equals(str)) {
					out.println("%1AVMT=ERR3");
				} else if ("%1ERST ?".equals(str)) {
					out.println("%1ERST=000000");
				} else if ("%1LAMP ?".equals(str)) {
					out.println("%1LAMP=422 0");
				} else if ("%1INST ?".equals(str)) {
					out.println("%1INST=11 12 32 33 41 52");
				} else if ("%1NAME ?".equals(str)) {
					out.println("%1NAME=EBDFE9AE");
				} else if ("%1INFO ?".equals(str)) {
					out.println("%1INFO=102.102.---");
				} else if ("%1INF1 ?".equals(str)) {
					out.println("%1INF1=EPSON");
				} else if ("%1INF2 ?".equals(str)) {
					out.println("%1INF2=EPSON L500");
				} else if ("%1CLSS ?".equals(str)) {
					out.println("%1CLSS=2");
				} else if ("%2INPT ?".equals(str)) {
					out.println("%2INPT=ERR3");
				} else if ("%2INST ?".equals(str)) {
					out.println("%2INST=11 12 32 33 41 52");
				} else if ("%2SNUM ?".equals(str)) {
					out.println("%2SNUM=X5TE80056L");
				} else if ("%2SVER ?".equals(str)) {
					out.println("%2SVER=87009470FJWV102");
				} else if ("%2INNM ?11".equals(str)) {
					out.println("%2INNM=Computer1");
				} else if ("%2IRES ?".equals(str)) {
					out.println("%2IRES=ERR3");
				} else if ("%2RRES ?".equals(str)) {
					out.println("%2RRES=1280x800");
				} else if ("%2FILT ?".equals(str)) {
					out.println("%2FILT=0");
				} else if ("%2RLMP ?".equals(str)) {
					out.println("%2RLMP=ERR1");
				} else if ("%2RFIL ?".equals(str)) {
					out.println("%2RFIL=ELAF56");
				} else if ("%2FREZ ?".equals(str)) {
					out.println("%2FREZ=ERR3");
				}
			}
			System.out.println("closing...");
		} catch (IOException e) {
		} finally {
			try {
				s.close();
			} catch (IOException e) {
			}
		}
	}
}

到这就可以写代码了。

根据挖井人代码我略微的修改了(有小BUG)。

代码如下,首先是PJLink类:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Serializable;
import java.math.BigInteger;
import java.net.Socket;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;


public class PJLink implements Serializable{
    
    
    // PJLink connection.
    private int _TCPPort = 4352;
    private String _ipAddress = "";
    private String _pjlinkPassword = "";
    
    private PJLinkSocket _pjlinkSocket = new PJLinkSocket();
    private PJLinkQueue _pjlinkQueue = new PJLinkQueue();
    private PJLinkRefreshTimer _rft = new PJLinkRefreshTimer();
    
    private ArrayList _pjlinkListeners = new ArrayList();
    
    // Device state.
    private int _powerState = PJlinkCode.POWER_OFF;
    private int _newPowerState = PJlinkCode.POWER_OFF;
    
    private int _activeInput = PJlinkCode.INPUT_RGB_1;
    private int _newActiveInput = PJlinkCode.INPUT_RGB_1;
    
    private boolean _audioMuteActive = false;
    private boolean _audioMuteStateBeforeVideoMuted = false;
    private boolean _newAudioMuteActive = false;
    
    private boolean _videoMuteActive = false;
    private boolean _newVideoMuteActive = false;
    
    private int _lampHours = 0;
    
    boolean _connectionError = false;
    
    int _fanError    = 0;
    int _lampError   = 0;
    int _tempError   = 0;
    int _coverError  = 0;
    int _filterError = 0;
    int _otherError  = 0;
    
    private String INST = null;
    private String NAME = null;
    private String INFO = null;
    private String INF1 = null;
    private String INF2 = null;
    private String CLSS = null;
    private String SNUM = null;
    private String SVER = null;
    private String INNM = null;
    private String IRES = null;
    private String RRES = null;
    private String FILT = null;
    private String RLMP = null;
    private String RFIL = null;
    private String FREZ = null;
    
    // Module settings.
    boolean _printDebug     = false;    // Print debug statements to the console.
    boolean _disablePolling = false;    // Disable polling of the projector state.
    
    
    
    /**
     * Creates an uninitialized PJLink connection.
     * At a minimum, the projector's IP address must be specified
     * before a connection can be established.
     */
    public PJLink() {
    }
    
    /**
     * Creates a PJLink connection to a projector at the specified IP address.
     * The default PJLink port is used.
     * @param ipAddress
     */
    public PJLink(String ipAddress) {
        setIPAddress(ipAddress);
    }
    
    /**
     * Creates a PJLink connection to a projector at the specified IP address and port.
     * @param ipAddress
     * @param port
     */
    public PJLink(String ipAddress, int port) {
        setIPAddress(ipAddress);
        setPort(port);
    }
    
    /**
     * Adds a <code>PJLinkListener</code> to receive changes regarding the projector's state.
     * @param listener
     */
    public void addListener(PJLinkListener listener) {
        if (_pjlinkListeners.contains(listener) == true) return;
        _pjlinkListeners.add(listener);
    }
    
    public void removeListener(PJLinkListener listener) {
        _pjlinkListeners.remove(listener);
    }
    
    private void notifyListeners(PJLinkEvent event) {
        Iterator i = _pjlinkListeners.iterator();
        while (i.hasNext()) {
            ((PJLinkListener) i.next()).deviceStateChanged(this, event);
        }
    }
    
    public String getIPAddress() {
        return _ipAddress;
    }
    
    public int getPort() {
        return _TCPPort;
    }
    
    /**
     * @return Projector is on, off, warming, or cooling.
     */
    public int getPowerState() {
        queryPowerState();
        return _powerState;
    }
    
    public boolean getConnectionError() {
        return _connectionError;
    }
    
    public boolean getPrintDebug() {
        return _printDebug;
    }
    
    public boolean getDisablePolling() {
        return _disablePolling;
    }
    
    
    
    public void powerOn() {
        _pjlinkQueue.push(new PJLinkCommand("%1POWR 1"));
        if (_powerState == PJlinkCode.POWER_OFF) {
            _newPowerState = (_disablePolling == false) ? PJlinkCode.POWER_WARMING : PJlinkCode.POWER_ON;
        }
        if (_disablePolling == false) queryPowerState();
    }
    
    public void powerOff() {
        _pjlinkQueue.push(new PJLinkCommand("%1POWR 0"));
        if (_powerState == PJlinkCode.POWER_ON) {
            _newPowerState = (_disablePolling == false) ? PJlinkCode.POWER_COOLING : PJlinkCode.POWER_OFF;
        }
        if (_disablePolling == false) queryPowerState();
    }
    
    public void switchInput(int input) {
        if (input < 11 || input > 59) return;
        
        _pjlinkQueue.push(new PJLinkCommand("%1INPT " + input));
        _newActiveInput = input;
    }
    
    public void muteAudio() {
        if (_audioMuteActive == true) return;
        _newAudioMuteActive = true;
        sendAVMuteState();
    }
    
    public void unmuteAudio() {
        if (_audioMuteActive == false) return;
        if (_videoMuteActive == false) _newAudioMuteActive = false;
        sendAVMuteState();
    }
    
    public void muteVideo() {
        if (_videoMuteActive == true) return;
        
        // Muting video also mutes audio, but the audio mute
        // state must be retained when video is unmuted again.
        if (_videoMuteActive == false) _audioMuteStateBeforeVideoMuted = _audioMuteActive;
        
        _newAudioMuteActive = true;
        _newVideoMuteActive = true;
        sendAVMuteState();
    }
    
    public void unmuteVideo() {
        if (_videoMuteActive == false) return;
        _newAudioMuteActive = _audioMuteStateBeforeVideoMuted;
        _newVideoMuteActive = false;
        sendAVMuteState();
    }
    
    private void sendAVMuteState() {
        if (_newVideoMuteActive == true) {
            // Mute audio and video.
            _pjlinkQueue.push(new PJLinkCommand("%1AVMT 31"));
        }
        else {
            if (_newAudioMuteActive == true) {
                // Unmute video, leave audio muted.
                _pjlinkQueue.push(new PJLinkCommand("%1AVMT 10"));
                _pjlinkQueue.push(new PJLinkCommand("%1AVMT 21"));
            }
            else {
                // Unmute audio and video.
                _pjlinkQueue.push(new PJLinkCommand("%1AVMT 30"));
            }
        }

        if (_disablePolling == false) queryAVMute();
    }
    
    
    /**
     * Queries projector error status, power state, selected input,
     * A/V mute, and lamp hours. It does <i>not</i> query the input
     * list.
     */
    public void queryAll() {
    	//错误状态
        queryErrorStatus();
        //开关
        queryPowerState();
        //输入信号
        queryInput();
        //音道
        queryAVMute();
        //灯泡时数
        queryLampHours();
        //分辨率
        queryRres();
    }
    public void queryOnce() {
    	//品牌
    	queryName();
    	//信息
    	queryInfo();
    	//信息1(品牌)
    	queryInf1();
    	//信息2(型号)
    	queryInf2();
    	//输入
    	//queryInput2();
    	//输入列表
//    	queryInputList2();
    	//编号
    	querySnum();
    	//版本
    	querySver();
    	//信道名称 参数:输入列表
//    	queryInnm();
    	//未知
    	queryIres();
    	//分辨率
//    	queryRres();
    	//未知
    	queryFILT();
    	//未知
    	queryRLMP();
    	//编号?出厂号?
    	queryRFIL();
    	//未知
    	queryFREZ();
    }
    
    
    public void queryAVMute() {
        _pjlinkQueue.push(new PJLinkCommand("%1AVMT ?"));
    }
    
    public void queryErrorStatus() {
        _pjlinkQueue.push(new PJLinkCommand("%1ERST ?"));
    }
    
    public void queryInput() {
        _pjlinkQueue.push(new PJLinkCommand("%1INPT ?"));
    }
    
    public void queryInputList() {
        _pjlinkQueue.push(new PJLinkCommand("%1INST ?"));
    }
    
    public void queryPowerState() {
        _pjlinkQueue.push(new PJLinkCommand("%1POWR ?"));
    }
    
    public void queryLampHours() {
        _pjlinkQueue.push(new PJLinkCommand("%1LAMP ?"));
    }
    
    
    
    
    //------------------queryOnce----------------
    public void queryName() {
        _pjlinkQueue.push(new PJLinkCommand("%1NAME ?"));
    }
    
    public void queryInfo() {
        _pjlinkQueue.push(new PJLinkCommand("%1INFO ?"));
    }
    
    public void queryInf1() {
        _pjlinkQueue.push(new PJLinkCommand("%1INF1 ?"));
    }
    
    public void queryInf2() {
        _pjlinkQueue.push(new PJLinkCommand("%1INF2 ?"));
    }
    
    public void queryInput2() {
        _pjlinkQueue.push(new PJLinkCommand("%2INPT ?"));
    }
    
    public void queryInputList2() {
        _pjlinkQueue.push(new PJLinkCommand("%2INST ?"));
    }
    
    public void querySnum() {
        _pjlinkQueue.push(new PJLinkCommand("%2SNUM ?"));
    }
    
    public void querySver() {
        _pjlinkQueue.push(new PJLinkCommand("%2SVER ?"));
    }
    
    public void queryInnm(int input) {
        _pjlinkQueue.push(new PJLinkCommand("%2INNM ?"+input));
    }
    
    public void queryIres() {
        _pjlinkQueue.push(new PJLinkCommand("%2IRES ?"));
    }
    
    public void queryRres() {
        _pjlinkQueue.push(new PJLinkCommand("%2RRES ?"));
    }
    
    public void queryFILT() {
        _pjlinkQueue.push(new PJLinkCommand("%2FILT ?"));
    }
    
    public void queryRLMP() {
        _pjlinkQueue.push(new PJLinkCommand("%2RLMP ?"));
    }
    
    public void queryRFIL() {
        _pjlinkQueue.push(new PJLinkCommand("%2RFIL ?"));
    }
    
    public void queryFREZ() {
        _pjlinkQueue.push(new PJLinkCommand("%2FREZ ?"));
    }
    //------------------queryOnce----------------
    public void setPassword(String password) {
        _pjlinkPassword = password;
    }
    
    public void setIPAddress(String ipAddress) {
        _ipAddress = ipAddress;
        if (_ipAddress.length() != 0) {
        	queryAll();
        	queryOnce();
        }
        	
    }
    
    public void setPort(int port) {
        _TCPPort = port;
    }
    
    public void setPrintDebug(boolean value) {
        _printDebug = value;
    }
    
    public void setDisablePolling(boolean value) {
        _disablePolling = value;
    }
    
    
    private void updatePowerState() {
        notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_POWER, _powerState));
    }
    
    private void updateInputState() {
        notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_INPUT, _activeInput));
    }
    
    private void updateAVMuteState() {
        int muteState = PJlinkCode.MUTE_OFF;
        
        if (_videoMuteActive == true && _audioMuteActive == true) {
            muteState = PJlinkCode.MUTE_AUDIO_VIDEO;
        }
        else if (_videoMuteActive == true && _audioMuteActive == false) {
            muteState = PJlinkCode.MUTE_VIDEO_ONLY;
        }
        else if (_videoMuteActive == false && _audioMuteActive == true) {
            muteState = PJlinkCode.MUTE_AUDIO_ONLY;
        }
        
        notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_AV_MUTE, muteState));
    }
    
    
    /**
     * The refresh timer queries all of the projector's parameters
     * at a regular interval. This keeps the instance variables and
     * class's listeners up to date without the need to poll the class.
     */
    private class PJLinkRefreshTimer {
        Timer _pjlinkRefreshTimer = new Timer(true);
        int x = 0;
        
        public PJLinkRefreshTimer () {
            _pjlinkRefreshTimer.scheduleAtFixedRate(new TimerTask() {

                public void run() {
                    if (_ipAddress.length() != 0 && _disablePolling == false) queryAll();
                }
                
            }, 5000, 5000);
            
        }
    }
    
    /**
     * 
     *
     */
    private class PJLinkQueue {
        ArrayList _commandQueue = new ArrayList();
        
        private Thread _queueThread = new Thread(new PJLinkQueueRunner());
        
        public PJLinkQueue() {
            _queueThread.start();
        }
        
        public synchronized void push(PJLinkCommand command) {
            _commandQueue.add(command);
        }
        
        private synchronized PJLinkCommand pop() {
            if (_commandQueue.isEmpty() == true) return null;
            return (PJLinkCommand) _commandQueue.remove(0);
        }
        
        public synchronized boolean isEmpty() {
            return _commandQueue.isEmpty();
        }
        
        private class PJLinkQueueRunner implements Runnable {
            
            public void run() {
                while (true) {
                    if (_commandQueue.isEmpty() == true) {
                        Thread.yield();
                    }
                    else {
                        PJLinkCommand command = (PJLinkCommand) pop();
                        if (command != null) command.execute();
                    }
                }
            }
        }
    }
    
    private class PJLinkSocket {        
        private String _pjlinkKey = "";         // Random number generated by PJLink upon connect.
        
        private Socket _socket = new Socket();
        private BufferedReader _socketReader;
        private PrintWriter _socketWriter;
        private Thread _socketThread;
        private SocketDataListener _socketDataListener;
        
        private MessageDigest _md5;
        
        private boolean _sessionUsesAuthentication = false;
        
        
        // TODO: Turn this into a state machine.
        
        private boolean _socketReadyForCommand = false;     // Projector has responded after opening socket.
        private boolean _socketCommandReceived = true;
        
        private Object _socketLock = new Object();
        
        public PJLinkSocket() {
            try {
                _md5 = MessageDigest.getInstance("MD5");
            }
            catch (NoSuchAlgorithmException e) {
                System.out.println("PJLink error: MD5 encryption not supported. Disable authentication.");
            }
        }
        
        /**
         * 
         * @param command
         * 
         * This method is already called from another thread.
         */
        public void sendCommand(String command) {
            synchronized (_socketLock) {
                // Expires the connection if it stalls.
                Timer connectionExpire = new Timer(false);
                connectionExpire.schedule(new TimerTask() {
                    public void run() {
                        _connectionError = true;
                        
                        if (_printDebug == true) System.out.println("PJLink connection timed out. " + _ipAddress);
                        
                        disconnect();
                        notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_ERROR, PJlinkCode.ERROR_CONNECTION));
                        this.cancel();
                    }
                }, 4000);
                boolean oldConnectionErrorState = _connectionError;
                try {
                    connect();
                    _connectionError = false;
                    while (_socketReadyForCommand == false) Thread.yield();
                    
                    if (_socketWriter != null) {    // This prevents the Duet module from crashing.
                        if (_sessionUsesAuthentication == true) {
                            String pjlinkHash = _pjlinkKey  + _pjlinkPassword;
                            String commandHash = new BigInteger(1, _md5.digest(pjlinkHash.getBytes("ASCII"))).toString(16) + command + "\r";
                            _socketWriter.print(commandHash);
                        }
                        else {
                            _socketWriter.print(command + "\r");
                        }
                        
                        _socketWriter.flush();
                        
                        while (_socketCommandReceived == false) Thread.yield();
                    }
                }
                catch (IOException ex) {
                    _connectionError = true;
                    notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_ERROR, PJlinkCode.ERROR_CONNECTION));
                    
                    
                    if (_printDebug == true) System.out.println("PJLink connection error. " + _ipAddress);
                }
                catch (Exception ex) {
                	_connectionError = true;
                	notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_ERROR, PJlinkCode.ERROR_CONNECTION));
                    
                    if (_printDebug == true) System.out.println("Unknown PJLink connection error. " + _ipAddress);
                }

                if(oldConnectionErrorState&&!_connectionError) {//first online
                	queryOnce();
                }else if(!oldConnectionErrorState&&_connectionError) {//first offline
                	
                }
                
                connectionExpire.cancel();
                
//                boolean oldConnectionErrorState = _connectionError;
//                
//                
//                if (oldConnectionErrorState == true) notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_ERROR, PJLink.ERROR_CONNECTION));
            }
        }
        
        private void connect() throws IOException {
            if (_ipAddress.length() == 0) {
                // Prevent thread from yielding on error.
                _socketReadyForCommand = true;
                _socketCommandReceived = true;
                return;
            }
            
            if (_socket != null) {
                if (_socket.isClosed() == false) {
                    disconnect();
                }
            }
            
            _socket = new Socket(_ipAddress, _TCPPort);
            _socket.setTcpNoDelay(true);
            _socketReader = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
            _socketWriter = new PrintWriter(_socket.getOutputStream(), true);
            
            _sessionUsesAuthentication = false;
            _socketReadyForCommand = false;
            _socketCommandReceived = false;
            _pjlinkKey = "";
            
            _socketDataListener = new SocketDataListener();
            _socketThread = new Thread(_socketDataListener);
            _socketThread.start();
        }
        
        private void disconnect() {
            try {
                _socket.close();
                _socketReader = null;
                _socketWriter = null;
                _socketCommandReceived = true;
                
                _socketReadyForCommand = true;
                _socketCommandReceived = true;
            }
            catch (IOException ex) {
                // Don't care.  Socket is getting destroyed.
            }
        }
        
        /***********************************************************
            Socket Parser
        ***********************************************************/
        private class SocketDataListener implements Runnable {
            
            public void run() {
                String line;
                
                try {
                    while ( _socketReader != null &&
                            _socket != null &&
                            _socket.isClosed() == false &&
                            (line = _socketReader.readLine()) != null) {
                        
                        if (_printDebug == true) {
                            System.out.println("PJLink received: " + line);
                            System.out.flush();
                        }
                        
                        // Projector greeting, no authentication.
                        if (line.startsWith("PJLINK 0")) {
                            _pjlinkKey = "";
                            _sessionUsesAuthentication = false;
                            _socketReadyForCommand = true;
                        }
                        
                        // Projector greeting, authentication challenge.
                        else if (line.startsWith("PJLINK 1 ")) {
                            _pjlinkKey = line.substring(9);
                            _sessionUsesAuthentication = true;
                            _socketReadyForCommand = true;
                        }
                        
                        // PJLink data response.
                        else {
                            // Authentication error.
                            if (line.indexOf(" ERRA") > -1) {
                                System.out.println("PJLink authentication error. " + _ipAddress);
                                _socket.close();
                            }
                            
                            // Undefined command.
                            if (line.endsWith("ERR1")){                                 
                                notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_ERROR, PJlinkCode.ERROR_UNDEFINED_COMMAND));
                            }
                            
                            // Unavailable time.
                            if (line.endsWith("ERR3")){                                 
                                notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_ERROR, PJlinkCode.ERROR_UNAVAILABLE_TIME));
                            }
                            
                            // Projector failure.
                            else if (line.endsWith("ERR4")) {
                                notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_ERROR, PJlinkCode.ERROR_PROJECTOR_FAILURE));
                            }
                            
                            // Power response.
                            else if (line.startsWith("%1POWR=")) {
                                
                                // Accepted power command.
                                if (line.endsWith("OK")) {
                                    _powerState = _newPowerState;
                                    updatePowerState();
                                }
                                
                                // Returned power state value.
                                else {
                                    int powerState = Integer.parseInt(line.substring(7));
                                    _powerState = powerState;
                                    updatePowerState();
                                }
                            }
                            
                            // Input response.
                            else if (line.startsWith("%1INPT=")||line.startsWith("%2INPT=")) {
                                
                                // Accepted input selection.
                                if (line.endsWith("OK")) {
                                    _activeInput = _newActiveInput;
                                    updateInputState();
                                }
                                
                                // Nonexistent input source.
                                else if (line.endsWith("ERR2")) {
                                    _newActiveInput = _activeInput; // Input switch cancelled.
                                    notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_INPUT, PJlinkCode.INPUT_ERROR_NONEXISTENT_SOURCE));
                                }
                                
                                // Returned active input value.
                                else {
                                    int activeInput = Integer.parseInt(line.substring(7, 8));
                                    
                                    if (activeInput > 0) {
                                        _activeInput = activeInput;
                                    }
                                    
                                    updateInputState();
                                }
                            }
                            
                            // A/V mute response.
                            else if (line.startsWith("%1AVMT=")) {                              
                                // Accepted mute instruction.
                                if (line.endsWith("OK")) {
                                    _audioMuteActive = _newAudioMuteActive;
                                    _videoMuteActive = _newVideoMuteActive;
                                    updateAVMuteState();
                                }
                                else if (line.endsWith("ERR2")) {
                                    _newAudioMuteActive = _audioMuteActive;
                                    _newVideoMuteActive = _videoMuteActive;
                                    notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_AV_MUTE, PJlinkCode.MUTE_ERROR_CANNOT_MUTE));
                                }
                                else {
                                    int avmt = Integer.parseInt(line.substring(7,9));
                                    
                                    switch (avmt) {
                                    
                                    case PJlinkCode.MUTE_VIDEO_ONLY:
                                        _videoMuteActive = true;
                                        _audioMuteActive = false;
                                        break;
                                    
                                    case PJlinkCode.MUTE_AUDIO_ONLY:
                                        _videoMuteActive = false;
                                        _audioMuteActive = true;
                                        break;
                                        
                                    case PJlinkCode.MUTE_AUDIO_VIDEO:
                                        _videoMuteActive = true;
                                        _audioMuteActive = true;
                                        break;
                                        
                                    case PJlinkCode.MUTE_OFF:
                                        _videoMuteActive = false;
                                        _audioMuteActive = false;
                                        break;
                                        
                                    default: break;
                                    }
                                    
                                    updateAVMuteState();
                                }
                            }
                            
                            // Error status response.
                            else if (line.startsWith("%1ERST=")) {
                                if (line.length() == 13) {
                                    _fanError = Integer.parseInt(line.substring(7, 8));
                                    _lampError = Integer.parseInt(line.substring(8, 9));
                                    _tempError = Integer.parseInt(line.substring(9, 10));
                                    _coverError = Integer.parseInt(line.substring(10, 11));
                                    _filterError = Integer.parseInt(line.substring(11, 12));
                                    _otherError = Integer.parseInt(line.substring(12, 13));
                                    
                                    // TODO: Refactor error status bit packing.
                                    //       This method will just confuse people who are unfamiliar with binary operations.
                                    //       Make it easy and well-named.
                                    
                                    // Packed bits:
                                    // | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
                                    // |Fail|Unav|Undf|    |  Other  | Filter| Cover |  Temp |  Lamp |  Fan  |
                                    
                                    // Bit 15: Projector Failure
                                    // Bit 14: In Unavailable Time
                                    // Bit 13: Undefined Command
                                    
                                    int packedData =    _fanError       << 0 +
                                                        _lampError      << 2 + 
                                                        _tempError      << 4 +
                                                        _coverError     << 6 +
                                                        _filterError    << 8 +
                                                        _otherError     << 10;
                                    
                                    notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_ERROR, packedData));
                                }
                            }
                            
                            // Lamp status response.
                            else if (line.startsWith("%1LAMP=")) {
                                int hoursEndPos = line.indexOf(' ', 7);
                                
                                if (hoursEndPos > -1) {
                                    _lampHours = Integer.parseInt(line.substring(7, hoursEndPos));
                                    notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_LAMP, _lampHours));
                                }
                            }
                            
                            // Input list response.
                            else if (line.startsWith("%1INST=")||line.startsWith("%2INST=")) {
                                // TODO: Implement list enumeration response.
                            	INST = line.substring(7);
                            	notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_INST, 0,INST));
                            }
                            
                            else if (line.startsWith("%1NAME=")) {
                            	NAME = line.substring(7);
                            	notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_NAME, 0,NAME));
                            }
                            else if (line.startsWith("%1INFO=")) {
                            	INFO = line.substring(7);
                            	notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_INFO, 0,INFO));
                            }
                            else if (line.startsWith("%1INF1=")) {
                            	INF1 = line.substring(7);
                            	notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_INF1, 0,INF1));
                            }
                            else if (line.startsWith("%1INF2=")) {
                            	INF2 = line.substring(7);
                            	notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_INF2, 0,INF2));
                            }
                            else if (line.startsWith("%1CLSS=")) {
                            	CLSS = line.substring(7);
                            	notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_CLSS, 0,CLSS));
                            }
                            else if (line.startsWith("%2SNUM=")) {
                            	SNUM = line.substring(7);
                            	notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_SNUM, 0,SNUM));
                            }
                            else if (line.startsWith("%2SVER=")) {
                            	SVER = line.substring(7);
                            	notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_SVER, 0,SVER));
                            }
                            else if (line.startsWith("%2INNM=")) {
                            	INNM = line.substring(7);
                            	notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_INNM, 0,INNM));
                            }
                            else if (line.startsWith("%2IRES=")) {
                            	IRES = line.substring(7);
                            	notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_IRES, 0,IRES));
                            }
                            else if (line.startsWith("%2FILT=")) {
                            	FILT = line.substring(7);
                            	notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_FILT, 0,FILT));
                            }
                            else if (line.startsWith("%2RLMP=")) {
                            	RLMP = line.substring(7);
                            	notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_RLMP, 0,RLMP));
                            }
                            else if (line.startsWith("%2RFIL=")) {
                            	RFIL = line.substring(7);
                            	notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_RFIL, 0,RFIL));
                            }
                            else if (line.startsWith("%2FREZ=")) {
                            	FREZ = line.substring(7);
                            	notifyListeners(new PJLinkEvent(PJLinkEvent.EVENT_FREZ, 0,FREZ));
                            }
                            
                            _socketCommandReceived = true;
                        }
                    }
                    
                    if (_socket != null) disconnect();
                }
                catch (IOException ex) {
                    
                }
            }
        }
    }
    
    private class PJLinkCommand {
        private String _command = "";
        
        public PJLinkCommand() {
        }
        
        public PJLinkCommand(String command) {
            _command = command;
        }
        
        public void execute() {
            if (_command.length() == 0) return;
            if (_ipAddress.length() == 0) return;
            
            if (_printDebug == true) {
                System.out.println("Executing command: " + _command);
                System.out.flush();
            }
            
            _pjlinkSocket.sendCommand(_command);
        }
    }
}

常量码PJlinkCode:

public class PJlinkCode {
//  Packed error bits:
   // | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
   // |Fail|Unav|Undf|Conn|  Other  | Filter| Cover |  Temp |  Lamp |  Fan  |
   
   // Projector errors.
   // See SocketDataListener private class for bit map.
   public static final int ERROR_FAN_WARNING       = 0x0001;
   public static final int ERROR_FAN_ERROR         = 0x0002;
   public static final int ERROR_LAMP_WARNING      = 0x0004;
   public static final int ERROR_LAMP_ERROR        = 0x0008;
   public static final int ERROR_TEMP_WARNING      = 0x0010;
   public static final int ERROR_TEMP_ERROR        = 0x0020;
   public static final int ERROR_COVER_WARNING     = 0x0040;
   public static final int ERROR_COVER_ERROR       = 0x0080;
   public static final int ERROR_FILTER_WARNING    = 0x0100;
   public static final int ERROR_FILTER_ERROR      = 0x0200;
   public static final int ERROR_OTHER_WARNING     = 0x0400;
   public static final int ERROR_OTHER_ERROR       = 0x0800;
   
   public static final int ERROR_CONNECTION        = 0x1000;
   public static final int ERROR_UNDEFINED_COMMAND = 0x2000;
   public static final int ERROR_UNAVAILABLE_TIME  = 0x4000;
   public static final int ERROR_PROJECTOR_FAILURE = 0x8000;
   
   // Power codes taken from PJLink spec.
   public static final int POWER_OFF           = 0;
   public static final int POWER_ON            = 1;
   public static final int POWER_COOLING       = 2;
   public static final int POWER_WARMING       = 3;
   
   // Input codes taken from PJLink spec.
   public static final int INPUT_ERROR_NONEXISTENT_SOURCE  = 2;
   
   public static final int INPUT_RGB_1         = 11;
   public static final int INPUT_RGB_2         = 12;
   public static final int INPUT_RGB_3         = 13;
   public static final int INPUT_RGB_4         = 14;
   public static final int INPUT_RGB_5         = 15;
   public static final int INPUT_RGB_6         = 16;
   public static final int INPUT_RGB_7         = 17;
   public static final int INPUT_RGB_8         = 18;
   public static final int INPUT_RGB_9         = 19;
   
   public static final int INPUT_VIDEO_1       = 21;
   public static final int INPUT_VIDEO_2       = 22;
   public static final int INPUT_VIDEO_3       = 23;
   public static final int INPUT_VIDEO_4       = 24;
   public static final int INPUT_VIDEO_5       = 25;
   public static final int INPUT_VIDEO_6       = 26;
   public static final int INPUT_VIDEO_7       = 27;
   public static final int INPUT_VIDEO_8       = 28;
   public static final int INPUT_VIDEO_9       = 29;
   
   public static final int INPUT_DIGITAL_1     = 31;
   public static final int INPUT_DIGITAL_2     = 32;
   public static final int INPUT_DIGITAL_3     = 33;
   public static final int INPUT_DIGITAL_4     = 34;
   public static final int INPUT_DIGITAL_5     = 35;
   public static final int INPUT_DIGITAL_6     = 36;
   public static final int INPUT_DIGITAL_7     = 37;
   public static final int INPUT_DIGITAL_8     = 38;
   public static final int INPUT_DIGITAL_9     = 39;
   
   public static final int INPUT_STORAGE_1     = 41;
   public static final int INPUT_STORAGE_2     = 42;
   public static final int INPUT_STORAGE_3     = 43;
   public static final int INPUT_STORAGE_4     = 44;
   public static final int INPUT_STORAGE_5     = 45;
   public static final int INPUT_STORAGE_6     = 46;
   public static final int INPUT_STORAGE_7     = 47;
   public static final int INPUT_STORAGE_8     = 48;
   public static final int INPUT_STORAGE_9     = 49;
   
   public static final int INPUT_NETWORK_1     = 51;
   public static final int INPUT_NETWORK_2     = 52;
   public static final int INPUT_NETWORK_3     = 53;
   public static final int INPUT_NETWORK_4     = 54;
   public static final int INPUT_NETWORK_5     = 55;
   public static final int INPUT_NETWORK_6     = 56;
   public static final int INPUT_NETWORK_7     = 57;
   public static final int INPUT_NETWORK_8     = 58;
   public static final int INPUT_NETWORK_9     = 59;
   
   // A/V Mute codes taken from PJLink spec.
   public static final int MUTE_ERROR_CANNOT_MUTE  = 2;
   
   public static final int MUTE_VIDEO_ONLY     = 11;
   public static final int MUTE_AUDIO_ONLY     = 21;
   public static final int MUTE_AUDIO_VIDEO    = 31;
   public static final int MUTE_OFF            = 30;
   
   
}

然后是事件监听类PJLinkListener:

public interface PJLinkListener {
    public void deviceStateChanged(PJLink source, PJLinkEvent e);
}

事件类:

package com.castle.ream.pjlink.util.pjlink;

public class PJLinkEvent {
    
	
//	public static final int EVENT_CON_ERR   = -1;
//	public static final int EVENT_CON_ON   = -2;
//	public static final int EVENT_CON_PFF   = -3;
//	public static final int EVENT_DEV_ERR   = -4;
	
	
    public static final int EVENT_ERROR   = 0;
    public static final int EVENT_POWER   = 1;
    public static final int EVENT_INPUT   = 2;
    public static final int EVENT_AV_MUTE = 3;
    public static final int EVENT_LAMP    = 4;
    public static final int EVENT_INST    = 5;
    public static final int EVENT_NAME    = 6;
    public static final int EVENT_INFO    = 7;
    public static final int EVENT_INF1    = 8;
    public static final int EVENT_INF2    = 9;
    public static final int EVENT_CLSS    = 10;
    public static final int EVENT_SNUM    = 11;
    public static final int EVENT_SVER    = 12;
    public static final int EVENT_INNM    = 13;
    public static final int EVENT_IRES    = 14;
    public static final int EVENT_FILT    = 15;
    public static final int EVENT_RLMP    = 16;
    public static final int EVENT_RFIL    = 17;
    public static final int EVENT_FREZ    = 18;
    
    private int _eventType;
    private int _data;
    private String _message = "";
    
    public PJLinkEvent(int eventType, int data) {
        _eventType = eventType;
        _data = data;
    }
    
    public PJLinkEvent(int eventType, int data, String message) {
        _eventType = eventType;
        _data = data;
        _message = message;
    }
    
    public int getEventType() {
        return _eventType;
    }
    
    public int getEventData() {
        return _data;
    }
    
    public String getEventMessage() {
        return _message;
    }
}

测试:

public class Test {
	
	public static void main(String[] args) {
		PJLink p = new PJLink("192.168.1.3",5555);
		p.setPrintDebug(true);
		PJLinkListener listener = new PJLinkListener() {
			
			@Override
			public void deviceStateChanged(PJLink p, PJLinkEvent e) {
//				if(arg1 != null && PJLinkEvent.EVENT_ERROR==arg1.getEventType()&& PJLink.ERROR_CONNECTION == arg1.getEventData()) {
//					System.out.println("in...");
//					p.setConnectionError(true);
//				}
				
				int eventCode = e.getEventType();
				switch (eventCode) {
				case PJLinkEvent.EVENT_ERROR:
					int data = e.getEventData();
					switch (data) {
					case PJlinkCode.ERROR_CONNECTION:
						
						break;
					case PJlinkCode.ERROR_UNDEFINED_COMMAND:
						
						break;
					case PJlinkCode.ERROR_UNAVAILABLE_TIME:
						
						break;
					case PJlinkCode.ERROR_PROJECTOR_FAILURE:
						
						break;

					default:
						
						break;
					}
					
					break;
				case PJLinkEvent.EVENT_POWER:
					
					break;
				case PJLinkEvent.EVENT_INPUT:
					
					break;
				case PJLinkEvent.EVENT_AV_MUTE:
					
					break;
				case PJLinkEvent.EVENT_LAMP:
					
					break;
				case PJLinkEvent.EVENT_INST:
					
					break;
				case PJLinkEvent.EVENT_NAME:
					
					break;
				case PJLinkEvent.EVENT_INFO:
					
					break;
				case PJLinkEvent.EVENT_INF1:
					
					break;
				case PJLinkEvent.EVENT_INF2:
					
					break;
				case PJLinkEvent.EVENT_CLSS:
					
					break;
				case PJLinkEvent.EVENT_SNUM:
					
					break;
				case PJLinkEvent.EVENT_SVER:
					
					break;
				case PJLinkEvent.EVENT_INNM:
					
					break;
				case PJLinkEvent.EVENT_IRES:
					
					break;
				case PJLinkEvent.EVENT_FILT:
					
					break;
				case PJLinkEvent.EVENT_RLMP:
					
					break;
				case PJLinkEvent.EVENT_RFIL:
					
					break;
				case PJLinkEvent.EVENT_FREZ:
					
					break;

				default:
					break;
				}
				
			}
		};
		p.addListener(listener);
		while(true){
//			System.out.println(p.getConnectionError());
			System.out.println(RamUsageEstimator.sizeOf(p));
			try {
				Thread.sleep(3000);
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
		
	}

}

添加监听,根据不同的事件类型做出相关的操作,如库操作。

RamUsageEstimator.sizeOf(p)是查看内存对象大小的方法,具体见:点我

启动测试类(PJLINKServer和Test)

告辞!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值