001package jmri.jmrix.can.cbus.node; 002 003import java.util.Collections; 004import java.util.HashMap; 005import java.util.Map; 006 007import javax.annotation.Nonnull; 008 009import static jmri.jmrix.can.cbus.CbusConstants.*; 010 011// import org.slf4j.Logger; 012// import org.slf4j.LoggerFactory; 013 014/** 015 * Static Methods relating to nodes ( modules ). 016 * 017 * @author Steve Young (C) 2019 018 */ 019public class CbusNodeConstants { 020 021 /** 022 * Node Parameters 023 * 024 * Para 0 Number of parameters 025 * Para 1 The manufacturer ID 026 * Para 2 Minor code version as an alphabetic character (ASCII) 027 * Para 3 Manufacturer module identifier as a HEX numeric 028 * Para 4 Number of supported events as a HEX numeric 029 * Para 5 Number of Event Variables per event as a HEX numeric 030 * Para 6 Number of supported Node Variables as a HEX numeric 031 * Para 7 Major version 032 * Para 8 Node flags 033 * Para 9 Processor type 034 * Para 10 Bus type 035 * Para 11 load address, 4 bytes 036 * Para 15 CPU manufacturer's id as read from the chip config space, 4 bytes 037 * Para 19 CPU manufacturer code 038 * Para 20 Beta revision (numeric), or 0 if release 039 * Para 21 - 24 Zero filled spare 040 * Not readable by index: 041 * Para 25 - 26 Number of paranmeters can be read as parameter 0 042 * Para 27 - 30 Name string base address 043 * Para 31 - 32 Checksum. Para 1 - 32 must sum to zero 044 */ 045 public static final int NUM_PARAM_IDX = 0; // Para 0 Number of parameters 046 public static final int MANU_ID_IDX = 1; // Para 1 The manufacturer ID 047 public static final int MINOR_VER_IDX = 2; // Para 2 Minor code version as an alphabetic character (ASCII) 048 public static final int MODULE_ID_IDX = 3; // Para 3 Manufacturer module identifier as a HEX numeric 049 public static final int NUM_EV_IDX = 4; // Para 4 Number of supported events as a HEX numeric 050 public static final int EV_PER_EN_IDX = 5; // Para 5 Number of Event Variables per event as a HEX numeric 051 public static final int NUM_NV_IDX = 6; // Para 6 Number of supported Node Variables as a HEX numeric 052 public static final int MAJOR_VER_IDX = 7; // Para 7 Major version 053 public static final int FLAGS_IDX = 8; // Para 8 Node flags 054 public static final int PROC_TYPE_IDX = 9; // Para 9 Processor type 055 public static final int BUS_TYPE_IDX = 10; // Para 10 Bus type 056 public static final int LOAD_ADDR_IDX = 11; // Para 11 load address, 4 bytes 057 public static final int CPU_ID_IDX = 15; // Para 15 CPU manufacturer's id as read from the chip config space, 4 bytes, only firs two used for PIC18 058 public static final int CPU_CODE_IDX = 19; // Para 19 CPU manufacturer code 059 public static final int BETA_REV_IDX = 20; // Para 20 Beta revision (numeric), or 0 if release 060 public static final int SPARE_IDX = 21; // Para 21 - 24 061 // Following are available from hex data but not readable by index 062 public static final int PARAM_COUNT_IDX = 25; // Para 25 - 26 parameter count high byte 063 public static final int NAME_STRING_BASE_IDX = 27; // Para 27 - 30 parameter count high byte 064 public static final int PARAM_CHECK_IDX = 31; // Para 31 - 32 parameter count high byte 065 066 067 /** 068 * Set traits for a node where there is a minor deviance to MERG CBUS protocol 069 * or provide extra info. which is missing for a known module firmware. 070 * @param node The CbusNode object we are setting the traits for 071 */ 072 public static void setTraits(@Nonnull CbusNode node ){ 073 074 // defaults 075 node.setsendsWRACKonNVSET(true); 076 077 if ( node.getNodeParamManager().getParameter(MANU_ID_IDX) == MANU_MERG ) { // MERG MODULE 078 switch (node.getNodeParamManager().getParameter(MODULE_ID_IDX)) { // Module Type ID Number 079 case 1: // CANACC4 080 case 8: // CANACC4_2 081 case 29: // CANPAN 082 case 34: // CANSOL 083 case 37: // CANACC4CDU 084 node.setsendsWRACKonNVSET(false); 085 break; 086 case 10 : // CANCMD 087 case 55 : // or CANCSB 088 case 12 : // or CANBC 089 case 83 : // or CANCMDB 090 if ( node.getNodeParamManager().getParameter(MAJOR_VER_IDX) == 4 ) { // v4 Firmware 091 node.getNodeEventManager().resetNodeEventsToZero(); // sets num events to 0 as does not respond to RQEVN 092 node.setStatResponseFlagsAccurate(false); 093 } 094 break; 095 case 46: // CANPiWi 096 if ( node.getNodeParamManager().getParameter(MAJOR_VER_IDX) == 1 ) { // v1 Firmware 097 node.getNodeEventManager().resetNodeEventsToZero(); // sets num events to 0 as does not respond to RQEVN 098 } 099 break; 100 case 9: // CANCAB 101 node.getNodeEventManager().resetNodeEventsToZero(); // sets num events to 0 as does not respond to RQEVN 102 break; 103 case 50: // CANMIO-SVO 104 case 19: // CANSERVO8C 105 node.setnvWriteInLearnOnly(true); 106 break; 107 default: 108 break; 109 } 110 } else if ( node.getNodeParamManager().getParameter(MANU_ID_IDX) == SPROG_DCC ) { // SPROG DCC module 111 switch (node.getNodeParamManager().getParameter(MODULE_ID_IDX)) { // Module Type ID Number 112 case MTYP_CANSERVOIO: 113 node.setnvWriteInLearnOnly(true); 114 break; 115 116 default: 117 break; 118 } 119 } 120 } 121 122 /** 123 * Return a string representation of a decoded Module Manufacturer 124 * @param man manufacturer int 125 * @return decoded CBUS message 126 */ 127 public static String getManu(int man) { 128 if (man < 1 ) { 129 return (""); 130 } 131 // look for the manufacturer 132 String format = manMap.get(man); 133 if (format == null) { 134 return "Manufacturer " + man; 135 } else { 136 return format; 137 } 138 } 139 140 /** 141 * Hashmap for decoding Module Manufacturers 142 */ 143 private static final Map<Integer, String> manMap = createManMap(); 144 145 /** 146 * Populate hashmap with format strings 147 * 148 */ 149 private static Map<Integer, String> createManMap() { 150 Map<Integer, String> result = new HashMap<>(); 151 result.put(MANU_ROCRAIL, "ROCRAIL"); // NOI18N 152 result.put(MANU_SPECTRUM, "SPECTRUM"); // NOI18N 153 result.put(MANU_MERG, "MERG"); // NOI18N 154 result.put(SPROG_DCC, "SPROG DCC"); // NOI18N 155 return Collections.unmodifiableMap(result); 156 } 157 158 /** 159 * Return a string representation of a decoded Bus Type 160 * @param type Bus type 161 * @return decoded CBUS message 162 */ 163 public static String getBusType(int type) { 164 // look for the opcode 165 String format = busMap.get(type); 166 if (format == null) { 167 return "Unknown"; 168 } else { 169 return format; 170 } 171 } 172 173 /** 174 * Hashmap for decoding Bus Type 175 */ 176 private static final Map<Integer, String> busMap = createBusMap(); 177 178 /** 179 * Populate hashmap with format strings 180 * 181 */ 182 private static Map<Integer, String> createBusMap() { 183 Map<Integer, String> result = new HashMap<>(); 184 result.put(0, "None"); // NOI18N 185 result.put(1, "CAN"); // NOI18N 186 result.put(2, "ETH"); // NOI18N 187 result.put(3, "MIWI"); // NOI18N 188 result.put(4, "USB"); // NOI18N 189 return Collections.unmodifiableMap(result); 190 } 191 192 // manufacturer specific stuff from here down 193 // do not rely on these as defs, may be moved to module config file. 194 195 // getModuleTypeExtra 196 // getModuleSupportLink 197 198 /** 199 * Return a string representation of a decoded Module Name for 200 * manufacturer MERG. 201 * @param man int manufacturer 202 * @param type module type int 203 * @return decoded String module type name else empty string 204 */ 205 public static String getModuleType(int man, int type) { 206 String format=""; 207 if (man == MANU_MERG) { 208 format = type165Map.get(type); 209 } 210 else if (man == MANU_ROCRAIL) { 211 format = type70Map.get(type); 212 } 213 else if (man == MANU_SPECTRUM) { 214 format = type80Map.get(type); 215 } 216 else if (man == SPROG_DCC) { 217 format = type44Map.get(type); 218 } 219 220 if ( format == null ){ 221 return (""); 222 } 223 else { 224 return format; 225 } 226 } 227 228 /** 229 * Hashmap for decoding Module Names 230 */ 231 private static final Map<Integer, String> type165Map = createType165Map(); 232 private static final Map<Integer, String> type70Map = createType70Map(); 233 private static final Map<Integer, String> type80Map = createType80Map(); 234 private static final Map<Integer, String> type44Map = createType44Map(); 235 236 /** 237 * Populate hashmap with format strings for manufacturer MERG 238 */ 239 private static Map<Integer, String> createType165Map() { 240 Map<Integer, String> result = new HashMap<>(); 241 result.put(0, "SLIM"); // NOI18N 242 result.put(1, "CANACC4"); // NOI18N 243 result.put(2, "CANACC5"); // NOI18N 244 result.put(3, "CANACC8"); // NOI18N 245 result.put(4, "CANACE3"); // NOI18N 246 result.put(5, "CANACE8C"); // NOI18N 247 result.put(6, "CANLED"); // NOI18N 248 result.put(7, "CANLED64"); // NOI18N 249 result.put(8, "CANACC4_2"); // NOI18N 250 result.put(9, "CANCAB"); // NOI18N 251 result.put(10, "CANCMD"); // NOI18N 252 result.put(11, "CANSERVO"); // NOI18N 253 result.put(12, "CANBC"); // NOI18N 254 result.put(13, "CANRPI"); // NOI18N 255 result.put(14, "CANTTCA"); // NOI18N 256 result.put(15, "CANTTCB"); // NOI18N 257 result.put(16, "CANHS"); // NOI18N 258 result.put(17, "CANTOTI"); // NOI18N 259 result.put(18, "CAN8I8O"); // NOI18N 260 result.put(19, "CANSERVO8C"); // NOI18N 261 result.put(20, "CANRFID"); // NOI18N 262 result.put(21, "CANTC4"); // NOI18N 263 result.put(22, "CANACE16C"); // NOI18N 264 result.put(23, "CANIO8"); // NOI18N 265 result.put(24, "CANSNDX"); // NOI18N 266 result.put(25, "CANEther"); // NOI18N 267 result.put(26, "CANSIG64"); // NOI18N 268 result.put(27, "CANSIG8"); // NOI18N 269 result.put(28, "CANCOND8C"); // NOI18N 270 result.put(29, "CANPAN"); // NOI18N 271 result.put(30, "CANACE3C"); // NOI18N 272 result.put(31, "CANPanel"); // NOI18N 273 result.put(32, "CANMIO"); // NOI18N 274 result.put(33, "CANACE8MIO"); // NOI18N 275 result.put(34, "CANSOL"); // NOI18N 276 result.put(35, "CANBIP"); // NOI18N 277 result.put(36, "CANCDU"); // NOI18N 278 result.put(37, "CANACC4CDU"); // NOI18N 279 result.put(38, "CANWiBase"); // NOI18N 280 result.put(39, "WiCAB"); // NOI18N 281 result.put(40, "CANWiFi"); // NOI18N 282 result.put(41, "CANFTT"); // NOI18N 283 result.put(42, "CANHNDST"); // NOI18N 284 result.put(43, "CANTCHNDST"); // NOI18N 285 result.put(44, "CANRFID8"); // NOI18N 286 result.put(45, "CANmchRFID"); // NOI18N 287 result.put(46, "CANPiWi"); // NOI18N 288 result.put(47, "CAN4DC"); // NOI18N 289 result.put(48, "CANELEV"); // NOI18N 290 result.put(49, "CANSCAN"); // NOI18N 291 result.put(50, "CANMIO_SVO"); // NOI18N 292 result.put(51, "CANMIO_INP"); // NOI18N 293 result.put(52, "CANMIO_OUT"); // NOI18N 294 result.put(53, "CANBIP_OUT"); // NOI18N 295 result.put(54, "CANASTOP"); // NOI18N 296 result.put(55, "CANCSB"); // NOI18N 297 result.put(56, "CANMAG"); // NOI18N 298 result.put(57, "CANACE16CMIO"); // NOI18N 299 result.put(58, "CANPiNODE"); // NOI18N 300 result.put(59, "CANDISP"); // NOI18N 301 result.put(60, "CANCOMPUTE"); // NOI18N 302 result.put(61, "CANRC522"); // NOI18N 303 result.put(62, "CANINP"); // NOI18N 304 result.put(63, "CANOUT"); // NOI18N 305 result.put(64, "CANEMIO"); // NOI18N 306 result.put(65, "CANCABDC"); // NOI18N 307 result.put(66, "CANRCOM"); // NOI18N 308 result.put(67, "CANMP3"); 309 result.put(68, "CANXMAS"); 310 result.put(69, "CANSVOSET"); 311 result.put(70, "CANCMDDC"); 312 result.put(71, "CANTEXT"); 313 result.put(72, "CANASIGNAL"); 314 result.put(73, "CANSLIDER"); 315 result.put(74, "CANDCATC"); 316 result.put(75, "CANGATE"); 317 result.put(76, "CANSINP"); 318 result.put(77, "CANSOUT"); 319 result.put(78, "CANSBIP"); 320 result.put(79, "CANBUFFER"); 321 result.put(80, "CANLEVER"); 322 result.put(81, "CANSHIELD"); 323 result.put(82, "CAN4IN4OUT"); 324 result.put(83, "CANCMDB"); 325 result.put(84, "CANPIXEL"); 326 result.put(85, "CANCABPE"); 327 result.put(86, "CANSMARTTD"); 328 result.put(87, "CANARGB"); 329 330 result.put(252, "VLCB"); 331 result.put(253, "CANUSB"); // NOI18N 332 result.put(254, "EMPTY"); // NOI18N 333 result.put(255, "CAN_SW"); // NOI18N 334 return Collections.unmodifiableMap(result); 335 } 336 337 /* 338 * Populate hashmap with format strings 339 * 340 */ 341 private static Map<Integer, String> createType70Map() { 342 Map<Integer, String> result = new HashMap<>(); 343 result.put(1, "CANGC1"); // NOI18N 344 result.put(2, "CANGC2"); // NOI18N 345 result.put(3, "CANGC3"); // NOI18N 346 result.put(4, "CANGC4"); // NOI18N 347 result.put(5, "CANGC5"); // NOI18N 348 result.put(6, "CANGC6"); // NOI18N 349 result.put(7, "CANGC7"); // NOI18N 350 result.put(11, "CANGC1e"); // NOI18N 351 return Collections.unmodifiableMap(result); 352 } 353 354 355 /* 356 * Populate hashmap with format strings 357 * 358 */ 359 private static Map<Integer, String> createType80Map() { 360 Map<Integer, String> result = new HashMap<>(); 361 result.put(1, "AMCTRLR"); // NOI18N 362 result.put(2, "DUALCAB"); // NOI18N 363 return Collections.unmodifiableMap(result); 364 } 365 366 367 /* 368 * Populate hashmap with format strings. 369 * Visible name of module, not the CBUS NAME OPC Response. 370 */ 371 private static Map<Integer, String> createType44Map() { 372 Map<Integer, String> result = new HashMap<>(); 373 result.put(1, "Pi-SPROG 3"); // NOI18N 374 result.put(2, "CANSPROG3P"); // NOI18N 375 result.put(3, "CANSPROG"); // NOI18N 376 result.put(4, "SBOOST"); // NOI18N 377 result.put(5, "Unsupported"); // NOI18N 378 379 result.put(8, "CANSOLNOID"); // NOI18N. Matches MERG CANSOL 380 result.put(50, "CANSERVOIO"); // NOI18N. Matches MERG canmio-svo 381 382 result.put(100, "CANISB"); // NOI18N 383 result.put(101, "CANSOLIO"); // NOI18N 384 return Collections.unmodifiableMap(result); 385 } 386 387 388 /** 389 * Return a string representation of extra module info 390 * @param man int manufacturer code 391 * @param type int module type 392 * @return string value of extra module info 393 */ 394 public static String getModuleTypeExtra(int man, int type) { 395 String format=""; 396 switch (man) { 397 case MANU_MERG: 398 format = extra165Map.get(type); 399 break; 400 case MANU_ROCRAIL: 401 format = extra70Map.get(type); 402 break; 403 case MANU_SPECTRUM: 404 format = extra80Map.get(type); 405 break; 406 case SPROG_DCC: 407 format = extra44Map.get(type); 408 break; 409 default: 410 break; 411 } 412 return format; 413 } 414 415 /** 416 * Hashmap for decoding Module extra info 417 */ 418 private static final Map<Integer, String> extra165Map = createExtra165Map(); 419 private static final Map<Integer, String> extra70Map = createExtra70Map(); 420 private static final Map<Integer, String> extra80Map = createExtra80Map(); 421 private static final Map<Integer, String> extra44Map = createExtra44Map(); 422 423 /* 424 * Populate hashmap with format strings 425 */ 426 private static Map<Integer, String> createExtra165Map() { 427 Map<Integer, String> result = new HashMap<>(); 428 result.put(0, "Default for SLiM nodes"); 429 result.put(1, "Solenoid point driver"); 430 result.put(2, "Motorised point driver"); 431 result.put(3, "8 digital outputs ( + 8 inputs if modded)"); 432 result.put(4, "Control panel switch/button encoder"); 433 result.put(5, "8 digital inputs"); 434 result.put(6, "64 led driver"); 435 result.put(7, "64 led driver (multi leds per event)"); 436 result.put(8, "12v version of CANACC4 Solenoid point driver"); 437 result.put(9, "CANCAB hand throttle"); 438 result.put(10, "Command Station"); 439 result.put(11, "8 servo driver (on canacc8 or similar hardware)"); 440 result.put(12, "BC1a Command Station"); 441 result.put(13, "RPI and RFID interface"); 442 result.put(14, "Turntable controller (turntable end)"); 443 result.put(15, "Turntable controller (control panel end)"); 444 result.put(16, "Handset controller for old BC1a type handsets"); 445 result.put(17, "Track occupancy detector"); 446 result.put(18, "8 inputs 8 outputs"); 447 result.put(19, "Canservo with servo position feedback"); 448 result.put(20, "RFID input"); 449 result.put(21, "CANTC4"); 450 result.put(22, "16 inputs"); 451 result.put(23, "8 way I/O"); 452 result.put(24, "CANSNDX"); 453 result.put(25, "Ethernet interface"); 454 result.put(26, "Multiple aspect signalling for CANLED module"); 455 result.put(27, "Multiple aspect signalling for CANACC8 module"); 456 result.put(28, "Conditional event generation"); 457 result.put(29, "Control panel 32 Outputs + 32 Inputs"); 458 result.put(30, "Newer version of CANACE3 firmware"); 459 result.put(31, "Control panel 64 Inputs / 64 Outputs"); 460 result.put(32, "Multiple I/O – Universal CANMIO firmware"); 461 result.put(33, "Multiple IO module 16 inputs emulating CANACE8C on CANMIO hardware"); 462 result.put(34, "Solenoid driver module"); 463 result.put(35, "Universal CANBIP firmware - Bipolar IO module with additional 8 I/O pins (CANMIO family)"); 464 result.put(36, "Solenoid driver module with additional 6 I/O pins (CANMIO family)"); 465 result.put(37, "CANACC4 firmware ported to CANCDU"); 466 result.put(38, "CAN to MiWi base station"); 467 result.put(39, "Wireless cab using MiWi protocol"); 468 result.put(40, "CAN to WiFi connection with Withrottle to CBUS protocol conversion"); 469 result.put(41, "Turntable controller configured using FLiM"); 470 result.put(42, "Handset (alternative to CANCAB)"); 471 result.put(43, "Touchscreen handset"); 472 result.put(44, "multi-channel RFID reader"); 473 result.put(45, "either a 2ch or 8ch RFID reader"); 474 result.put(46, "Raspberry Pi based module for WiFi"); 475 result.put(47, "DC train controller"); 476 result.put(48, "Nelevator controller"); 477 result.put(49, "128 switch inputs"); 478 result.put(50, "16MHz 25k80 version of CANSERVO8c on CANMIO hardware"); 479 result.put(51, "16MHz 25k80 version of CANACE8MIO on CANMIO hardware"); 480 result.put(52, "16MHz 25k80 version of CANACC8 on CANMIO hardware"); 481 result.put(53, "16MHz 25k80 version of CANACC5 on CANMIO hardware"); 482 result.put(54, "DCC stop generator"); 483 result.put(55, "Command Station with 3A booster"); 484 result.put(56, "Magnet on Track detector"); 485 result.put(57, "16 input equivaent to CANACE8C"); 486 result.put(58, "CBUS module based on Raspberry Pi"); 487 result.put(59, "25K80 version of CANLED64"); 488 result.put(60, "Compute Event processing engine"); 489 result.put(61, "Read/Write from/to RC522 RFID tags"); 490 result.put(62, "8 inputs module (2g version of CANACE8c)"); 491 result.put(63, "8 outputs module (2g version of CANACC8)"); 492 result.put(64, "Extended CANMIO (24 I/O ports)"); 493 result.put(65, "DC cab"); 494 result.put(66, "DCC Railcom detector/reader"); 495 result.put(67, "MP3 sound player in response to events (eg: station announcements)"); 496 result.put(68, "Addressed RGB LED driver"); 497 result.put(69, "Servo setting box"); 498 result.put(70, "DC Command station"); 499 result.put(71, "Text message display"); 500 result.put(72, "Signal controller"); 501 result.put(73, "DCC cab with slider control"); 502 result.put(74, "DC ATC module"); 503 result.put(75, "Logic module using and/or gates"); 504 result.put(76, "Q series PIC input module"); 505 result.put(77, "Q series PIC output module"); 506 result.put(78, "Q series PIC BIP module"); 507 result.put(79, "Message buffer"); 508 result.put(80, "Lever frame module"); 509 result.put(81, "Kit 110 Arduino shield test firmware"); 510 result.put(82, "4 inputs 4 outputs (Arduino module)"); 511 result.put(83, "CANCMD with built in booster"); 512 result.put(84, "neopixel driver"); 513 result.put(85, "Cab2 with pot or encoder"); 514 result.put(86, "Smart train detector"); 515 result.put(87, "Addressable LEDs"); 516 517 result.put(252, "All VLCB modules have the same ID"); 518 result.put(253, "USB interface"); 519 result.put(254, "Empty module, bootloader only"); 520 result.put(255, "Software nodes"); 521 return Collections.unmodifiableMap(result); 522 } 523 524 /* 525 * Populate hashmap with format strings 526 * extra text for Rocrail Modules 527 */ 528 private static Map<Integer, String> createExtra70Map() { 529 Map<Integer, String> result = new HashMap<>(); 530 result.put(1, "RS232 PC interface."); 531 result.put(2, "16 I/O."); 532 result.put(3, "Command station (derived from cancmd)."); 533 result.put(4, "8 channel RFID reader."); 534 result.put(5, "Cab for fixed panels (derived from cancab)."); 535 result.put(6, "4 channel servo controller."); 536 result.put(7, "Fast clock module."); 537 result.put(11, "CAN Ethernet interface."); 538 return Collections.unmodifiableMap(result); 539 } 540 541 /* 542 * Populate hashmap with format strings 543 * extra text for Animated Modeller module types 544 */ 545 private static Map<Integer, String> createExtra80Map() { 546 Map<Integer, String> result = new HashMap<>(); 547 result.put(1, "Animation controller (firmware derived from cancmd)."); 548 result.put(2, "Dual cab based on cancab."); 549 return Collections.unmodifiableMap(result); 550 } 551 552 553 /* 554 * Populate hashmap with format strings 555 * extra text for Animated Modeller module types 556 */ 557 private static Map<Integer, String> createExtra44Map() { 558 Map<Integer, String> result = new HashMap<>(); 559 result.put(1, "Pi-SPROG 3 programmer/command station."); 560 result.put(2, "SPROG 3 Plus programmer/command station."); 561 result.put(3, "CAN SPROG programmer/command station."); 562 result.put(4, "System booster"); 563 result.put(5, "Unsupported module type"); 564 565 result.put(8, "8-channel twin-coil solenoid, like MERG CANACC4_2."); 566 result.put(50, "8-channel servo I/O, like MERG CANMIO_SVO."); 567 568 result.put(100, "Isolated USB to CAN interface with CBUS node."); 569 result.put(101, "8-channel twin-coil solenoid I/O."); 570 return Collections.unmodifiableMap(result); 571 } 572 573 574 /** 575 * Return a string representation of Module Support Link 576 * @param man int manufacturer ID 577 * @param type int module type ID 578 * @return string module support link, else empty string 579 */ 580 public static String getModuleSupportLink(int man, int type) { 581 String format=""; 582 if (man == MANU_MERG) { 583 format = link165Map.get(type); 584 } 585 else if (man == MANU_ROCRAIL) { 586 format = link70Map.get(type); 587 } 588 else if (man == SPROG_DCC) { 589 format = link44Map.get(type); 590 } 591 if ( format == null ){ 592 return (""); 593 } 594 return format; 595 } 596 597 private static final Map<Integer, String> link165Map = createLink165Map(); 598 private static final Map<Integer, String> link70Map = createLink70Map(); 599 private static final Map<Integer, String> link44Map = createLink44Map(); 600 601 /* 602 * Populate hashmap with merg module support links 603 */ 604 private static Map<Integer, String> createLink165Map() { 605 Map<Integer, String> result = new HashMap<>(); 606 607 result.put(1, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canacc4"); // NOI18N 608 result.put(2, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canacc5"); // NOI18N 609 result.put(3, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canacc8"); // NOI18N 610 result.put(4, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canace3"); // NOI18N 611 result.put(5, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canace8c"); // NOI18N 612 // result.put(6, "CANLED"); // NOI18N 613 result.put(7, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canled64"); // NOI18N 614 result.put(8, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canacc4"); // NOI18N 615 result.put(9, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:cancab"); // NOI18N 616 result.put(10, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:cancmd"); // NOI18N 617 // result.put(11, "CANSERVO"); // NOI18N 618 // result.put(12, "CANBC"); // NOI18N 619 // result.put(13, "CANRPI"); // NOI18N 620 result.put(14, "https://www.merg.org.uk/merg_wiki/doku.php?id=other_download:turntable"); // NOI18N 621 result.put(15, "https://www.merg.org.uk/merg_wiki/doku.php?id=other_download:turntable"); // NOI18N 622 // result.put(16, "CANHS"); // NOI18N 623 result.put(17, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canace8c"); // NOI18N 624 // result.put(18, "CAN8I8O"); // NOI18N 625 result.put(19, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canservo8"); // NOI18N 626 result.put(20, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canrfid"); // NOI18N 627 // result.put(21, "CANTC4"); // NOI18N 628 // result.put(22, "CANACE16C"); // NOI18N 629 // result.put(23, "CANIO8"); // NOI18N 630 // result.put(24, "CANSNDX"); // NOI18N 631 result.put(25, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canether"); // NOI18N 632 result.put(26, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:cansig"); // NOI18N 633 result.put(27, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:cansig"); // NOI18N 634 result.put(28, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canccond8c"); // NOI18N 635 result.put(29, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canpan"); // NOI18N 636 result.put(30, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canace3"); // NOI18N 637 result.put(31, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canpanel"); // NOI18N 638 result.put(32, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canmio"); // NOI18N 639 // result.put(33, "CANACE8MIO"); // NOI18N 640 result.put(34, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:cansol"); // NOI18N 641 result.put(35, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canbip"); // NOI18N 642 result.put(36, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:cancdu"); // NOI18N 643 // result.put(37, "CANACC4CDU"); // NOI18N 644 // result.put(38, "CANWiBase"); // NOI18N 645 // result.put(39, "WiCAB"); // NOI18N 646 // result.put(40, "CANWiFi"); // NOI18N 647 // result.put(41, "CANFTT"); // NOI18N 648 // result.put(42, "CANHNDST"); // NOI18N 649 // result.put(43, "CANTCHNDST"); // NOI18N 650 result.put(44, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canrfid8"); // NOI18N 651 result.put(45, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canmchrfid"); // NOI18N 652 result.put(46, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canwi"); // NOI18N 653 result.put(47, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:can4dc"); // NOI18N 654 // result.put(48, "CANELEV"); // NOI18N 655 result.put(49, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canscan"); // NOI18N 656 result.put(50, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canmio"); // NOI18N 657 result.put(51, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canmio"); // NOI18N 658 result.put(52, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canmio"); // NOI18N 659 // result.put(53, "CANBIP_OUT"); // NOI18N 660 result.put(54, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canastop"); // NOI18N 661 result.put(55, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:cancsb"); // NOI18N 662 // result.put(56, "CANMAGOT"); // NOI18N 663 // result.put(57, "CANACE16CMIO"); // NOI18N 664 // result.put(58, "CANPiNODE"); // NOI18N 665 result.put(59, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:candisp"); // NOI18N 666 result.put(60, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:cancompute"); // NOI18N 667 result.put(61, "https://merg.org.uk/merg_wiki/doku.php?id=cbus:canrc522"); // NOI18N 668 result.put(62, "https://merg.org.uk/merg_wiki/doku.php?id=cbus:caninp"); // NOI18N 669 result.put(63, "https://merg.org.uk/merg_wiki/doku.php?id=cbus:canout"); // NOI18N 670 // result.put(64, "CANEMIO"); // NOI18N 671 result.put(65, "https://merg.org.uk/merg_wiki/doku.php?id=cbus:cancabdc"); // NOI18N 672 result.put(66, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:canrcom"); // NOI18N 673 // result.put(67, "CANMP3"); 674 result.put(68, "https://www.merg.org.uk/merg_wiki/doku.php?id=projects:canxmas"); 675 // result.put(69, "CANSVOSET"); 676 // result.put(70, "CANCMDDC"); 677 // result.put(71, "CANTEXT"); 678 // result.put(72, "CANASIGNAL"); 679 result.put(73, "https://www.merg.org.uk/merg_wiki/doku.php?id=projects:canslider"); 680 // result.put(74, "CANDCATC"); 681 result.put(75, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:cangate"); 682 // result.put(76, "CANSINP"); 683 // result.put(77, "CANSOUT"); 684 // result.put(78, "CANSBIP"); 685 // result.put(79, "CANBUFFER"); 686 // result.put(80, "CANLEVER"); 687 // result.put(81, "CANSHIELD"); 688 // result.put(82, "CAN4IN4OUT"); 689 result.put(83, "https://www.merg.org.uk/merg_wiki/doku.php?id=cbus:cancmdb"); 690 // result.put(84, "CANPIXEL"); 691 // result.put(85, "CANCABPE"); 692 // result.put(86, "CANSMARTTD"); 693 // result.put(87, "CANARGB"); 694 695 // result.put(252, "VLCB"); 696 // result.put(253, "CANUSB"); // NOI18N 697 // result.put(254, "EMPTY"); // NOI18N 698 // result.put(255, "CAN_SW"); // NOI18N 699 700 return Collections.unmodifiableMap(result); 701 } 702 703 /* 704 * Populate hashmap with rocrail module support links 705 */ 706 private static Map<Integer, String> createLink70Map() { 707 Map<Integer, String> result = new HashMap<>(); 708 result.put(1, "https://wiki.rocrail.net/doku.php?id=can-gca1-en"); // NOI18N 709 result.put(2, "https://wiki.rocrail.net/doku.php?id=can-gca2-en"); // NOI18N 710 result.put(3, "https://wiki.rocrail.net/doku.php?id=can-gc3-en"); // NOI18N 711 result.put(4, "https://wiki.rocrail.net/doku.php?id=can-gc4-en"); // NOI18N 712 result.put(5, "https://wiki.rocrail.net/doku.php?id=can-gca5-en"); // NOI18N 713 result.put(6, "https://wiki.rocrail.net/doku.php?id=can-gc6-en"); // NOI18N 714 result.put(7, "https://wiki.rocrail.net/doku.php?id=can-gc7-en"); // NOI18N 715 result.put(11, "https://wiki.rocrail.net/doku.php?id=can-gca1e-en"); // NOI18N 716 return Collections.unmodifiableMap(result); 717 } 718 719 720 /* 721 * Populate hashmap with SPROG module support links 722 */ 723 private static Map<Integer, String> createLink44Map() { 724 Map<Integer, String> result = new HashMap<>(); 725 result.put(1, "https://www.sprog-dcc.co.uk/download-page"); // NOI18N 726 result.put(2, "https://www.sprog-dcc.co.uk/download-page"); // NOI18N 727 result.put(3, "https://www.sprog-dcc.co.uk/download-page"); // NOI18N 728 result.put(4, "https://www.sprog-dcc.co.uk/download-page"); // NOI18N 729 result.put(5, "https://www.sprog-dcc.co.uk/download-page"); // NOI18N 730 result.put(8, "https://www.sprog-dcc.co.uk/download-page"); // NOI18N 731 result.put(50, "https://www.sprog-dcc.co.uk/download-page"); // NOI18N 732 result.put(100, "https://www.sprog-dcc.co.uk/download-page"); // NOI18N 733 result.put(101, "https://www.sprog-dcc.co.uk/download-page"); // NOI18N 734 return Collections.unmodifiableMap(result); 735 } 736 737 738 /** 739 * Return a string representation of a reserved node number 740 * @param modnum node number 741 * @return reserved node number reason 742 */ 743 public static String getReservedModule(int modnum) { 744 // look for the opcode 745 String format = resMod.get(modnum); 746 if (format == null) { 747 return ""; 748 } else { 749 return format; 750 } 751 } 752 753 /** 754 * Hashmap for fixed Module Numbers 755 */ 756 private static final Map<Integer, String> resMod = createModMap(); 757 758 /* 759 * Populate hashmap with format strings 760 * 761 */ 762 private static Map<Integer, String> createModMap() { 763 Map<Integer, String> result = new HashMap<>(); 764 765 for (int i = 100; i < 126; i++) { 766 result.put(i, Bundle.getMessage("NdNumReserveFixed")); // NOI18N 767 } 768 // use html with br so text fits into dialogue 769 result.put(120, "Reserved / Command Station Shuttles"); 770 result.put(126, "Reserved for CAN_RS Modules"); 771 result.put(127, "Reserved for CAN_USB Modules"); 772 result.put(162, "Used in Command Station Shuttles"); 773 result.put(163, "Used in Command Station Shuttles"); 774 result.put(164, "Used in Command Station Shuttles"); 775 result.put(167, "Used in Command Station Shuttles"); 776 result.put(65534, "Reserved for Command Station"); 777 result.put(65535, "Reserved, used by all CABS"); 778 return Collections.unmodifiableMap(result); 779 } 780 781 private static final Map<String, BackupType> nameIndex = 782 new HashMap<>(BackupType.values().length); 783 static { 784 for (BackupType t : BackupType.values()) { 785 nameIndex.put(t.name(), t); 786 } 787 } 788 789 private static final Map<BackupType, String> displayPhraseIndex = 790 new HashMap<>(BackupType.values().length); 791 static { 792 displayPhraseIndex.put(BackupType.INCOMPLETE, Bundle.getMessage("BackupIncomplete")); 793 displayPhraseIndex.put(BackupType.COMPLETE, Bundle.getMessage("BackupComplete")); 794 displayPhraseIndex.put(BackupType.COMPLETEDWITHERROR, Bundle.getMessage("BackupCompleteError")); 795 displayPhraseIndex.put(BackupType.NOTONNETWORK, Bundle.getMessage("BackupNotOnNetwork")); 796 displayPhraseIndex.put(BackupType.OUTSTANDING, Bundle.getMessage("BackupOutstanding")); 797 displayPhraseIndex.put(BackupType.SLIM, Bundle.getMessage("NodeInSlim")); 798 } 799 800 /* 801 * Get the display phrase for an enum value 802 * <p> 803 * eg. displayPhrase(BackupType.INCOMPLETE) will return "Backup InComplete" 804 * 805 * @param type The enum to translate 806 * @return The phrase 807 * 808 */ 809 public static String displayPhrase(BackupType type) { 810 return displayPhraseIndex.get(type); 811 } 812 813 /* 814 * Get the enum type for a String value 815 * <p> 816 * eg. lookupByName("Complete") will return BackupType.COMPLETE 817 * 818 * @param name The String to lookup 819 * @return The BackupType enum, else null 820 * 821 */ 822 public static BackupType lookupByName(String name) { 823 return nameIndex.get(name); 824 } 825 826 /* 827 * enum to represent Node Backup Conditions in a CBUS Node XML File 828 * 829 */ 830 public enum BackupType{ 831 INCOMPLETE(0), 832 COMPLETE(1), 833 COMPLETEDWITHERROR(2), 834 NOTONNETWORK(3), 835 OUTSTANDING(4), 836 SLIM(5); 837 838 private final int v; 839 840 BackupType(final int v) { 841 this.v = v; 842 } 843 844 public int getValue() { 845 return v; 846 } 847 848 } 849 850 // private final static Logger log = LoggerFactory.getLogger(CbusNodeConstants.class); 851}