001package jmri.jmrix.ecos;
002
003import java.util.regex.Matcher;
004import java.util.regex.Pattern;
005import jmri.DccLocoAddress;
006import jmri.IdTag;
007import jmri.IdTagManager;
008import jmri.InstanceManager;
009import jmri.LocoAddress;
010import jmri.PhysicalLocationReporter;
011import jmri.implementation.AbstractReporter;
012import jmri.util.PhysicalLocation;
013import org.slf4j.Logger;
014import org.slf4j.LoggerFactory;
015
016/**
017 * Extend jmri.AbstractReporter for Ecos Reporters Implemenation for providing
018 * status of rail com decoders at this reporter location.
019 * <p>
020 * The reporter will decode the rail com packets and add the information to the
021 * rail com tag.
022 *
023 * @author Kevin Dickerson Copyright (C) 2012
024 */
025public class EcosReporter extends AbstractReporter implements PhysicalLocationReporter {
026
027    public EcosReporter(String systemName, String userName) {  // a human-readable Reporter number must be specified!
028        super(systemName, userName);  // can't use prefix here, as still in construction
029    }
030
031    /**
032     * Provide an int value for use in scripts, etc. This will be the numeric
033     * locomotive address last seen, unless the last message said the loco was
034     * exiting. Note that there may still some other locomotive in the
035     * transponding zone!
036     *
037     * @return -1 if the last message specified exiting
038     */
039    @Override
040    public int getState() {
041        return lastLoco;
042    }
043
044    @Override
045    public void setState(int s) {
046        lastLoco = s;
047    }
048    int lastLoco = -1;
049
050    private int object;
051    private int port;
052
053    public int getObjectId() {
054        return object;
055    }
056
057    public int getPort() {
058        return port;
059    }
060
061    public void setObjectPort(int object, int port) {
062        this.object = object;
063        this.port = port;
064    }
065
066    //This could possibly do with a debounce option being added
067    public void decodeDetails(String msg) {
068        int start = msg.indexOf('[') + 1;
069        int end = msg.indexOf(']');
070        String[] result = msg.substring(start, end).split(",");
071        result[1] = result[1].trim();
072        if (!result[1].equals("0000")) {
073            IdTag idTag = jmri.InstanceManager.getDefault(jmri.IdTagManager.class).provideIdTag(result[1]);
074            setReport(idTag);
075        } else {
076            setReport(null);
077        }
078    }
079
080    // Methods to support PhysicalLocationReporter interface
081
082    /**
083     * Get the locomotive address we're reporting about from the current report.
084     *
085     * Note: We ignore the string passed in, because Ecos Reporters don't send
086     * String type reports.
087     */
088    @Override
089    public LocoAddress getLocoAddress(String rep) {
090        // For now, we assume the current report.
091        // IdTag.getTagID() is a system-name-ized version of the loco address. I think.
092        // Matcher.group(1) : loco address (I think)
093        IdTag cr = (IdTag) this.getCurrentReport();
094        IdTagManager tm = InstanceManager.getDefault(IdTagManager.class);
095        Pattern p = Pattern.compile("" + tm.getSystemPrefix() + tm.typeLetter() + "(\\d+)");
096        Matcher m = p.matcher(cr.getTagID());
097        if (m.find()) {
098            log.debug("Parsed address: {}", m.group(1));
099            // I have no idea what kind of loco address an Ecos reporter uses,
100            // so we'll default to DCC for now.
101            return (new DccLocoAddress(Integer.parseInt(m.group(1)), LocoAddress.Protocol.DCC));
102        } else {
103            return (null);
104        }
105    }
106
107    /**
108     * Get the direction (ENTER/EXIT) of the report. Because of the way Ecos.
109     * Reporters work (or appear to), all reports are ENTER type.
110     */
111    @Override
112    public PhysicalLocationReporter.Direction getDirection(String rep) {
113        // TEMPORARY:  Assume we're always Entering, if asked.
114        return (PhysicalLocationReporter.Direction.ENTER);
115    }
116
117    /**
118     * Get the PhysicalLocation of the Reporter
119     * <p>
120     * Reports its own location, for now. Not sure if that's the right thing or
121     * not. NOT DONE YET
122     */
123    @Override
124    public PhysicalLocation getPhysicalLocation() {
125        return (this.getPhysicalLocation(null));
126    }
127
128    /**
129     * Get the PhysicalLocation of the Reporter.
130     *
131     * @param s is not used
132     */
133    @Override
134    public PhysicalLocation getPhysicalLocation(String s) {
135        return (PhysicalLocation.getBeanPhysicalLocation(this));
136    }
137
138    private final static Logger log = LoggerFactory.getLogger(EcosReporter.class);
139
140}