001package jmri.jmrix.dcc4pc; 002 003import java.beans.PropertyChangeListener; 004import java.util.List; 005import javax.annotation.Nonnull; 006import jmri.RailCom; 007import jmri.AddressedProgrammer; 008import jmri.AddressedProgrammerManager; 009import jmri.ProgListener; 010import jmri.Programmer; 011import jmri.ProgrammerException; 012import jmri.ProgrammingMode; 013 014/** 015 * Provides an Ops mode proxy programming interface for a RailCom Reader. This 016 * forwards the read request to the command station to forward on and handles 017 * sending back the CV reading results from the RailCom message 018 * 019 * @see jmri.Programmer 020 * @author Kevin Dickerson Copyright (C) 2012 021 */ 022public class Dcc4PcOpsModeProgrammer extends jmri.jmrix.AbstractProgrammer implements PropertyChangeListener, AddressedProgrammer { 023 024 int pAddress = 0; 025 boolean pLongAddress; 026 int progState = 0; 027 RailCom rcTag; 028 int value; 029 int cv; 030 jmri.ProgListener progListener = null; 031 032 static protected final int DCC4PC_PROGRAMMER_TIMEOUT = 2000; 033 034 AddressedProgrammerManager defaultManager; 035 Programmer defaultProgrammer; 036 037 public Dcc4PcOpsModeProgrammer(boolean pLongAddress, int pAddress, AddressedProgrammerManager dp) { 038 defaultManager = dp; 039 defaultProgrammer = defaultManager.getAddressedProgrammer(pLongAddress, pAddress); 040 this.pAddress = pAddress; 041 this.pLongAddress = pLongAddress; 042 rcTag = (RailCom) jmri.InstanceManager.getDefault(jmri.RailComManager.class).provideIdTag("" + pAddress); 043 } 044 045 /** 046 * {@inheritDoc} 047 * 048 * Send an ops-mode write request to the XPressnet. 049 */ 050 @Override 051 synchronized public void writeCV(String CVname, int val, ProgListener p) throws ProgrammerException { 052 final int CV = Integer.parseInt(CVname); 053 rcTag.setExpectedCv(CV); 054 progListener = p; 055 defaultProgrammer.writeCV(CVname, val, new ProxyProgList()); 056 } 057 058 /** 059 * {@inheritDoc} 060 */ 061 @Override 062 synchronized public void readCV(String CVname, ProgListener p) throws ProgrammerException { 063 final int CV = Integer.parseInt(CVname); 064 rcTag.addPropertyChangeListener(this); 065 rcTag.setExpectedCv(CV); 066 progListener = p; 067 this.cv = CV; 068 startLongTimer(); 069 defaultProgrammer.readCV(CVname, new ProxyProgList()); 070 notifyProgListenerEnd(progListener, CV, jmri.ProgListener.OK); // this call seems seriously misplaced; is it an error? 071 } 072 073 static class ProxyProgList implements jmri.ProgListener { 074 075 ProxyProgList() { 076 } 077 078 @Override 079 public void programmingOpReply(int value, int status) { 080 /*if(status!=NotImplemented){ 081 notifyProgListenerEnd(progListener, 0, status); 082 } 083 log.debug("Actual Command station returned " + status + " " + value);*/ 084 } 085 } 086 087 /** 088 * {@inheritDoc} 089 */ 090 @Override 091 public void confirmCV(String cvName, int val, ProgListener p) throws ProgrammerException { 092 int cvValue = Integer.parseInt(cvName); 093 rcTag.addPropertyChangeListener(this); 094 rcTag.setExpectedCv(cvValue); 095 synchronized (this) { 096 progListener = p; 097 } 098 this.cv = cvValue; 099 defaultProgrammer.confirmCV(cvName, val, new ProxyProgList()); 100 } 101 102 /** 103 * {@inheritDoc} 104 * 105 * Types implemented here. 106 */ 107 @Override 108 @Nonnull 109 public List<ProgrammingMode> getSupportedModes() { 110 return defaultProgrammer.getSupportedModes(); 111 } 112 113 /** 114 * {@inheritDoc} 115 */ 116 @Override 117 synchronized protected void timeout() { 118 rcTag.removePropertyChangeListener(this); 119 rcTag.setExpectedCv(-1); 120 notifyProgListenerEnd(progListener, 0, ProgListener.FailedTimeout); 121 } 122 123 /** 124 * {@inheritDoc} 125 */ 126 @Override 127 public void propertyChange(java.beans.PropertyChangeEvent e) { 128 if (e.getSource() != rcTag) { 129 log.error("Unexpected source"); 130 } 131 if (e.getPropertyName().equals("cvvalue")) { 132 int repliedCv = (Integer) e.getOldValue(); 133 log.info("propertyChange {} {}", e.getOldValue(), e.getNewValue()); 134 if (repliedCv == cv) { 135 int newValue = (Integer) e.getNewValue(); 136 stopTimer(); 137 rcTag.removePropertyChangeListener(this); 138 synchronized (this) { 139 notifyProgListenerEnd(progListener, newValue, ProgListener.OK); 140 } 141 } else { 142 log.error("Unexpected cv {} returned, was expecting CV {}", repliedCv, cv); 143 } 144 } 145 } 146 147 /** 148 * {@inheritDoc} 149 */ 150 @Override 151 public boolean getLongAddress() { 152 return pLongAddress; 153 } 154 155 /** 156 * {@inheritDoc} 157 */ 158 @Override 159 public int getAddressNumber() { 160 return pAddress; 161 } 162 163 /** 164 * {@inheritDoc} 165 */ 166 @Override 167 public String getAddress() { 168 return "" + getAddressNumber() + " " + getLongAddress(); 169 } 170 171 // initialize logging 172 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Dcc4PcOpsModeProgrammer.class); 173 174}