001package jmri.jmrix.roco.z21; 002 003import java.util.Locale; 004import jmri.Manager; 005import jmri.Manager.NameValidity; 006import jmri.NamedBean; 007import org.slf4j.Logger; 008import org.slf4j.LoggerFactory; 009 010import javax.annotation.Nonnull; 011 012/** 013 * Utility Class supporting parsing and testing of addresses for Z21 RMBus 014 * <p> 015 * One address format are supported: 016 * <ul> 017 * <li> 018 * ZSxxxx where: 'S' for sensors, 019 * </li> 020 * </ul> 021 * 022 * @author Dave Duchamp, Copyright (C) 2004 - 2006 023 * @author Bob Coleman Copyright (C) 2007, 2008, 2009 024 * @author Egbert Broerse (C) 2017 Based on Acela example, modified for XpressNet. 025 */ 026public class Z21RMBusAddress { 027 028 private Z21RMBusAddress() { 029 // class of static functions 030 } 031 032 static final int MINSENSORADDRESS = 1; 033 static final int MAXSENSORADDRESS = 160; // 20 RM bus modules with 8 contacts each. 034 035 /** 036 * Public static method to parse a Z21RMBus system name.Note: Bits are numbered from 1. 037 * 038 * @param systemName system name. 039 * @param prefix system prefix. 040 * @return the hardware address number, return -1 if an error is found 041 */ 042 public static int getBitFromSystemName(String systemName, String prefix) { 043 // validate the system Name leader characters 044 if (!systemName.startsWith(prefix)) { 045 // here if an invalid Z21 RM Bus system name 046 log.error("invalid character in header field of Z21 RM Bus system name: {}", systemName); 047 return (-1); 048 } 049 int num; 050 try { 051 String curAddress = systemName.substring(prefix.length() + 1); 052 num = Integer.parseInt(curAddress); 053 } catch (NumberFormatException e) { 054 log.warn("invalid character in number field of system name: {}", systemName); 055 return (-1); 056 } 057 if ((num >= MINSENSORADDRESS) && (num <= MAXSENSORADDRESS)) { 058 return (num); 059 } 060 log.warn("Z21 RM Bus hardware address out of range in system name {}", systemName); 061 return (-1); 062 } 063 064 /** 065 * Validate a system name format. 066 * 067 * @param name the name to validate 068 * @param manager the manager requesting validation 069 * @param locale the locale for user messages 070 * @return name, unchanged 071 * @see jmri.Manager#validateSystemNameFormat(java.lang.String, 072 * java.util.Locale) 073 */ 074 public static String validateSystemNameFormat(String name, Manager<?> manager, Locale locale) { 075 try { 076 return manager.validateIntegerSystemNameFormat(name, 1, 160, locale); 077 } catch (NumberFormatException ex) { 078 throw new NamedBean.BadSystemNameException( 079 Bundle.getMessage(Locale.ENGLISH, "SystemNameInvalidRMAddress", name), 080 Bundle.getMessage(locale, "SystemNameInvalidRMAddress", name)); 081 } 082 } 083 084 /** 085 * Public static method to validate system name format. 086 * Logging of handled cases no higher than WARN. 087 * 088 * @param systemName system name. 089 * @param type bean type, S for Sensor, T for Turnout. 090 * @param prefix system prefix. 091 * @return VALID if system name has a valid format, else return INVALID 092 */ 093 public static NameValidity validSystemNameFormat(@Nonnull String systemName, char type, String prefix) { 094 // validate the system Name leader characters 095 if (!(systemName.startsWith(prefix + type))) { 096 // here if an illegal format 097 log.error("invalid character in header field of system name: {}", systemName); 098 return NameValidity.INVALID; 099 } 100 int address = getBitFromSystemName(systemName,prefix); 101 if (address >= 0 && address <= 160 ) { 102 return NameValidity.VALID; 103 } else { 104 return NameValidity.INVALID; 105 } 106 } 107 108 /** 109 * Public static method to check the user name for a valid system name. 110 * 111 * @param systemName system name. 112 * @param prefix system prefix. 113 * @return "" (null string) if the system name is not valid or does not exist 114 */ 115 public static String getUserNameFromSystemName(String systemName, String prefix) { 116 // check for a valid system name 117 if ((systemName.length() < (prefix.length() + 2)) || (!systemName.startsWith(prefix))) { 118 // not a valid system name for Z21 RM Bus 119 return (""); 120 } 121 // check for a sensor 122 if (systemName.charAt(prefix.length() + 1) == 'S') { 123 jmri.Sensor s; 124 s = jmri.InstanceManager.sensorManagerInstance().getBySystemName(systemName); 125 if (s != null) { 126 return s.getUserName(); 127 } else { 128 return (""); 129 } 130 } 131 // not any known sensor 132 return (""); 133 } 134 135 private static final Logger log = LoggerFactory.getLogger(Z21RMBusAddress.class); 136 137}