001package jmri.jmris.srcp; 002 003import java.beans.PropertyChangeEvent; 004import java.io.DataInputStream; 005import java.io.IOException; 006import java.io.OutputStream; 007 008import jmri.InstanceManager; 009import jmri.Turnout; 010import jmri.jmris.AbstractTurnoutServer; 011import jmri.SystemConnectionMemo; 012import org.slf4j.Logger; 013import org.slf4j.LoggerFactory; 014 015/** 016 * SRCP Server interface between the JMRI Turnout manager and a network 017 * connection 018 * 019 * @author Paul Bender Copyright (C) 2010-2013 020 */ 021public class JmriSRCPTurnoutServer extends AbstractTurnoutServer { 022 023 private OutputStream output; 024 025 public JmriSRCPTurnoutServer(DataInputStream inStream, OutputStream outStream) { 026 output = outStream; 027 } 028 029 /* 030 * Protocol Specific Abstract Functions 031 */ 032 @Override 033 public void sendStatus(String turnoutName, int Status) throws IOException { 034 output.write("499 ERROR unspecified error\n\r".getBytes()); 035 } 036 037 public void sendStatus(int bus, int address) throws IOException { 038 log.debug("send Status called with bus {} and address {}", bus, address); 039 java.util.List<SystemConnectionMemo> list = InstanceManager.getList(SystemConnectionMemo.class); 040 SystemConnectionMemo memo = null; 041 try { 042 memo = list.get(bus - 1); 043 } catch (java.lang.IndexOutOfBoundsException obe) { 044 output.write("412 ERROR wrong value\n\r".getBytes()); 045 return; 046 } 047 String turnoutName = memo.getSystemPrefix() 048 + "T" + address; 049 try { 050 // busy loop, wait for turnout to settle before continuing. 051 while (InstanceManager.turnoutManagerInstance().provideTurnout(turnoutName).getKnownState() != InstanceManager.turnoutManagerInstance().provideTurnout(turnoutName).getCommandedState()) { 052 } 053 int Status = InstanceManager.turnoutManagerInstance().provideTurnout(turnoutName).getKnownState(); 054 if (Status == Turnout.THROWN) { 055 output.write(("100 INFO " + bus + " GA " + address + " 1 0\n\r").getBytes()); 056 } else if (Status == Turnout.CLOSED) { 057 output.write(("100 INFO " + bus + " GA " + address + " 0 0\n\r").getBytes()); 058 } else { 059 // unknown state 060 output.write("411 ERROR unknown value\n\r".getBytes()); 061 } 062 } catch (IllegalArgumentException ex) { 063 log.warn("Failed to provide Turnout \"{}\" in sendStatus", turnoutName); 064 } 065 } 066 067 @Override 068 public void sendErrorStatus(String turnoutName) throws IOException { 069 output.write("499 ERROR unspecified error\n\r".getBytes()); 070 } 071 072 @Override 073 public void parseStatus(String statusString) throws jmri.JmriException, java.io.IOException { 074 output.write("499 ERROR unspecified error\n\r".getBytes()); 075 } 076 077 /* 078 * Initialize an SRCP server turnout. Constructs the system name 079 * string from the provided parameters. 080 */ 081 public void initTurnout(int bus, int address, String protocol) throws jmri.JmriException, java.io.IOException { 082 083 log.debug("init Turnout called with bus {} address {} and protocol {}", bus, address, protocol); 084 java.util.List<SystemConnectionMemo> list = InstanceManager.getList(SystemConnectionMemo.class); 085 SystemConnectionMemo memo; 086 try { 087 memo = list.get(bus - 1); 088 } catch (java.lang.IndexOutOfBoundsException obe) { 089 output.write("412 ERROR wrong value\n\r".getBytes()); 090 return; 091 } 092 String turnoutName = memo.getSystemPrefix() 093 + "T" + address; 094 // create turnout if it does not exist. 095 this.initTurnout(turnoutName); 096 output.write(("101 INFO " + bus + " GA " + address + " " + protocol + "\n\r").getBytes()); 097 } 098 099 /* 100 * for SRCP, we're doing the parsing elsewhere, so we just need to build 101 * the correct string from the provided compoents. 102 */ 103 public void parseStatus(int bus, int address, int value) throws jmri.JmriException, java.io.IOException { 104 105 log.debug("parse Status called with bus {} address {} and value {}", bus, address, value); 106 java.util.List<SystemConnectionMemo> list = InstanceManager.getList(SystemConnectionMemo.class); 107 SystemConnectionMemo memo; 108 try { 109 memo = list.get(bus - 1); 110 } catch (java.lang.IndexOutOfBoundsException obe) { 111 output.write("412 ERROR wrong value\n\r".getBytes()); 112 return; 113 } 114 String turnoutName = memo.getSystemPrefix() 115 + "T" + address; 116 if (value == 1) { 117 log.debug("Setting Turnout THROWN"); 118 throwTurnout(turnoutName); 119 } else if (value == 0) { 120 log.debug("Setting Turnout CLOSED"); 121 closeTurnout(turnoutName); 122 } 123 sendStatus(bus, address); 124 } 125 126 @Override 127 protected TurnoutListener getListener(String turnoutName) { 128 return new TurnoutListener(turnoutName); 129 } 130 131 class TurnoutListener extends AbstractTurnoutServer.TurnoutListener { 132 133 TurnoutListener(String turnoutName) { 134 super(turnoutName); 135 } 136 137 // update state as state of turnout changes 138 @Override 139 public void propertyChange(PropertyChangeEvent e) { 140 // If the Commanded State changes, show transition state as "<inconsistent>" 141 if (e.getPropertyName().equals("KnownState")) { 142 try { 143 String Name = ((jmri.Turnout) e.getSource()).getSystemName(); 144 java.util.List<SystemConnectionMemo> List = InstanceManager.getList(SystemConnectionMemo.class); 145 int i = 0; 146 int address; 147 for (Object memo : List) { 148 String prefix = memo.getClass().getName(); 149 if (Name.startsWith(prefix)) { 150 address = Integer.parseInt(Name.substring(prefix.length())); 151 sendStatus(i, address); 152 break; 153 } 154 i++; 155 } 156 } catch (java.io.IOException ie) { 157 log.error("Error Sending Status"); 158 } 159 } 160 } 161 } 162 private final static Logger log = LoggerFactory.getLogger(JmriSRCPTurnoutServer.class); 163}