001package jmri.jmrix.roco.z21; 002 003import jmri.DccLocoAddress; 004import jmri.InstanceManager; 005import jmri.RailCom; 006import jmri.RailComManager; 007 008/** 009 * Z21Reporter implements the Reporter Manager interface 010 * for Roco Z21 systems. 011 * <p> 012 * Reports from this reporter are of the type jmri.RailCom. 013 * 014 * @author Paul Bender Copyright (C) 2016 015 */ 016public class Z21Reporter extends jmri.implementation.AbstractRailComReporter implements Z21Listener { 017 018 private Z21SystemConnectionMemo _memo; 019 020 private javax.swing.Timer refreshTimer; // Timer used to periodically 021 // referesh the RailCom data (this does not appear to happen automatically). 022 private static final int refreshTimeoutValue = 15000; 023 024 /** 025 * Create a new Z21Reporter. 026 * 027 * @param systemName the system name of the new reporter. 028 * @param userName the user name of the new reporter. 029 * @param memo an instance of Z21SystemConnectionMemo this manager 030 * is associated with. 031 * 032 */ 033 public Z21Reporter(String systemName,String userName,Z21SystemConnectionMemo memo){ 034 super(systemName,userName); 035 _memo = memo; 036 _memo.getTrafficController().addz21Listener(this); 037 // request an update from the layout. 038 requestUpdateFromLayout(); 039 refreshTimer(); 040 } 041 042 /** 043 * request an update from the layout. 044 */ 045 private void requestUpdateFromLayout(){ 046 _memo.getTrafficController().sendz21Message(Z21Message.getLanRailComGetDataRequestMessage(),this); 047 } 048 049 // the Z21 Listener interface 050 051 /** 052 * Member function that will be invoked by a z21Interface implementation to 053 * forward a z21 message from the layout. 054 * 055 * @param msg The received z21 reply. Note that this same object may be 056 * presented to multiple users. It should not be modified here. 057 */ 058 @Override 059 public void reply(Z21Reply msg){ 060 // for incoming messages all the reporter cares about is 061 // LAN_RAILCOM_DATACHANGED messages. 062 if(msg.isRailComDataChangedMessage()){ 063 // find out how many RailCom Transmitters the command 064 // station is telling us about (there is a maximum of 19). 065 int tags = msg.getNumRailComDataEntries(); 066 for(int i=0;i<tags;i++){ 067 // get the locomotive address from the message. 068 DccLocoAddress l = msg.getRailComLocoAddress(i); 069 // see if there is a tag for this address. 070 RailCom tag = (RailCom) InstanceManager.getDefault(RailComManager.class).provideIdTag("" + l.getNumber()); 071 tag.setActualSpeed(msg.getRailComSpeed(i)); 072 notify(tag); 073 } 074 if(tags == 0){ 075 notify(null); // clear the current report if no tags. 076 } 077 } 078 } 079 080 /** 081 * Member function that will be invoked by a z21Interface implementation to 082 * forward a z21 message sent to the layout. Normally, this function will do 083 * nothing. 084 * 085 * @param msg The received z21 message. Note that this same object may be 086 * presented to multiple users. It should not be modified here. 087 */ 088 @Override 089 public void message(Z21Message msg){ 090 // we don't need to handle outgoing messages, so just ignore them. 091 } 092 093 /** 094 * Set up the refreshTimer, and start it. 095 */ 096 private void refreshTimer() { 097 if (refreshTimer == null) { 098 refreshTimer = new javax.swing.Timer(refreshTimeoutValue, e -> { 099 // If the timer times out, send a request for status 100 requestUpdateFromLayout(); 101 }); 102 } 103 refreshTimer.stop(); 104 refreshTimer.setInitialDelay(refreshTimeoutValue); 105 refreshTimer.setRepeats(true); 106 refreshTimer.start(); 107 } 108 109 @Override 110 public void dispose(){ 111 super.dispose(); 112 refreshTimer.stop(); 113 } 114 115}