/** * Copyright (C) 2014 KAIST * @author Janggwan Im <limg00n@kaist.ac.kr> * */ package org.fosstrak.ale.server.readers.llrp; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.InetSocketAddress; import java.util.Properties; import kr.ac.kaist.resl.fosstrak.ale.ReaderImpl; import kr.ac.kaist.resl.ltk.generated.LLRPMessageFactory; import kr.ac.kaist.resl.ltk.generated.messages.GET_READER_CAPABILITIES_RESPONSE; import kr.ac.kaist.resl.ltk.generated.messages.GET_READER_CONFIG; import kr.ac.kaist.resl.ltk.generated.messages.GET_READER_CONFIG_RESPONSE; import kr.ac.kaist.resl.ltk.generated.messages.KEEPALIVE; import kr.ac.kaist.resl.ltk.generated.messages.KEEPALIVE_ACK; import kr.ac.kaist.resl.ltk.generated.messages.READER_EVENT_NOTIFICATION; import kr.ac.kaist.resl.ltk.generated.messages.SET_READER_CONFIG_RESPONSE; import kr.ac.kaist.resl.ltk.generated.parameters.ConnectionAttemptEvent; import kr.ac.kaist.resl.ltk.generated.parameters.ReaderEventNotificationData; import kr.ac.kaist.resl.ltk.net.LLRPEndpoint; import kr.ac.kaist.resl.ltk.net.LLRPIoHandlerAdapterImpl; import org.apache.log4j.Logger; import org.apache.mina.core.session.IoSession; import org.fosstrak.ale.server.ALEApplicationContext; import org.jdom.Document; import org.jdom.JDOMException; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; import org.llrp.ltk.exceptions.InvalidLLRPMessageException; import org.llrp.ltk.types.LLRPMessage; public class ReaderInitiatedLLRPIoHandlerAdapter extends LLRPIoHandlerAdapterImpl implements LLRPEndpoint {//LLRPIoHandlerAdapterImpl implements LLRPEndpoint { /** logger. */ private static final Logger log = Logger.getLogger(ReaderInitiatedLLRPIoHandlerAdapter.class); /** the path to the properties file for the LLRPAdaptor. */ private static final String LLRPADAPTOR_CONFIG_FILE = "/LLRPAdaptorConfig.properties"; /** * to define and undefine ReaderImpl object */ private LLRPManager manager = null; public LLRPManager getManager() { if(manager == null) { manager = ALEApplicationContext.getBean(LLRPManager.class); } return manager; } @Override public void messageReceived(IoSession arg0, Object arg1) throws Exception { InetSocketAddress inetAddr = (InetSocketAddress)arg0.getRemoteAddress(); String addr = inetAddr.getHostString(); int port = inetAddr.getPort(); LLRPMessage llrpMessage = (LLRPMessage) arg1; log.info("message "+arg1.getClass()+" received in session "+arg0); if (log.isDebugEnabled()) { if(!(llrpMessage instanceof KEEPALIVE)) log.debug(llrpMessage.toXMLString()); } if(arg1 instanceof READER_EVENT_NOTIFICATION) { ReaderEventNotificationData data = null; if((data = ((READER_EVENT_NOTIFICATION)arg1).getReaderEventNotificationData()) != null) { ConnectionAttemptEvent connectionAttemptEvent = null; if((connectionAttemptEvent = data.getConnectionAttemptEvent()) != null) { //System.out.println(connectionAttemptEvent.getStatus().getName(ConnectionAttemptStatusType.Success)); log.debug("READER_EVENT_NOTIFICATION received. send GET_READER_CONFIG"); GET_READER_CONFIG msg = (GET_READER_CONFIG) loadXMLLLRPMessage(PhysicalReaderAcceptor.class.getResourceAsStream("/llrp/GET_READER_CONFIG.xml")); arg0.write(msg); return; } } } else if(arg1 instanceof GET_READER_CAPABILITIES_RESPONSE) { // do nothing } else if(arg1 instanceof GET_READER_CONFIG_RESPONSE) { GET_READER_CONFIG_RESPONSE resp = ((GET_READER_CONFIG_RESPONSE)arg1); if(resp.getLLRPStatus() != null) { if(resp.getLLRPStatus().getStatusCode() != null) { if(resp.getLLRPStatus().getStatusCode().toString().equals("M_Success")) { if(resp.getIdentification() != null) { String idType = null; String readerId = null; if(resp.getIdentification().getIDType() != null) { idType = resp.getIdentification().getIDType().toString(); } if(resp.getIdentification().getReaderID() != null) { readerId = resp.getIdentification().getReaderID().toString(); } if(idType != null && readerId != null) { String physicalReaderId = readerId; log.debug("reader (id: "+readerId+", ip: "+addr+" port: "+port+") is connected"); // create reader-initiated connection and store it in the map ReaderInitiatedConnectionEntry entry = new ReaderInitiatedConnectionEntry(physicalReaderId, idType, addr, port, this, this, arg0); PhysicalReaderAcceptor.mapIdAndReaderInitiatedConnectionEntry.put(physicalReaderId, entry); // if there exists ReaderImpl (internal object which is 1:1 correspondence with LLRPAdaptor/LRSpec) which is related to this reader, // set this reader's endpoint to ReaderImpl, // and ReaderImpl's connection to this reader's connection // because there is 1:N relationship between this reader and ReaderImpl, endpoints need to be multiplexed for(String definedReaderName : getManager().getAdaptor().getReaderNames()) { log.debug("checking this reader's ReaderImpl object"); // definedReaderName has the form of physicalReaderId+"___"+AntennaId // for example, definedReaderName is 000011112222333344445555___1,2 // check whether the name starts with physicalReaderId // if so, set connection for the reader and endpoint (reader) for the connection if(definedReaderName.startsWith(physicalReaderId)) { log.debug("this reader's ReaderImpl object: "+definedReaderName); ReaderImpl reader = (ReaderImpl)getManager().getAdaptor().getReader(definedReaderName); //reader.setConnection(getConnection()); reader.setIoSession(arg0); // we need to multiplex one reader connection to multiple ReaderImpls // because there can be multiple ReaderImpls due to different antennas entry.getEndpoint().addLLRPEndpoint(reader); } } // restore previously-defined LLRP Specs try { String[] llrpSpecList = getLlrpSpecList(); for(String llrpSpecToDefine : llrpSpecList) { log.info("define "+llrpSpecToDefine); if(llrpSpecToDefine.equals("")) continue; LLRPMessage msg = loadXMLLLRPMessage(PhysicalReaderAcceptor.class.getResourceAsStream("/llrp/"+llrpSpecToDefine)); arg0.write(msg); Thread.sleep(500); } /* SET_READER_CONFIG msgSetReaderConfigKeepalive = (SET_READER_CONFIG) loadXMLLLRPMessage(PhysicalReaderAcceptor.class.getResourceAsStream("/llrp/SET_READER_CONFIG_KEEPALIVE.xml")); //arg0.write(msgSetReaderConfigKeepalive); // set keep alive message Thread.sleep(500); DELETE_ROSPEC msgDeleteRospec = (DELETE_ROSPEC) loadXMLLLRPMessage(PhysicalReaderAcceptor.class.getResourceAsStream("/llrp/DELETE_ROSPEC.xml")); arg0.write(msgDeleteRospec); // delete ROSpec whose message ID is 1 Thread.sleep(500); DELETE_ROSPEC msgDeleteRospec2 = (DELETE_ROSPEC) loadXMLLLRPMessage(PhysicalReaderAcceptor.class.getResourceAsStream("/llrp/DELETE_ROSPEC_2.xml")); arg0.write(msgDeleteRospec2); // delete ROSpec whose message ID is 1 Thread.sleep(500); LLRPMessage msgAddRospec = loadXMLLLRPMessage(PhysicalReaderAcceptor.class.getResourceAsStream("/llrp/ADD_ROSPEC.xml")); arg0.write(msgAddRospec); Thread.sleep(500); LLRPMessage msgAddRospecGpi = loadXMLLLRPMessage(PhysicalReaderAcceptor.class.getResourceAsStream("/llrp/ADD_ROSPEC_GPIEvent.xml")); arg0.write(msgAddRospecGpi); Thread.sleep(500); DELETE_ACCESSSPEC msgDelAccessspec = new DELETE_ACCESSSPEC(); msgDelAccessspec.setAccessSpecID(new UnsignedInteger(3)); arg0.write(msgDelAccessspec); Thread.sleep(500); LLRPMessage msgAddAccessspec = loadXMLLLRPMessage(PhysicalReaderAcceptor.class.getResourceAsStream("/llrp/ADD_ACCESSSPEC3.xml")); arg0.write(msgAddAccessspec); Thread.sleep(500); ENABLE_ACCESSSPEC msgEnableAccessSpec = new ENABLE_ACCESSSPEC(); msgEnableAccessSpec.setAccessSpecID(new UnsignedInteger(3)); arg0.write(msgEnableAccessSpec); Thread.sleep(500); LLRPMessage msgEnableRospec = loadXMLLLRPMessage(PhysicalReaderAcceptor.class.getResourceAsStream("/llrp/ENABLE_ROSPEC.xml")); arg0.write(msgEnableRospec); Thread.sleep(500); ENABLE_ROSPEC msgEnableRospec2 = (ENABLE_ROSPEC) loadXMLLLRPMessage(PhysicalReaderAcceptor.class.getResourceAsStream("/llrp/ENABLE_ROSPEC.xml")); msgEnableRospec2.setROSpecID(new UnsignedInteger(2)); arg0.write(msgEnableRospec2); Thread.sleep(500); //File fileStartRospec = convertInputStreamToFile(getClass().getResourceAsStream("/llrp/START_ROSPEC.xml")); //LLRPMessage msgStartRospec = Util.loadXMLLLRPMessage(fileStartRospec); //getConnection().send(msgStartRospec); //Thread.sleep(500); */ } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (JDOMException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvalidLLRPMessageException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } // restore LLRP specs which were defined in LLRPAdaptor for(String definedReaderName : getManager().getAdaptor().getReaderNames()) { if(definedReaderName.startsWith(physicalReaderId)) { ReaderImpl reader = (ReaderImpl)getManager().getAdaptor().getReader(definedReaderName); reader.getLlrpAdaptor().restoreLLRPSpecs(); } } } } } else { throw new Exception("GET_READER_CONFIG_RESPONSE is not successful"); } } } } else if (arg1 instanceof KEEPALIVE) { log.debug("KEEPALIVE message received. write KEEPALIVE_ACK back"); KEEPALIVE_ACK kack = new KEEPALIVE_ACK(); arg0.write(kack); } else if(arg1 instanceof SET_READER_CONFIG_RESPONSE) { log.debug("SET_READER_CONFIG_RESPONSE is received: "+((SET_READER_CONFIG_RESPONSE)arg1).toXMLString()); } // instead of super.messageReceived(arg0, arg1); MultipleLLRPEndpoint endpoint = PhysicalReaderAcceptor.mapIdAndReaderInitiatedConnectionEntry.getMultipleLLRPEndpointByIpPort(addr, port); if(endpoint != null) endpoint.messageReceived(llrpMessage); } @Override public void sessionOpened(IoSession session) throws Exception { super.sessionOpened(session); log.debug("Reader-initiated connection session opened ("+((InetSocketAddress)session.getRemoteAddress()).getHostString()+":"+((InetSocketAddress)session.getRemoteAddress()).getPort()+")"); // send GET_READER_CONFIG //File file = convertInputStreamToFile(getClass().getResourceAsStream("/llrp/GET_READER_CONFIG.xml")); //GET_READER_CONFIG msg = (GET_READER_CONFIG) Util.loadXMLLLRPMessage(file); } public LLRPMessage loadXMLLLRPMessage(InputStream is) throws FileNotFoundException, IOException, JDOMException, InvalidLLRPMessageException { Document doc = new org.jdom.input.SAXBuilder().build(new InputStreamReader(is)); XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat()); log.debug("Loaded XML Message: " + outputter.outputString(doc)); LLRPMessage message = LLRPMessageFactory.createLLRPMessage(doc); return message; } @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { if(session != null && session.getRemoteAddress() != null) { log.debug("exception in the connection ("+((InetSocketAddress)session.getRemoteAddress()).getHostString()+":"+((InetSocketAddress)session.getRemoteAddress()).getPort()+")"); } else { log.debug("exception in the connection but session is null"); } //InetSocketAddress addr = (InetSocketAddress)session.getRemoteAddress(); cause.printStackTrace(); //getConnectionAttemptEventQueue().clear(); //getSynMessageQueue().clear(); session.close(true);//.close(); super.exceptionCaught(session, cause); } @Override public void errorOccured(String arg0) { log.debug("error occured in default handler : "+arg0); } @Override public void messageReceived(LLRPMessage arg0) { log.debug("message received in default handler : "+arg0); } private String[] getLlrpSpecList() { Properties props = new Properties(); try { props.load(LLRPAdaptor.class.getResourceAsStream(LLRPADAPTOR_CONFIG_FILE)); } catch (Exception e) { e.printStackTrace(); } String llrpSpecFiles = props.getProperty("llrpSpecFiles"); llrpSpecFiles = llrpSpecFiles.replaceAll("\\s",""); String[] specFilenames = llrpSpecFiles.split(","); return specFilenames; } }