001/**
002 * MqttPowerManager.java
003 *
004 * PowerManager implementation for controlling layout power
005 *
006 * @author Dean Cording Copyright (C) 2023
007 *
008 */
009package jmri.jmrix.mqtt;
010
011import jmri.JmriException;
012import jmri.managers.AbstractPowerManager;
013
014import javax.annotation.Nonnull;
015
016public class MqttPowerManager extends AbstractPowerManager<MqttSystemConnectionMemo> implements MqttEventListener {
017
018    private static final String onText = "ON";
019    private static final String offText = "OFF";
020    private final MqttAdapter mqttAdapter;
021
022    public MqttPowerManager(MqttSystemConnectionMemo memo) {
023        super(memo);
024        mqttAdapter = memo.getMqttAdapter();
025
026    }
027
028    public void setSendTopic(@Nonnull String sendTopic) {
029        this.sendTopic = sendTopic;
030    }
031    public void setRcvTopic(@Nonnull String rcvTopic) {
032        this.mqttAdapter.unsubscribe(rcvTopic, this);
033        this.rcvTopic = rcvTopic;
034        this.mqttAdapter.subscribe(rcvTopic, this);
035
036        log.info("Subscribed to {}", rcvTopic);
037
038    }
039
040    @Nonnull
041    public String sendTopic = "track/power"; // for constructing topic; public for script access
042    @Nonnull
043    public String rcvTopic = "track/power"; // for constructing topic; public for script access
044
045    @Override
046    public boolean implementsIdle() {
047        return false;
048    }
049
050    @Override
051    public void setPower(int v) throws JmriException {
052        if (v == ON) {
053            // send TRACK_POWER_ON
054            sendMessage(onText);
055        } else if (v == OFF) {
056            // send TRACK_POWER_OFF
057            sendMessage(offText);
058        } else {
059            log.warn("Saw unknown power state : {}", v);
060        }
061    }
062
063
064
065    // to free resources when no longer used
066    @Override
067    public void dispose() throws JmriException {
068            this.mqttAdapter.unsubscribe(rcvTopic, this);
069    }
070
071
072     private void sendMessage(String c) {
073        jmri.util.ThreadingUtil.runOnLayoutEventually(() -> {
074            mqttAdapter.publish(this.sendTopic, c);
075        });
076        log.debug("sent {}", c);
077    }
078
079    @Override
080    public void notifyMqttMessage(String receivedTopic, String message) {
081        if (!receivedTopic.endsWith(rcvTopic)) {
082            log.error("Got a message whose topic ({}) wasn't for me ({})", receivedTopic, rcvTopic);
083            return;
084        }
085        log.debug("notifyMqttMessage with {}", message);
086
087        // handle on/off
088        try {
089            switch (message) {
090                case onText: super.setPower(ON); break;
091                case offText: super.setPower(OFF); break;
092                default: log.error("Invalid message to power manager: {}", message); break;
093            }
094        } catch (JmriException e) {
095            log.error("JMRI Exception", e);
096        }
097    }
098
099    // Initialize logging information
100    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(MqttPowerManager.class);
101
102}
103
104
105