001package jmri.web.servlet.simple; 002 003import java.io.IOException; 004import javax.servlet.annotation.WebServlet; 005import javax.servlet.http.HttpServlet; 006import javax.servlet.http.HttpServletRequest; 007import javax.servlet.http.HttpServletResponse; 008import jmri.InstanceManager; 009import jmri.JmriException; 010import jmri.jmris.JmriConnection; 011import jmri.jmris.simpleserver.SimpleLightServer; 012import jmri.jmris.simpleserver.SimpleOperationsServer; 013import jmri.jmris.simpleserver.SimplePowerServer; 014import jmri.jmris.simpleserver.SimpleReporterServer; 015import jmri.jmris.simpleserver.SimpleSensorServer; 016import jmri.jmris.simpleserver.SimpleSignalHeadServer; 017import jmri.jmris.simpleserver.SimpleTurnoutServer; 018import jmri.util.FileUtil; 019import jmri.util.node.NodeIdentity; 020import jmri.web.server.WebServerPreferences; 021import jmri.web.servlet.ServletUtil; 022import org.eclipse.jetty.websocket.api.Session; 023import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; 024import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError; 025import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; 026import org.eclipse.jetty.websocket.api.annotations.WebSocket; 027import org.eclipse.jetty.websocket.servlet.WebSocketServlet; 028import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; 029import org.openide.util.lookup.ServiceProvider; 030import org.slf4j.Logger; 031import org.slf4j.LoggerFactory; 032 033/** 034 * WebSocket servlet for JMRI Simple service protocol. 035 * 036 * @author Randall Wood (c) 2016 037 */ 038@WebServlet(name = "SimpleServlet", 039 urlPatterns = {"/simple"}) 040@ServiceProvider(service = HttpServlet.class) 041public class SimpleServlet extends WebSocketServlet { 042 043 private static final Logger log = LoggerFactory.getLogger(SimpleServlet.class); 044 045 @Override 046 public void configure(WebSocketServletFactory factory) { 047 factory.register(SimpleWebSocket.class); 048 } 049 050 @Override 051 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { 052 response.setStatus(HttpServletResponse.SC_OK); 053 response.setContentType(ServletUtil.UTF8_TEXT_HTML); // NOI18N 054 response.getWriter().print(String.format(request.getLocale(), 055 FileUtil.readURL(FileUtil.findURL(Bundle.getMessage(request.getLocale(), "Simple.html"))), 056 String.format(request.getLocale(), 057 Bundle.getMessage(request.getLocale(), "HtmlTitle"), 058 InstanceManager.getDefault(ServletUtil.class).getRailroadName(false), 059 Bundle.getMessage(request.getLocale(), "SimpleTitle") 060 ), 061 InstanceManager.getDefault(ServletUtil.class).getNavBar(request.getLocale(), request.getContextPath()), 062 InstanceManager.getDefault(ServletUtil.class).getRailroadName(false), 063 InstanceManager.getDefault(ServletUtil.class).getFooter(request.getLocale(), request.getContextPath()) 064 )); 065 } 066 067 @WebSocket 068 public static class SimpleWebSocket { 069 070 private JmriConnection connection; 071 private Runnable shutDownTask; 072 private SimpleLightServer lightServer; 073 private SimpleOperationsServer operationsServer; 074 private SimplePowerServer powerServer; 075 private SimpleReporterServer reporterServer; 076 private SimpleSensorServer sensorServer; 077 private SimpleSignalHeadServer signalHeadServer; 078 private SimpleTurnoutServer turnoutServer; 079 080 public void sendMessage(String message) throws IOException { 081 this.connection.sendMessage(message); 082 } 083 084 @OnWebSocketConnect 085 public void onOpen(Session cnctn) { 086 this.connection = new JmriConnection(cnctn); 087 this.shutDownTask = () -> SimpleWebSocket.this.connection.getSession().close(); 088 this.lightServer = new SimpleLightServer(this.connection); 089 this.operationsServer = new SimpleOperationsServer(this.connection); 090 this.powerServer = new SimplePowerServer(this.connection); 091 this.reporterServer = new SimpleReporterServer(this.connection); 092 this.sensorServer = new SimpleSensorServer(this.connection); 093 this.signalHeadServer = new SimpleSignalHeadServer(this.connection); 094 this.turnoutServer = new SimpleTurnoutServer(this.connection); 095 try { 096 this.connection.sendMessage("JMRI " + jmri.Version.name() + " \n"); 097 this.connection.sendMessage("RAILROAD " + InstanceManager.getDefault(WebServerPreferences.class).getRailroadName() + " \n"); 098 this.connection.sendMessage("NODE " + NodeIdentity.networkIdentity() + " \n"); 099 } catch (IOException e) { 100 log.warn("Closing Session due to ", e); 101 this.connection.getSession().close(); 102 } 103 InstanceManager.getDefault(jmri.ShutDownManager.class).register(this.shutDownTask); 104 } 105 106 @OnWebSocketError 107 public void onError(Throwable thrwbl) { 108 log.error("Socket Error: ", thrwbl); 109 } 110 111 @OnWebSocketMessage 112 public void onMessage(String string) { 113 log.debug("Received from client: {}", string); 114 try { 115 if (string.startsWith("POWER")) { 116 this.powerServer.parseStatus(string); 117 this.powerServer.sendStatus(InstanceManager.getDefault(jmri.PowerManager.class).getPower()); 118 } else if (string.startsWith("TURNOUT")) { 119 this.turnoutServer.parseStatus(string); 120 } else if (string.startsWith("LIGHT")) { 121 this.lightServer.parseStatus(string); 122 } else if (string.startsWith("SENSOR")) { 123 this.sensorServer.parseStatus(string); 124 } else if (string.startsWith("SIGNALHEAD")) { 125 this.signalHeadServer.parseStatus(string); 126 } else if (string.startsWith("REPORTER")) { 127 this.reporterServer.parseStatus(string); 128 } else if (string.startsWith(SimpleOperationsServer.OPERATIONS)) { 129 this.operationsServer.parseStatus(string); 130 } else { 131 this.connection.sendMessage("Unknown Command " + string + "\n"); 132 } 133 } catch (JmriException je) { 134 try { 135 this.connection.sendMessage("not supported\n"); 136 } catch (IOException ie) { 137 log.warn("Closing Connection due to Exception", ie); 138 this.connection.getSession().close(); 139 InstanceManager.getDefault(jmri.ShutDownManager.class).deregister(this.shutDownTask); 140 } 141 } catch (IOException ie) { 142 log.warn("Closing Connection due to Exception", ie); 143 this.connection.getSession().close(); 144 InstanceManager.getDefault(jmri.ShutDownManager.class).deregister(this.shutDownTask); 145 } 146 } 147 } 148}