001package jmri.jmrix.openlcb;
002
003import jmri.PowerManager;
004import jmri.managers.AbstractPowerManager;
005import jmri.jmrix.can.CanSystemConnectionMemo;
006
007import org.openlcb.EventID;
008import org.openlcb.OlcbInterface;
009import org.openlcb.implementations.BitProducerConsumer;
010import org.openlcb.implementations.EventTable;
011import org.openlcb.implementations.VersionedValueListener;
012
013/**
014 * Extend jmri.managers.AbstractPowerManager for OpenLCB controls.
015 *
016 * @author Bob Jacobsen Copyright (C) 2025
017 */
018public final class OlcbPowerManager extends AbstractPowerManager<CanSystemConnectionMemo> {
019
020    // The following are the Well Known power events defined by the Standard
021    OlcbAddress addrOn  = new OlcbAddress(new EventID("01.00.00.00.00.00.FF.FE"));
022    OlcbAddress addrOff = new OlcbAddress(new EventID("01.00.00.00.00.00.FF.FF"));
023
024    private final OlcbInterface iface;
025
026    VersionedValueListener<Boolean> powerListener;
027    BitProducerConsumer pc;
028    EventTable.EventTableEntryHolder onEventTableEntryHolder = null;
029    EventTable.EventTableEntryHolder offEventTableEntryHolder = null;
030    private static final int PC_DEFAULT_FLAGS = BitProducerConsumer.DEFAULT_FLAGS &
031            (~BitProducerConsumer.LISTEN_INVALID_STATE);
032
033    public OlcbPowerManager(CanSystemConnectionMemo memo) {
034        super(memo);
035        this.iface = memo.get(OlcbInterface.class);
036
037        int flags = PC_DEFAULT_FLAGS;
038        log.debug("Power Manager Flags: default {} overridden {} listen bit {}", PC_DEFAULT_FLAGS, flags,
039                    BitProducerConsumer.LISTEN_EVENT_IDENTIFIED);
040
041        pc = new BitProducerConsumer(iface, addrOn.toEventID(),
042                addrOff.toEventID(), flags);
043        powerListener = new VersionedValueListener<Boolean>(pc.getValue()) {
044            @Override
045            public void update(Boolean value) {
046                try {
047                    OlcbPowerManager.super.setPower(value ? PowerManager.ON : PowerManager.OFF);
048                } catch (jmri.JmriException e) {
049                    log.error("Unexpected exception", e);
050                }
051            }
052        };
053
054        onEventTableEntryHolder = iface.getEventTable().addEvent(addrOn.toEventID(), "PowerManager:on");
055        offEventTableEntryHolder = iface.getEventTable().addEvent(addrOff.toEventID(), "PowerManager:off");
056    }
057
058    
059    @Override
060    public void setPower(int s) {
061        if (s == PowerManager.ON) {
062            powerListener.setFromOwnerWithForceNotify(true);
063        } else if (s == PowerManager.OFF) {
064            powerListener.setFromOwnerWithForceNotify(false);
065        }
066        try {
067            super.setPower(s);
068        } catch (jmri.JmriException e) {
069            log.error("Unexpected exception", e);
070        }
071    }
072
073    @Override
074    public void dispose() {
075        if (powerListener != null) {
076            powerListener.release();
077            powerListener = null;
078        }
079        if (pc != null) {
080            pc.release();
081            pc = null;
082        }
083 
084        if (onEventTableEntryHolder != null) {
085            onEventTableEntryHolder.release();
086            onEventTableEntryHolder = null;
087        }
088        
089        if (offEventTableEntryHolder != null) {
090            offEventTableEntryHolder.release();
091            offEventTableEntryHolder = null;
092        }
093        
094   }
095
096    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(OlcbPowerManager.class);
097
098}