001package jmri.jmrix.cmri.serial.serialdriver.configurexml; 002 003import java.util.List; 004import java.util.StringTokenizer; 005 006import jmri.jmrix.AbstractSerialConnectionConfig; 007import jmri.jmrix.cmri.CMRISystemConnectionMemo; 008import jmri.jmrix.cmri.serial.SerialNode; 009import jmri.jmrix.cmri.serial.SerialTrafficController; 010import jmri.jmrix.cmri.serial.serialdriver.ConnectionConfig; 011import jmri.jmrix.cmri.serial.serialdriver.SerialDriverAdapter; 012import jmri.jmrix.configurexml.AbstractSerialConnectionConfigXml; 013import jmri.jmrix.cmri.serial.cmrinetmetrics.CMRInetMetricsCollector; 014import org.jdom2.Element; 015 016/** 017 * Handle XML persistence of layout connections by persisting the 018 * SerialDriverAdapter (and connections). Note this is named as the XML version 019 * of a ConnectionConfig object, but it's actually persisting the 020 * SerialDriverAdapter. 021 * <p> 022 * This class is invoked from {@link jmri.jmrix.configurexml.JmrixConfigPaneXml} 023 * on write, as that class is the one actually registered. Reads are brought 024 * here directly via the class attribute in the XML. 025 * 026 * @author Bob Jacobsen Copyright: Copyright (c) 027 * @author Chuck Catania Copyright: Copyright (c) 2014, 2015, 2016, 2017 028 * 029 */ 030public class ConnectionConfigXml extends AbstractSerialConnectionConfigXml { 031 032 public ConnectionConfigXml() { 033 super(); 034 } 035 036 CMRInetMetricsCollector metricsCollector; 037 038 /** 039 * Write out the SerialNode objects too 040 * 041 * @param e Element being extended 042 */ 043 @Override 044 protected void extendElement(Element e) { 045 // Create a polling list from the configured nodes 046 StringBuilder polllist = new StringBuilder(""); 047 SerialTrafficController tcPL = ((CMRISystemConnectionMemo) adapter.getSystemConnectionMemo()).getTrafficController(); 048 SerialNode plNode = (SerialNode) tcPL.getNode(0); 049 int index = 1; 050 while (plNode != null) { 051 if (index != 1) { 052 polllist.append(","); 053 } 054 polllist.append(Integer.toString(plNode.getNodeAddress())); 055 plNode = (SerialNode) tcPL.getNode(index); 056 index++; 057 } 058 059 Element l = new Element("polllist"); 060 l.setAttribute("pollseq", polllist.toString()); 061 e.addContent(l); 062 063 SerialTrafficController tc = ((CMRISystemConnectionMemo) adapter.getSystemConnectionMemo()).getTrafficController(); 064 SerialNode node = (SerialNode) tc.getNode(0); 065 index = 1; 066 067 while (node != null) { 068 // add node as an element 069 Element n = new Element("node"); 070 n.setAttribute("name", Integer.toString(node.getNodeAddress())); 071 e.addContent(n); 072 // add parameters to the node as needed 073 n.addContent(makeParameter("nodetype", Integer.toString(node.getNodeType()))); 074 n.addContent(makeParameter("bitspercard", Integer.toString(node.getNumBitsPerCard()))); 075 n.addContent(makeParameter("transmissiondelay", Integer.toString(node.getTransmissionDelay()))); 076 n.addContent(makeParameter("num2lsearchlights", Integer.toString(node.getNum2LSearchLights()))); 077 n.addContent(makeParameter("pulsewidth", Integer.toString(node.getPulseWidth()))); 078 079 StringBuilder value = new StringBuilder(); 080 for (int i = 0; i < node.getLocSearchLightBits().length; i++) { 081 value.append(Integer.toHexString(node.getLocSearchLightBits()[i] & 0xF)); 082 } 083 n.addContent(makeParameter("locsearchlightbits", value.toString())); 084 value = new StringBuilder(); 085 for (int i = 0; i < node.getCardTypeLocation().length; i++) { 086 value.append(Integer.toHexString(node.getCardTypeLocation()[i] & 0xF)); 087 } 088 n.addContent(makeParameter("cardtypelocation", value.toString())); 089 log.debug("Node {} Card Type Written = {}", node.nodeAddress, value); 090 091 // CMRInet Options 092 value = new StringBuilder(""); 093 for (int i = 0; i < SerialNode.NUMCMRINETOPTS; i++) { 094 value.append(Integer.toHexString((node.getCMRInetOpts(i) & 0xF))); 095 } 096 n.addContent(makeParameter("cmrinetoptions", value.toString().toUpperCase())); 097 log.debug("Node {} NET Options Written = {}", node.nodeAddress, value); 098 099 // cpNode Options Classic CMRI nodes do not have options 100 if (node.getNodeType() == SerialNode.CPNODE || node.getNodeType() == SerialNode.CPMEGA) { 101 value = new StringBuilder(); 102 for (int i = 0; i < SerialNode.NUMCPNODEOPTS; i++) { 103 value.append(Integer.toHexString((node.getcpnodeOpts(i) & 0xF))); 104 } 105 n.addContent(makeParameter("cpnodeoptions", value.toString().toUpperCase())); 106 log.debug("Node {} NODE Options Written = {}", node.nodeAddress, value); 107 } 108 109 // node description 110 n.addContent(makeParameter("cmrinodedesc", node.getcmriNodeDesc())); 111 112 // look for the next node 113 node = (SerialNode) tc.getNode(index); 114 index++; 115 } 116 } 117 118 protected Element makeParameter(String name, String value) { 119 Element p = new Element("parameter"); 120 p.setAttribute("name", name); 121 p.addContent(value); 122 return p; 123 } 124 125 @Override 126 protected void getInstance() { 127 if (adapter == null) { 128 adapter = new SerialDriverAdapter(); 129 } 130 } 131 132 @Override 133 protected void getInstance(Object object) { 134 adapter = ((AbstractSerialConnectionConfig) object).getAdapter(); 135 } 136 137 @Override 138 protected void unpackElement(Element shared, Element perNode) { 139 // -------------------------------------- 140 // Load the poll list sequence if present 141 // -------------------------------------- 142 List<Element> pl = shared.getChildren("polllist"); 143 if (!pl.isEmpty()) { 144 Element ps = pl.get(0); 145 if (ps != null) { 146 String pseq = ps.getAttributeValue("pollseq"); 147 if (pseq != null) { 148 StringTokenizer nodes = new StringTokenizer(pseq, " ,"); 149 SerialTrafficController tcPL = ((CMRISystemConnectionMemo) adapter.getSystemConnectionMemo()).getTrafficController(); 150 while (nodes.hasMoreTokens()) { 151 tcPL.cmriNetPollList.add(Integer.parseInt(nodes.nextToken())); 152 } 153 log.debug("Poll List = {}", tcPL.cmriNetPollList); 154 } 155 } 156 } 157 158 // Load the node specific parameters 159 int pollListSize = ((CMRISystemConnectionMemo) adapter.getSystemConnectionMemo()).getTrafficController().cmriNetPollList.size(); 160 int nextPollPos = pollListSize + 1; 161 162 List<Element> l = shared.getChildren("node"); 163 for (int i = 0; i < l.size(); i++) { 164 Element n = l.get(i); 165 int addr = Integer.parseInt(n.getAttributeValue("name")); 166 int type = Integer.parseInt(findParmValue(n, "nodetype")); 167 int bpc = Integer.parseInt(findParmValue(n, "bitspercard")); 168 int delay = Integer.parseInt(findParmValue(n, "transmissiondelay")); 169 int num2l = Integer.parseInt(findParmValue(n, "num2lsearchlights")); 170 int pulseWidth = 500; 171 if ((findParmValue(n, "pulsewidth")) != null) { 172 pulseWidth = Integer.parseInt(findParmValue(n, "pulsewidth")); 173 } 174 175 String slb = findParmValue(n, "locsearchlightbits"); 176 String ctl = findParmValue(n, "cardtypelocation"); 177 String opts = ""; 178 179 // create node (they register themselves) 180 SerialNode node = new SerialNode(addr, type, ((CMRISystemConnectionMemo) adapter.getSystemConnectionMemo()).getTrafficController()); 181 node.setNumBitsPerCard(bpc); 182 node.setTransmissionDelay(delay); 183 node.setNum2LSearchLights(num2l); 184 node.setPulseWidth(pulseWidth); 185 186 // From the loaded poll list, assign the poll list position to the node 187 boolean assigned = false; 188 if (pollListSize > 0) { 189 for (int pls = 0; pls < pollListSize; pls++) { 190 if (((CMRISystemConnectionMemo) adapter.getSystemConnectionMemo()).getTrafficController().cmriNetPollList.get(pls) == node.getNodeAddress()) { 191 node.setPollListPosition(pls + 1); 192 assigned = true; 193 } 194 } 195 if (!assigned) { 196 node.setPollListPosition(nextPollPos++); 197 } 198 } 199 200 // CMRInet Options 201 //---------------- 202 if (findParmValue(n, "cmrinetoptions") != null) { 203 opts = findParmValue(n, "cmrinetoptions"); 204 // Convert and load the value into the node options array 205 for (int j = 0; j < SerialNode.NUMCMRINETOPTS; j++) { 206 node.setCMRInetOpts(j, (opts.charAt(j) - '0')); 207 } 208 log.debug("Node {} NET Options Read = {}", node.nodeAddress, opts); 209 210 } else { 211 // This must be the first time the nodes were loaded into a cpNode 212 // supported version. Set the Auto Poll option to avoid confusion 213 // with installed configurations. 214 for (int j = 0; j < SerialNode.NUMCMRINETOPTS; j++) { 215 node.setCMRInetOpts(j, 0); 216 } 217 node.setOptNet_AUTOPOLL(1); 218 log.debug("Node {} AUTO POLL Set ", node.nodeAddress); 219 220 } 221 222 for (int j = 0; j < slb.length(); j++) { 223 node.setLocSearchLightBits(j, (slb.charAt(j) - '0')); 224 } 225 226 for (int j = 0; j < ctl.length(); j++) { 227 node.setCardTypeLocation(j, (ctl.charAt(j) - '0')); 228 } 229 230 if (type == SerialNode.CPNODE || type == SerialNode.CPMEGA) { 231 // cpNode Options 232 if (findParmValue(n, "cpnodeoptions") != null) { 233 opts = findParmValue(n, "cpnodeoptions"); 234 // Convert and load the value into the node options array 235 for (int j = 0; j < SerialNode.NUMCPNODEOPTS; j++) { 236 node.setcpnodeOpts(j, (opts.charAt(j) - '0')); 237 } 238 } 239 240 log.debug("Node {} NODE Options Read = {}", node.nodeAddress, opts); 241 } 242 243 if (findParmValue(n, "cmrinodedesc") != null) { 244 node.setcmriNodeDesc(findParmValue(n, "cmrinodedesc")); 245 } else { 246 log.debug("No Description - Node {}", addr); 247 } 248 249 // Trigger initialization of this Node to reflect these parameters 250 ((CMRISystemConnectionMemo) adapter.getSystemConnectionMemo()).getTrafficController().initializeSerialNode(node); 251 } 252 } 253 254 @Override 255 protected void register() { 256 this.register(new ConnectionConfig(adapter)); 257 } 258 259 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ConnectionConfigXml.class); 260}