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