001package jmri.implementation; 002 003import java.util.regex.Matcher; 004import java.util.regex.Pattern; 005 006import javax.annotation.Nonnull; 007 008import jmri.*; 009import jmri.util.PhysicalLocation; 010 011import org.slf4j.Logger; 012import org.slf4j.LoggerFactory; 013 014/** 015 * Extend AbstractReporter for IdTag reporters 016 * <p> 017 * This file is based on @{link jmri.jmrix.rfid.RfidReporter} 018 * 019 * @author Matthew Harris Copyright (c) 2011 020 * @author Paul Bender Copyright (c) 2016, 2019 021 * @since 4.15.3 022 */ 023public class AbstractIdTagReporter extends AbstractReporter 024 implements IdTagListener, PhysicalLocationReporter { 025 026 public AbstractIdTagReporter(String systemName) { 027 super(systemName); 028 } 029 030 public AbstractIdTagReporter(String systemName, String userName) { 031 super(systemName, userName); 032 } 033 034 /** 035 * {@inheritDoc} 036 */ 037 @Override 038 public void notify(IdTag id) { 039 log.debug("Notify: {}",mSystemName); 040 if (id != null) { 041 log.debug("Tag: {}",id); 042 Reporter r = id.getWhereLastSeen(); 043 if (r != null) { 044 notifyPreviousReporter(r,id); 045 } 046 id.setWhereLastSeen(this); 047 log.debug("Seen here: {}",this.mSystemName); 048 } 049 setReport(id); 050 setState(id != null ? IdTag.SEEN : IdTag.UNSEEN); 051 } 052 053 private void notifyPreviousReporter(Reporter r, IdTag id) { 054 log.debug("Previous reporter: {}",r.getSystemName()); 055 if (!(r.equals(this)) && r.getCurrentReport() == id 056 && (r instanceof IdTagListener)) { 057 log.debug("Notify previous"); 058 ((IdTagListener)r).notify(null); 059 } else { 060 log.debug("Current report was: {}",r.getCurrentReport()); 061 } 062 } 063 064 private int state = UNKNOWN; 065 066 /** {@inheritDoc} */ 067 @Override 068 public void setState(int s) { 069 state = s; 070 } 071 072 /** {@inheritDoc} */ 073 @Override 074 public int getState() { 075 return state; 076 } 077 078 /** {@inheritDoc} */ 079 @Override 080 @Nonnull 081 public String describeState(int state) { 082 switch (state) { 083 case IdTag.SEEN: 084 return Bundle.getMessage("IdTagReporterStateSeen"); 085 case IdTag.UNSEEN: 086 return Bundle.getMessage("IdTagReporterStateUnSeen"); 087 default: 088 return super.describeState(state); 089 } 090 } 091 092 // Methods to support PhysicalLocationReporter interface 093 094 /** 095 * Get the locomotive address we're reporting about from the current report. 096 * {@inheritDoc} 097 * @param rep ignored, IdTag Reporters don't send String type reports. 098 */ 099 @Override 100 public LocoAddress getLocoAddress(String rep) { 101 // For now, we assume the current report. 102 // IdTag.getTagID() is a system-name-ized version of the loco address. I think. 103 // Matcher.group(1) : loco address (I think) 104 IdTag cr = (IdTag) this.getCurrentReport(); 105 ReporterManager rm = InstanceManager.getDefault(jmri.ReporterManager.class); 106 Pattern p = Pattern.compile("" + rm.getSystemPrefix() + rm.typeLetter() + "(\\d+)"); 107 Matcher m = p.matcher(cr.getTagID()); 108 if (m.find()) { 109 log.debug("Parsed address: {}", m.group(1)); 110 // I have no idea what kind of loco address an Ecos reporter uses, 111 // so we'll default to DCC for now. 112 return (new DccLocoAddress(Integer.parseInt(m.group(1)), LocoAddress.Protocol.DCC)); 113 } else { 114 return (null); 115 } 116 } 117 118 /** 119 * Gets the direction (ENTER/EXIT) of the report. 120 * <p> 121 * Because of the way 122 * IdTag Reporters work, all reports are ENTER type. 123 * {@inheritDoc} 124 */ 125 @Override 126 public PhysicalLocationReporter.Direction getDirection(String rep) { 127 // TEMPORARY: Assume we're always Entering, if asked. 128 return (PhysicalLocationReporter.Direction.ENTER); 129 } 130 131 /** 132 * Get the PhysicalLocation of the Reporter 133 * 134 * Reports its own location, for now. 135 * Not sure if that's the right thing or 136 * not. NOT DONE YET 137 * 138 * {@inheritDoc} 139 */ 140 @Override 141 public PhysicalLocation getPhysicalLocation() { 142 return (this.getPhysicalLocation(null)); 143 } 144 145 /** 146 * Get the PhysicalLocation of the Reporter. 147 * 148 * {@inheritDoc} 149 * @param s unused. 150 */ 151 @Override 152 public PhysicalLocation getPhysicalLocation(String s) { 153 return (PhysicalLocation.getBeanPhysicalLocation(this)); 154 } 155 156 private static final Logger log = LoggerFactory.getLogger(AbstractIdTagReporter.class); 157 158}