001package jmri.implementation; 002 003import java.util.TimerTask; 004 005import javax.annotation.Nonnull; 006 007import jmri.*; 008import jmri.util.TimerUtil; 009 010/** 011 * Abstract base class for average meter objects. 012 * 013 * @author Mark Underwood (C) 2015 014 * @author Daniel Bergqvist (C) 2025 015 */ 016public class DefaultAverageMeter extends AbstractAnalogIO implements AverageMeter { 017 018 private static final int DELAY = 250; 019 private final int SIZE = 100; 020 private final double[] _measurements = new double[SIZE]; 021 022 private int _numMeasurements = 1; 023 private TimerTask _updateTask; 024 private Meter _meter; 025 private int _time = 1000; // 1 second 026 027 public DefaultAverageMeter(@Nonnull String sys) { 028 this(sys, null); 029 } 030 031 public DefaultAverageMeter(@Nonnull String sys, String user) { 032 super(sys, user, false); 033 DefaultAverageMeter.this.setTime(1000); 034 } 035 036 /** {@inheritDoc} */ 037 @Override 038 public void enable() { 039 log.debug("Enabling meter."); 040 } 041 042 /** {@inheritDoc} */ 043 @Override 044 public void disable() { 045 log.debug("Disabling meter."); 046 } 047 048 /** 049 * {@inheritDoc} 050 * <p> 051 * Override this if the meter can send value to the layout. 052 */ 053 @Override 054 protected void sendValueToLayout(double value) throws JmriException { 055 // Do nothing 056 } 057 058 /** {@inheritDoc} */ 059 @Override 060 protected boolean cutOutOfBoundsValues() { 061 return true; 062 } 063 064 /** {@inheritDoc} */ 065 @Override 066 public void setState(int s) throws JmriException { 067 throw new UnsupportedOperationException("Not supported."); 068 } 069 070 /** {@inheritDoc} */ 071 @Override 072 public int getState() { 073 throw new UnsupportedOperationException("Not supported."); 074 } 075 076 /** {@inheritDoc} */ 077 @Override 078 public String getBeanType() { 079 return Bundle.getMessage("BeanNameMeter"); 080 } 081 082 /** {@inheritDoc} */ 083 @Override 084 public Unit getUnit() { 085 if (_meter != null) { 086 return _meter.getUnit(); 087 } else { 088 return Unit.NoPrefix; 089 } 090 } 091 092 /** {@inheritDoc} */ 093 @Override 094 public double getMin() { 095 if (_meter != null) { 096 return _meter.getMin(); 097 } else { 098 return 0.0; 099 } 100 } 101 102 /** {@inheritDoc} */ 103 @Override 104 public double getMax() { 105 if (_meter != null) { 106 return _meter.getMax(); 107 } else { 108 return 0.0; 109 } 110 } 111 112 /** {@inheritDoc} */ 113 @Override 114 public double getResolution() { 115 if (_meter != null) { 116 return _meter.getResolution(); 117 } else { 118 return 1.0; 119 } 120 } 121 122 /** {@inheritDoc} */ 123 @Override 124 public AbsoluteOrRelative getAbsoluteOrRelative() { 125 if (_meter != null) { 126 return _meter.getAbsoluteOrRelative(); 127 } else { 128 return AbsoluteOrRelative.RELATIVE; 129 } 130 } 131 132 /** 133 * Request an update from the layout. 134 */ 135 @Override 136 public void requestUpdateFromLayout() { 137 _meter.requestUpdateFromLayout(); 138 } 139 140 @Override 141 public int getTime() { 142 return _time; 143 } 144 145 @Override 146 public void setTime(int time) { 147 this._time = time; 148 _numMeasurements = (int) Math.round(((double)_time) / DELAY); 149 } 150 151 @Override 152 public Meter getMeter() { 153 return _meter; 154 } 155 156 @Override 157 public void setMeter(Meter meter) { 158 if (meter == this._meter) { 159 return; 160 } 161 if (_meter != null) { 162 _updateTask.cancel(); 163 } 164 this._meter = meter; 165 if (_meter != null) { 166 _updateTask = new MyTimerTask(); 167 TimerUtil.scheduleOnGUIThread(_updateTask, DELAY, DELAY); 168 } 169 } 170 171 /** {@inheritDoc} */ 172 @Override 173 public double getKnownAnalogValue() { 174 double sum = 0.0; 175 int start = SIZE - _numMeasurements; 176 for (int i=start; i < SIZE; i++) { 177 sum += _measurements[i]; 178 } 179 return sum / _numMeasurements; 180 } 181 182 /** {@inheritDoc} */ 183 @Override 184 public void dispose() { 185 if (_meter != null) { 186 _updateTask.cancel(); 187 _meter.dispose(); 188 } 189 super.dispose(); 190 } 191 192 193 private class MyTimerTask extends TimerTask { 194 195 @Override 196 public void run() { 197 System.arraycopy(_measurements, 1, _measurements, 0, SIZE-1); 198 _measurements[SIZE-1] = _meter.getKnownAnalogValue(); 199 } 200 201 } 202 203 204 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultAverageMeter.class); 205 206}