001package jmri.jmrix.lenz.liusbserver; 002 003import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 004import java.nio.charset.StandardCharsets; 005import jmri.jmrix.AbstractMRListener; 006import jmri.jmrix.AbstractMRMessage; 007import jmri.jmrix.lenz.XNetPacketizer; 008import org.slf4j.Logger; 009import org.slf4j.LoggerFactory; 010 011/** 012 * This is an extension of the XNetPacketizer to handle the device specific 013 * requirements of the LIUSB Server. 014 * <p> 015 * In particular, LIUSBServerXNetPacketizer counts the number of commands 016 * received. 017 * 018 * @author Paul Bender, Copyright (C) 2009 019 * 020 */ 021public class LIUSBServerXNetPacketizer extends XNetPacketizer { 022 023 public LIUSBServerXNetPacketizer(jmri.jmrix.lenz.LenzCommandStation pCommandStation) { 024 super(pCommandStation); 025 log.debug("Loading LIUSB Server Extension to XNetPacketizer"); 026 } 027 028 /** 029 * Actually transmits the next message to the port 030 */ 031 @SuppressFBWarnings(value = {"UW_UNCOND_WAIT"}, 032 justification = "Wait is for external hardware, which doesn't necessarilly respond, to process the data.") 033 034 @Override 035 protected void forwardToPort(AbstractMRMessage m, AbstractMRListener reply) { 036 log.debug("forwardToPort message: [{}]", m); 037 // remember who sent this 038 mLastSender = reply; 039 040 // forward the message to the registered recipients, 041 // which includes the communications monitor, except the sender. 042 // Schedule notification via the Swing event queue to ensure order 043 Runnable r = new XmtNotifier(m, mLastSender, this); 044 javax.swing.SwingUtilities.invokeLater(r); 045 046 // stream the bytes 047 try { 048 if (ostream != null) { 049 while (m.getRetries() >= 0) { 050 if (portReadyToSend(controller)) { 051 ostream.write((m + "\n\r").getBytes(StandardCharsets.UTF_8)); 052 ostream.flush(); 053 log.debug("written"); 054 break; 055 } else if (m.getRetries() >= 0) { 056 if (log.isDebugEnabled()) { 057 log.debug("Retry message: {} attempts remaining: {}", m.toString(), m.getRetries()); 058 } 059 m.setRetries(m.getRetries() - 1); 060 try { 061 synchronized (xmtRunnable) { 062 xmtRunnable.wait(m.getTimeout()); 063 } 064 } catch (InterruptedException e) { 065 Thread.currentThread().interrupt(); // retain if needed later 066 log.error("retry wait interrupted"); 067 } 068 } else { 069 log.warn("sendMessage: port not ready for data sending: {}", m.toString()); 070 } 071 } 072 } else { // ostream is null 073 // no stream connected 074 connectionWarn(); 075 } 076 } catch (java.io.IOException e) { 077 // start the recovery process if an exception occurs. 078 portWarn(e); 079 controller.recover(); 080 } 081 } 082 083 private static final Logger log = LoggerFactory.getLogger(LIUSBServerXNetPacketizer.class); 084 085}