001package jmri.jmrix.roco.z21;
002
003import jmri.*;
004import jmri.implementation.DefaultMeter;
005import jmri.implementation.MeterUpdateTask;
006
007/**
008 * Provide access to voltage and current readings from the Roco Z21 
009 *
010 * @author Mark Underwood    Copyright (C) 2015
011 * @author Paul Bender       Copyright (C) 2017
012 * @author Daniel Bergqvist  Copyright (C) 2020
013 */
014public class Z21PredefinedMeters {
015
016    private Z21TrafficController tc;
017    private Z21SystemConnectionMemo _memo;
018    private final MeterUpdateTask updateTask;
019    private final Meter currentMeter;
020    private final Meter voltageMeter;
021    private boolean enabled = false;  // disable by default; prevent polling when not being used.
022
023    public Z21PredefinedMeters(Z21SystemConnectionMemo memo) {
024        
025        _memo = memo;
026        tc = _memo.getTrafficController();
027        
028        updateTask = new UpdateTask(-1);
029        
030        currentMeter = new DefaultMeter.DefaultCurrentMeter(
031                memo.getSystemPrefix() + "V" + "CommandStationCurrent",
032                Meter.Unit.Milli, 0, 10000.0, 100, updateTask);
033        
034        voltageMeter = new DefaultMeter.DefaultVoltageMeter(
035                memo.getSystemPrefix() + "V" + "CommandStationVoltage",
036                Meter.Unit.Milli, 0, 50000.0, 500, updateTask);
037        
038        InstanceManager.getDefault(MeterManager.class).register(currentMeter);
039        InstanceManager.getDefault(MeterManager.class).register(voltageMeter);
040        
041        log.debug("Z21MultiMeter constructor called");
042
043    }
044
045    public void setZ21TrafficController(Z21TrafficController controller) {
046        tc = controller;
047    }
048
049    public void dispose() {
050        updateTask.disable(currentMeter);
051        updateTask.disable(voltageMeter);
052        InstanceManager.getDefault(MeterManager.class).deregister(currentMeter);
053        InstanceManager.getDefault(MeterManager.class).deregister(voltageMeter);
054        updateTask.dispose(currentMeter);
055        updateTask.dispose(voltageMeter);
056    }
057
058
059    private class UpdateTask extends MeterUpdateTask implements Z21Listener {
060    
061        public UpdateTask(int interval) {
062            super(interval);
063            tc.addz21Listener(this);
064        }
065    
066        @Override 
067        public void enable(){
068            enabled = true;
069            RocoZ21CommandStation cs = _memo.getRocoZ21CommandStation();
070            cs.setSystemStatusMessagesFlag(true);
071            tc.sendz21Message(Z21Message.getLanSetBroadcastFlagsRequestMessage(cs.getZ21BroadcastFlags()),this);
072            super.enable();
073        }
074
075        @Override 
076        public void disable(){
077            if (!enabled) return;
078            super.disable();
079            enabled = false;
080            RocoZ21CommandStation cs = _memo.getRocoZ21CommandStation();
081            cs.setSystemStatusMessagesFlag(false);
082            tc.sendz21Message(Z21Message.getLanSetBroadcastFlagsRequestMessage(cs.getZ21BroadcastFlags()),this);
083        }
084        
085        @Override
086        public void message(Z21Message m) {
087        }
088
089        @Override
090        public void reply(Z21Reply r) {
091            log.debug("Z21MultiMeter received reply: {}", r.toString());
092            if (r.isSystemDataChangedReply()) {
093                try {
094                    setCurrent(r.getSystemDataMainCurrent() * 1.0f);
095                    setVoltage(r.getSystemDataVCCVoltage() * 1.0f);
096                } catch (JmriException e) {
097                    log.error("exception thrown by setCurrent or setVoltage", e);
098                }
099            }
100        }
101
102        private void setCurrent(double value) throws JmriException {
103            currentMeter.setCommandedAnalogValue(value);
104        }
105
106        private void setVoltage(double value) throws JmriException {
107            voltageMeter.setCommandedAnalogValue(value);
108        }
109
110        @Override
111        public void requestUpdateFromLayout() {
112            if( enabled ) {
113                tc.sendz21Message(Z21Message.getLanSystemStateDataChangedRequestMessage(), this);
114            }
115        }
116    }
117    
118    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Z21PredefinedMeters.class);
119
120}