001package jmri.jmris.srcp.parser; 002 003import jmri.InstanceManager; 004import jmri.ProgrammingMode; 005import org.slf4j.Logger; 006import org.slf4j.LoggerFactory; 007 008/* This class provides an interface between the JavaTree/JavaCC 009 * parser for the SRCP protocol and the JMRI back end. 010 * @author Paul Bender Copyright (C) 2010 011 */ 012public class SRCPVisitor extends SRCPParserDefaultVisitor { 013 014 private String outputString = null; 015 016 public String getOutputString() { 017 return outputString; 018 } 019 020 // note that the isSupported function has the side 021 // effect of setting an error message to outputString if 022 // it returns false. 023 private boolean isSupported(int bus, String devicegroup) { 024 // get the system memo coresponding to the bus. 025 // and ask it what is supported 026 try { 027 jmri.SystemConnectionMemo memo 028 = InstanceManager.getList(jmri.SystemConnectionMemo.class).get(bus - 1); 029 if (memo != null) { 030 log.debug("devicegroup {}", devicegroup); 031 if (devicegroup.equals("FB")) { 032 if (memo.provides(jmri.SensorManager.class)) { 033 return true; 034 } else { 035 // respond this isn't supported 036 outputString = "422 ERROR unsupported device group"; 037 } 038 } else if (devicegroup.equals("GA")) { 039 if (memo.provides(jmri.TurnoutManager.class)) { 040 return true; 041 } else { 042 // respond this isn't supported 043 outputString = "422 ERROR unsupported device group"; 044 } 045 } else if (devicegroup.equals("GL")) { 046 if (memo.provides(jmri.ThrottleManager.class)) { 047 return true; 048 } else { 049 // respond this isn't supported 050 outputString = "422 ERROR unsupported device group"; 051 } 052 } else if (devicegroup.equals("POWER")) { 053 if (memo.provides(jmri.PowerManager.class)) { 054 return true; 055 } else { 056 // respond this isn't supported 057 outputString = "422 ERROR unsupported device group"; 058 } 059 } else if (devicegroup.equals("SM")) { 060 if (memo.provides(jmri.GlobalProgrammerManager.class)) { 061 return true; 062 } else { 063 // respond this isn't supported 064 outputString = "422 ERROR unsupported device group"; 065 } 066 } else { 067 // respond this isn't supported 068 outputString = "422 ERROR unsupported device group"; 069 070 } 071 } else { 072 // no memo registered for this bus. 073 outputString = "416 ERROR no data"; 074 } 075 } catch (java.lang.IndexOutOfBoundsException obe) { 076 outputString = "412 ERROR wrong value"; 077 } 078 return false; 079 } 080 081 @Override 082 public Object visit(ASTgo node, Object data) { 083 log.debug("Go {}", node.jjtGetValue()); 084 jmri.jmris.srcp.JmriSRCPServiceHandler handle = (jmri.jmris.srcp.JmriSRCPServiceHandler) data; 085 // The GO command should switch the server into runmode, but 086 // only if the client has set the protocol version. (if no mode 087 // is set, the default is command mode). 088 if (handle.getClientVersion().startsWith("0.8")) { 089 handle.setRunMode(); 090 outputString = "200 OK GO " + ((jmri.jmris.srcp.JmriSRCPServiceHandler) data).getSessionNumber(); 091 } else { 092 outputString = "402 ERROR insufficient data"; 093 } 094 return data; 095 } 096 097 @Override 098 public Object visit(ASThandshake_set node, Object data) { 099 log.debug("Handshake Mode SET "); 100 jmri.jmris.srcp.JmriSRCPServiceHandler handle = (jmri.jmris.srcp.JmriSRCPServiceHandler) data; 101 if (node.jjtGetChild(0).getClass() == ASTprotocollitteral.class) { 102 String version = (String) ((SimpleNode) node.jjtGetChild(1)).jjtGetValue(); 103 if (version.startsWith("0.8")) { 104 handle.setClientVersion(version); 105 outputString = "201 OK PROTOCOL SRCP"; 106 } else { 107 outputString = "400 ERROR unsupported protocol"; 108 } 109 } else if (node.jjtGetChild(0).getClass() == ASTconnectionlitteral.class) { 110 String mode = (String) ((SimpleNode) node.jjtGetChild(1)).jjtGetValue(); 111 outputString = "202 OK CONNECTIONMODEOK"; 112 if (mode.equals("COMMAND")) { 113 handle.setCommandMode(true); 114 } else if (mode.equals("INFO")) { 115 handle.setCommandMode(false); 116 } else { 117 outputString = "401 ERROR unsupported connection mode"; 118 } 119 } else { 120 outputString = "500 ERROR out of resources"; 121 } 122 return data; 123 } 124 125 @Override 126 public Object visit(ASTget node, Object data) { 127 log.debug("Get {}", ((SimpleNode) node.jjtGetChild(1)).jjtGetValue()); 128 int bus = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(0)).jjtGetValue())); 129 if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("POWER") 130 && isSupported(bus, "POWER")) { 131 // This is a message asking for the power status 132 try { 133 ((jmri.jmris.ServiceHandler) data).getPowerServer().sendStatus( 134 InstanceManager.getDefault(jmri.PowerManager.class).getPower()); 135 } catch (java.io.IOException ie) { 136 // silently ignore 137 } 138 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("GA") 139 && isSupported(bus, "GA")) { 140 // This is a message asking for the status of a "General Accessory". 141 int address = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(2)).jjtGetValue())); 142 // our implementation ignores the port, but maybe we shouldn't to 143 // follow the letter of the standard. 144 //int port = Integer.parseInt(((String)((SimpleNode)node.jjtGetChild(3)).jjtGetValue())); 145 try { 146 ((jmri.jmris.srcp.JmriSRCPTurnoutServer) ((jmri.jmris.ServiceHandler) data).getTurnoutServer()).sendStatus(bus, address); 147 } catch (java.io.IOException ie) { 148 } 149 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("FB") 150 && isSupported(bus, "FB")) { 151 // This is a message asking for the status of a FeedBack sensor. 152 int address = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(2)).jjtGetValue())); 153 try { 154 ((jmri.jmris.srcp.JmriSRCPSensorServer) ((jmri.jmris.ServiceHandler) data).getSensorServer()).sendStatus(bus, address); 155 } catch (java.io.IOException ie) { 156 } 157 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("SM") 158 && isSupported(bus, "SM")) { 159 // This is a Service Mode read request. 160 ProgrammingMode modeno = ProgrammingMode.REGISTERMODE; 161 if (node.jjtGetChild(3).getClass() == ASTcv.class) { 162 modeno = ProgrammingMode.DIRECTBYTEMODE; 163 } else if (node.jjtGetChild(3).getClass() == ASTcvbit.class) { 164 modeno = ProgrammingMode.DIRECTBITMODE; 165 } 166 167 int cv = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(4)).jjtGetValue())); 168 //try { 169 ((jmri.jmris.srcp.JmriSRCPProgrammerServer) ((jmri.jmris.ServiceHandler) data).getProgrammerServer()).readCV(modeno, cv); 170 //} catch(java.io.IOException ie) { 171 //} 172 173 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("GL") 174 && isSupported(bus, "GL")) { 175 // This is a Generic Loco request 176 // the 3rd child is the address of the locomotive we are 177 // requesting status of. 178 int address=Integer.parseInt(((String) ((SimpleNode)node.jjtGetChild(2)).jjtGetValue())); 179 // This is a Throttle Status request 180 try { 181 ((jmri.jmris.srcp.JmriSRCPThrottleServer)(((jmri.jmris.ServiceHandler) data).getThrottleServer())).sendStatus(bus,address); 182 } catch (java.io.IOException ie) { 183 } 184 185 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("TIME")) { 186 // This is a Time request 187 try { 188 ((jmri.jmris.ServiceHandler) data).getTimeServer().sendTime(); 189 } catch (java.io.IOException ie) { 190 } 191 192 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("SERVER")) { 193 // for the GET <bus> SERVER request, we return the current server 194 // state. In JMRI, we always return "Running". 195 outputString = "100 INFO 0 SERVER RUNNING"; 196 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("DESCRIPTION")) { 197 // for the GET <bus> DESCRIPTION request, what we return depends on 198 // the number of arguments passed. 199 SimpleNode descriptionnode = (SimpleNode) node.jjtGetChild(1); 200 int children = descriptionnode.jjtGetNumChildren(); 201 if (children == 0) { 202 // with no arguments, we send a list of supported groups. 203 if (bus == 0) { 204 // the groups supported by bus 0 are fixed 205 outputString = "100 INFO 0 DESCRIPTION SERVER SESSION TIME"; 206 } else { 207 outputString = "100 INFO " + bus; 208 // get the system memo coresponding to the bus. 209 // and ask it what is supported 210 try { 211 jmri.SystemConnectionMemo memo 212 = InstanceManager.getList(jmri.SystemConnectionMemo.class).get(bus - 1); 213 if (memo != null) { 214 outputString = outputString + " DESCRIPTION"; 215 if (memo.provides(jmri.SensorManager.class)) { 216 outputString = outputString + " FB"; 217 } 218 if (memo.provides(jmri.TurnoutManager.class)) { 219 outputString = outputString + " GA"; 220 } 221 if (memo.provides(jmri.ThrottleManager.class)) { 222 outputString = outputString + " GL"; 223 } 224 if (memo.provides(jmri.PowerManager.class)) { 225 outputString = outputString + " POWER"; 226 } 227 if (memo.provides(jmri.GlobalProgrammerManager.class)) { 228 outputString = outputString + " SM"; 229 } 230 } else { 231 // no memo registered for this bus. 232 outputString = "416 ERROR no data"; 233 } 234 } catch (java.lang.IndexOutOfBoundsException obe) { 235 outputString = "412 ERROR wrong value"; 236 } 237 } 238 } else if (children == 1) { 239 // with one argument, we respond with data only for device groups 240 // that have no addresses. 241 String devicegroup = (String) ((SimpleNode) descriptionnode.jjtGetChild(0)).jjtGetValue(); 242 outputString = "100 INFO " + bus; 243 log.debug("devicegroup {}", devicegroup); 244 if (devicegroup.equals("FB") && isSupported(bus, devicegroup)) { 245 outputString = "419 ERROR list too short"; 246 } else if (devicegroup.equals("GA") && isSupported(bus, devicegroup)) { 247 outputString = "419 ERROR list too short"; 248 } else if (devicegroup.equals("GL") && isSupported(bus, devicegroup)) { 249 outputString = "419 ERROR list too short"; 250 } else if (devicegroup.equals("POWER") && isSupported(bus, devicegroup)) { 251 // we are supposed to return the init string, 252 // and the POWER group has no parameters, so 253 // just return POWER 254 outputString = outputString + " POWER"; 255 } else if (devicegroup.equals("SM") && isSupported(bus, devicegroup)) { 256 outputString = "419 ERROR list too short"; 257 } else { 258 // respond this isn't supported 259 outputString = "422 ERROR unsupported device group"; 260 } // end if(chidren==1) 261 } else if (children == 2) { 262 outputString = "100 INFO " + bus; 263 // get the system memo coresponding to the bus. 264 // and ask it what is supported 265 // with 2 arguments, we send a description of a specific device. 266 jmri.SystemConnectionMemo memo 267 = InstanceManager.getList(jmri.SystemConnectionMemo.class).get(bus - 1); 268 if (memo != null) { 269 String devicegroup = (String) ((SimpleNode) descriptionnode.jjtGetChild(0)).jjtGetValue(); 270 String address = (String) ((SimpleNode) descriptionnode.jjtGetChild(1)).jjtGetValue(); 271 if (devicegroup.equals("FB") && isSupported(bus, devicegroup)) { 272 jmri.SensorManager mgr = memo.get(jmri.SensorManager.class); 273 try { 274 String searchName = mgr.createSystemName(address, 275 memo.getSystemPrefix()); 276 if (mgr.getBySystemName(searchName) != null) { 277 // add the initialization parameter list. 278 // we don't expect parameters, so just return 279 // the bus and address. 280 outputString = outputString + " FB " + address; 281 } else { 282 // the device wasn't found. 283 outputString = "412 ERROR wrong value"; 284 } 285 } catch (jmri.JmriException je) { 286 // the device wasn't found. 287 outputString = "412 ERROR wrong value"; 288 } 289 } else if (devicegroup.equals("GA") && isSupported(bus, devicegroup)) { 290 jmri.TurnoutManager mgr = memo.get(jmri.TurnoutManager.class); 291 try { 292 String searchName = mgr.createSystemName(address, memo.getSystemPrefix()); 293 if (mgr.getBySystemName(searchName) != null) { 294 // add the initialization parameter list. 295 // the only other required parameter is 296 // the protocol, and we treat all of our 297 // turnouts as NMRA-DCC turnouts, so return 298 // the fixed "N" protocol value. 299 // other valid options are: 300 // "M" (Mareklin/Motorola format) 301 // "S" (Selectrix Format) 302 // "P" (Protocol by server) 303 outputString = outputString + " GA " + address + " N"; 304 } else { 305 // the device wasn't found. 306 outputString = "412 ERROR wrong value"; 307 } 308 } catch (jmri.JmriException je) { 309 // the device wasn't found. 310 outputString = "412 ERROR wrong value"; 311 } 312 } else if (devicegroup.equals("GL") && isSupported(bus, devicegroup)) { 313 // outputString=outputString + " GL " +address; 314 // this one needs some tought on how to proceed, 315 // since the throttle manager differs from 316 // other JMRI managers. 317 // for now, just say no data. 318 outputString = "416 ERROR no data"; 319 } else if (devicegroup.equals("POWER") && isSupported(bus, devicegroup)) { 320 outputString = "418 ERROR list too long"; 321 } else if (devicegroup.equals("SM") && isSupported(bus, devicegroup)) { 322 //outputString=outputString + " SM " +address; 323 // this one needs some tought on how to proceed // since we have both service mode and ops mode 324 // programmers, but the service mode programmer is 325 // not addressed on DCC systems. 326 // for now, just say no data. 327 outputString = "416 ERROR no data"; 328 } 329 } // end if(children==2) 330 } else { 331 outputString = "418 ERROR list too long"; 332 } // end of DESCRIPTION device group. 333 } else { 334 outputString = "422 ERROR unsupported device group"; 335 } 336 return data; 337 } 338 339 @Override 340 public Object visit(ASTset node, Object data) { 341 SimpleNode target = (SimpleNode) node.jjtGetChild(1); 342 343 log.debug("Set {}", target.jjtGetValue()); 344 int bus = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(0)).jjtGetValue())); 345 346 if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("POWER") 347 && isSupported(bus, "POWER")) { 348 try { 349 ((jmri.jmris.ServiceHandler) data).getPowerServer().parseStatus( 350 ((String) ((SimpleNode) node.jjtGetChild(2)).jjtGetValue())); 351 } catch (java.io.IOException ie) { 352 } catch (jmri.JmriException je) { 353 // We shouldn't have any errors here. 354 // If we do, something is horibly wrong. 355 } 356 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("GA") 357 && isSupported(bus, "GA")) { 358 int address = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(2)).jjtGetValue())); 359 int port = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(3)).jjtGetValue())); 360 // we expect to get both the value and delay, but JMRI only cares about 361 // the port which indicates which output of a pair we are using. 362 // leave the values below commented out, unless we decide to use them 363 // later. 364 //int value = Integer.parseInt(((String)((SimpleNode)node.jjtGetChild(4)).jjtGetValue())); 365 //int delay = Integer.parseInt(((String)((SimpleNode)node.jjtGetChild(5)).jjtGetValue())); 366 367 try { 368 ((jmri.jmris.srcp.JmriSRCPTurnoutServer) ((jmri.jmris.ServiceHandler) data).getTurnoutServer()).parseStatus(bus, address, port); 369 } catch (jmri.JmriException je) { 370 // We shouldn't have any errors here. 371 // If we do, something is horibly wrong. 372 } catch (java.io.IOException ie) { 373 } 374 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("FB") 375 && isSupported(bus, "FB")) { 376 int address = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(2)).jjtGetValue())); 377 int value = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(3)).jjtGetValue())); 378 try { 379 ((jmri.jmris.srcp.JmriSRCPSensorServer) ((jmri.jmris.ServiceHandler) data).getSensorServer()).parseStatus(bus, address, value); 380 } catch (java.io.IOException ie) { 381 } 382 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("SM") 383 && isSupported(bus, "SM")) { 384 // This is a Service Mode write request 385 ProgrammingMode modeno = ProgrammingMode.REGISTERMODE; 386 if (node.jjtGetChild(3).getClass() == ASTcv.class) { 387 modeno = ProgrammingMode.DIRECTBYTEMODE; 388 } else if (node.jjtGetChild(3).getClass() == ASTcvbit.class) { 389 modeno = ProgrammingMode.DIRECTBITMODE; 390 } 391 int cv = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(4)).jjtGetValue())); 392 int value = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(5)).jjtGetValue())); 393 394 //try { 395 ((jmri.jmris.srcp.JmriSRCPProgrammerServer) ((jmri.jmris.ServiceHandler) data).getProgrammerServer()).writeCV(modeno, cv, value); 396 //} catch(java.io.IOException ie) { 397 //} 398 399 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("GL") 400 && isSupported(bus, "GL")) { 401 // This is a Generic Loco request 402 int address = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(2)).jjtGetValue())); 403 String drivemode = (String) ((SimpleNode) node.jjtGetChild(3)).jjtGetValue(); 404 405 int speedstep = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(4)).jjtGetValue())); 406 407 int maxspeedstep = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(5)).jjtGetValue())); 408 ((jmri.jmris.srcp.JmriSRCPThrottleServer) ((jmri.jmris.ServiceHandler) data).getThrottleServer()).setThrottleSpeedAndDirection(bus,address,(float)speedstep/(float)maxspeedstep,drivemode.equals("0")); 409 // setup the array list of function values. 410 411 int numFunctions = node.jjtGetNumChildren() - 6; 412 java.util.ArrayList<Boolean> functionList = new java.util.ArrayList<>(); 413 for(int i = 0; i < numFunctions;i++){ 414 // the functions start at the 7th child (index 6) of the node. 415 String functionMode = (String) ((SimpleNode) node.jjtGetChild(i+6)).jjtGetValue(); 416 functionList.add(Boolean.valueOf(functionMode.equals("1"))); 417 } 418 ((jmri.jmris.srcp.JmriSRCPThrottleServer) ((jmri.jmris.ServiceHandler) data).getThrottleServer()).setThrottleFunctions(bus,address,functionList); 419 420 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("TIME")) { 421 // This is a Time request 422 try { 423 jmri.jmris.srcp.JmriSRCPTimeServer ts = (jmri.jmris.srcp.JmriSRCPTimeServer) (((jmri.jmris.ServiceHandler) data).getTimeServer()); 424 int julDay = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(2)).jjtGetValue())); 425 int hour = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(3)).jjtGetValue())); 426 int minute = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(4)).jjtGetValue())); 427 int second = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(4)).jjtGetValue())); 428 429 // set the time 430 ts.parseTime(julDay, hour, minute, second); 431 // and start the clock. 432 ts.startTime(); 433 ts.sendTime(); 434 } catch (java.io.IOException ie) { 435 } 436 } else { 437 outputString = "422 ERROR unsupported device group"; 438 } 439 return data; 440 } 441 442 @Override 443 public Object visit(ASTterm node, Object data) { 444 SimpleNode target = (SimpleNode) node.jjtGetChild(1); 445 int bus = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(0)).jjtGetValue())); 446 log.debug("TERM {} {}", bus, target.jjtGetValue()); 447 if (target.jjtGetValue().equals("SERVER")) { 448 // for the TERM <bus> SERVER request, the protocol requries that 449 // we terminate all connections and reset the state to the initial 450 // state. Since we may have a local GUI controlling things, we 451 // ignore the request, but send the proper return value to the 452 // requesting client. 453 outputString = "200 OK"; 454 return data; 455 } else if (target.jjtGetValue().equals("SESSION")) { 456 // for the TERM <bus> SERVER request, the protocol requries that 457 // we terminate all connections and reset the state to the initial 458 // state. Since we may have a local GUI controlling things, we 459 // ignore the request, but send the proper return value to the 460 // requesting client. 461 outputString = "102 INFO " + bus + " SESSION " + ((jmri.jmris.srcp.JmriSRCPServiceHandler) data).getSessionNumber(); // we need to set session IDs. 462 return data; 463 } else if(target.jjtGetValue().equals("GL")) { 464 // terminate a locomotive 465 int address = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(2)).jjtGetValue())); 466 try { 467 ((jmri.jmris.srcp.JmriSRCPThrottleServer)(((jmri.jmris.ServiceHandler) data).getThrottleServer())).releaseThrottle(bus,address); 468 } catch (java.io.IOException ioe){ 469 log.error("Error writing to network port"); 470 } 471 return data; 472 } 473 474 return node.childrenAccept(this, data); 475 } 476 477 @Override 478 public Object visit(ASTreset node, java.lang.Object data) { 479 log.debug("RESET {}", ((SimpleNode) node.jjtGetChild(1)).jjtGetValue()); 480 if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("SERVER")) { 481 // for the RESET <bus> SERVER request, the protocol requries that 482 // we re-initialize the server. Since we may have a local GUI 483 // controlling things, we ignore the request, but send a prohibited 484 // response to the requesting client. 485 outputString = "413 ERROR temporarily prohibited"; 486 return data; 487 } else { 488 outputString = "422 ERROR unsupported device group"; 489 } 490 return node.childrenAccept(this, data); 491 } 492 493 @Override 494 public Object visit(ASTinit node, java.lang.Object data) { 495 int bus = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(0)).jjtGetValue())); 496 log.debug("INIT {}", ((SimpleNode) node.jjtGetChild(1)).jjtGetValue()); 497 if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("POWER") 498 && isSupported(bus, "POWER")) { 499 /* Power really has nothing to do in JMRI */ 500 outputString = "200 OK"; 501 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("GA") 502 && isSupported(bus, "GA")) { 503 /* Initilize a new accessory */ 504 int address = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(2)).jjtGetValue())); 505 String protocol = ((String) ((SimpleNode) node.jjtGetChild(3)).jjtGetValue()); 506 try { 507 ((jmri.jmris.srcp.JmriSRCPTurnoutServer) ((jmri.jmris.ServiceHandler) data).getTurnoutServer()).initTurnout(bus, address, protocol); 508 } catch (jmri.JmriException je) { 509 // We shouldn't have any errors here. 510 // If we do, something is horibly wrong. 511 } catch (java.io.IOException ie) { 512 } 513 514 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("GL") 515 && isSupported(bus, "GL")) { 516 /* Initilize a new locomotive */ 517 int address = Integer.parseInt(((String)((SimpleNode)node.jjtGetChild(2)).jjtGetValue())); 518 SimpleNode protocolNode = (SimpleNode)node.jjtGetChild(3); 519 String protocol = (String)(protocolNode.jjtGetValue()); 520 switch(protocol){ 521 case "N": // NMRA DCC 522 int protocolversion = Integer.parseInt(((String)((SimpleNode)protocolNode.jjtGetChild(0)).jjtGetValue())); 523 int speedsteps = Integer.parseInt(((String)((SimpleNode)protocolNode.jjtGetChild(1)).jjtGetValue())); 524 int functions = Integer.parseInt(((String)((SimpleNode)protocolNode.jjtGetChild(2)).jjtGetValue())); 525 try { 526 ((jmri.jmris.srcp.JmriSRCPThrottleServer)(((jmri.jmris.ServiceHandler) data).getThrottleServer())).initThrottle(bus,address,protocolversion==2,speedsteps,functions); 527 } catch (java.io.IOException ie) { 528 } 529 break; 530 case "A": // analog operation 531 // the documentation says this is reserved for address 0. 532 // but this could be used if we ever build support for 533 // analog non-dcc throttles. 534 case "P": // protocol by server. The documentation indicates 535 // the server gets to choose the type of decoder, 536 // but otherwise is silent on what parameters this 537 // should take. 538 case "F": // Fleischmann 539 case "L": // LocoNet 540 case "M": // Maerklin/Motorola 541 case "S": // Selectrix 542 case "Z": // zimo 543 default: 544 outputString = "420 ERROR unsupported device protocol"; 545 return data; 546 } 547 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("TIME")) { 548 /* Initilize fast clock ratio */ 549 try { 550 /* the two parameters form a ration of modeltime:realtime */ 551 int modeltime = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(2)).jjtGetValue())); 552 int realtime = Integer.parseInt(((String) ((SimpleNode) node.jjtGetChild(3)).jjtGetValue())); 553 jmri.jmris.srcp.JmriSRCPTimeServer ts = (jmri.jmris.srcp.JmriSRCPTimeServer) (((jmri.jmris.ServiceHandler) data).getTimeServer()); 554 ts.parseRate(modeltime, realtime); 555 ts.sendRate(); 556 } catch (java.io.IOException ie) { 557 } 558 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("SM") 559 && isSupported(bus, "SM")) { 560 /* Initilize service mode */ 561 outputString = "200 OK"; 562 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("FB") 563 && isSupported(bus, "FB")) { 564 /* Initilize feedback on a particular bus */ 565 outputString = "200 OK"; 566 } 567 568 return data; 569 } 570 571 @Override 572 public Object visit(ASTwait_cmd node, Object data) { 573 log.debug("Received WAIT CMD {}", node.jjtGetValue()); 574 if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("TIME")) { 575 long julday = Long.parseLong((String) ((SimpleNode) node.jjtGetChild(2)).jjtGetValue()); 576 int Hour = Integer.parseInt((String) ((SimpleNode) node.jjtGetChild(3)).jjtGetValue()); 577 int Minute = Integer.parseInt((String) ((SimpleNode) node.jjtGetChild(4)).jjtGetValue()); 578 int Second = Integer.parseInt((String) ((SimpleNode) node.jjtGetChild(5)).jjtGetValue()); 579 ((jmri.jmris.srcp.JmriSRCPTimeServer) ((jmri.jmris.ServiceHandler) data).getTimeServer()).setAlarm(julday, Hour, Minute, Second); 580 581 } else if (((SimpleNode) node.jjtGetChild(1)).jjtGetValue().equals("FB")) { 582 outputString = "425 ERROR not supported"; 583 } else { 584 outputString = "423 ERROR unsupported operation"; 585 } 586 return data; 587 } 588 589 private final static Logger log = LoggerFactory.getLogger(SRCPVisitor.class); 590 591}