001package jmri.jmrix.can.cbus; 002 003import java.util.ArrayList; 004import java.util.List; 005 006import javax.annotation.Nonnull; 007 008import jmri.*; 009import jmri.jmrix.can.CanSystemConnectionMemo; 010import jmri.managers.AbstractReporterManager; 011 012import org.slf4j.Logger; 013import org.slf4j.LoggerFactory; 014 015/** 016 * Implement ReporterManager for CAN CBUS systems. 017 * <p> 018 * System names are "MRnnnnn", where M is the user-configurable system getSystemPrefix(), 019 * nnnnn is the reporter number without padding. 020 * <p> 021 * CBUS Reporters are NOT automatically created. 022 * 023 * @author Mark Riddoch Copyright (C) 2015 024 * @author Steve Young Copyright (C) 2019 025 */ 026public class CbusReporterManager extends AbstractReporterManager { 027 028 public CbusReporterManager(CanSystemConnectionMemo memo) { 029 super(memo); 030 } 031 032 /** 033 * {@inheritDoc} 034 */ 035 @Override 036 @Nonnull 037 public CanSystemConnectionMemo getMemo() { 038 return (CanSystemConnectionMemo) memo; 039 } 040 041 /** 042 * {@inheritDoc} 043 */ 044 @Override 045 @Nonnull 046 protected Reporter createNewReporter(@Nonnull String systemName, String userName) throws IllegalArgumentException { 047 log.debug("ReporterManager create new CbusReporter: {}", systemName); 048 String addr = systemName.substring(getSystemNamePrefix().length()); 049 Reporter t = new CbusReporter(addr, getMemo()); 050 t.setUserName(userName); 051 t.addPropertyChangeListener(this); 052 return t; 053 } 054 055 /** 056 * {@inheritDoc} 057 * Checks for reporter number between 0 and 65535 058 */ 059 @Override 060 public NameValidity validSystemNameFormat(@Nonnull String systemName) { 061 // name must be in the MSnnnnn format (M is user configurable); no + or ; or - for Reporter address 062 log.debug("Checking system name: {}", systemName); 063 try { 064 // try to parse the string; success returns true 065 int testnum = Integer.parseInt(systemName.substring(getSystemPrefix().length() + 1, systemName.length())); 066 if ( testnum < 0 ) { 067 log.debug("Number field cannot be negative in system name: {}", systemName); 068 return NameValidity.INVALID; 069 } 070 if ( testnum > 65535 ) { 071 log.debug("Number field cannot be greater than 65535 in system name: {}", systemName); 072 return NameValidity.INVALID; 073 } 074 } 075 catch (NumberFormatException e) { 076 log.debug("Illegal character in number field of system name: {}", systemName); 077 return NameValidity.INVALID; 078 } 079 catch (StringIndexOutOfBoundsException e) { 080 log.debug("Wrong length ( missing MR? ) for system name: {}", systemName); 081 return NameValidity.INVALID; 082 } 083 log.debug("Valid system name: {}", systemName); 084 return NameValidity.VALID; 085 } 086 087 /** 088 * {@inheritDoc} 089 */ 090 @Override 091 public boolean allowMultipleAdditions(@Nonnull String systemName) { 092 return true; 093 } 094 095 /** 096 * {@inheritDoc} 097 */ 098 @Override 099 public String getEntryToolTip() { 100 return Bundle.getMessage("AddReporterEntryToolTip"); 101 } 102 103 /** 104 * Validates to only numeric system names. 105 * {@inheritDoc} 106 */ 107 @Override 108 @Nonnull 109 public String validateSystemNameFormat(@Nonnull String name, @Nonnull java.util.Locale locale) throws jmri.NamedBean.BadSystemNameException { 110 return validateSystemNameFormatOnlyNumeric(name,locale); 111 } 112 113 protected final static String CBUS_REPORTER_DESCRIPTOR_KEY = "CBUS Reporter Type"; // NOI18N 114 115 protected final static String CBUS_REPORTER_TYPE_CLASSIC = "Classic RFID"; // NOI18N 116 117 protected final static String CBUS_REPORTER_TYPE_DDES_DESCRIBING = "CANRC522 / CANRCOM"; // NOI18N 118 119 final static String[] CBUS_REPORTER_TYPES = { 120 CBUS_REPORTER_TYPE_CLASSIC,CBUS_REPORTER_TYPE_DDES_DESCRIBING}; 121 122 final static String[] CBUS_REPORTER_TYPE_TIPS = { 123 "DDES / ACDAT 5 byte unique tag.","DDES self-describing ( Writeable CANRC522 / Railcom )"}; // NOI18N 124 125 protected final static String CBUS_DEFAULT_REPORTER_TYPE = CBUS_REPORTER_TYPES[0]; 126 127 protected final static String CBUS_MAINTAIN_SENSOR_DESCRIPTOR_KEY = "Maintain CBUS Sensor"; // NOI18N 128 129 @Override 130 @Nonnull 131 public List<NamedBeanPropertyDescriptor<?>> getKnownBeanProperties() { 132 List<NamedBeanPropertyDescriptor<?>> l = new ArrayList<>(); 133 l.add(new SelectionPropertyDescriptor( 134 CBUS_REPORTER_DESCRIPTOR_KEY, CBUS_REPORTER_TYPES, CBUS_REPORTER_TYPE_TIPS, CBUS_DEFAULT_REPORTER_TYPE) { 135 @Override 136 public String getColumnHeaderText() { 137 return CBUS_REPORTER_DESCRIPTOR_KEY; 138 } 139 @Override 140 public boolean isEditable(NamedBean bean) { 141 return (bean instanceof CbusReporter); 142 } 143 }); 144 l.add(new BooleanPropertyDescriptor( 145 CBUS_MAINTAIN_SENSOR_DESCRIPTOR_KEY, false) { 146 @Override 147 public String getColumnHeaderText() { 148 return CBUS_MAINTAIN_SENSOR_DESCRIPTOR_KEY; 149 } 150 @Override 151 public boolean isEditable(NamedBean bean) { 152 return (bean instanceof CbusReporter); 153 } 154 }); 155 return l; 156 } 157 158 private int _timeout=2000; // same default as TimeoutReporter 159 160 /** 161 * Set the Reporter timeout. 162 * @param timeout time in milliseconds that CbusReporters stay at IdTag.SEEN after hearing an ID Tag. 163 */ 164 public void setTimeout(int timeout){ 165 _timeout = timeout; 166 } 167 168 /** 169 * Get the Reporter Timeout. 170 * @return milliseconds for CbusReporters to return to IdTag.UNSEEN 171 */ 172 public int getTimeout(){ 173 return _timeout; 174 } 175 176 private static final Logger log = LoggerFactory.getLogger(CbusReporterManager.class); 177 178}