001package jmri.jmrix.can.cbus; 002 003import jmri.Disposable; 004import jmri.JmriException; 005import jmri.jmrix.can.CanListener; 006import jmri.jmrix.can.CanMessage; 007import jmri.jmrix.can.CanReply; 008import jmri.jmrix.can.CanSystemConnectionMemo; 009import jmri.jmrix.can.TrafficController; 010import jmri.managers.AbstractPowerManager; 011 012/** 013 * PowerManager implementation for controlling CBUS layout power. 014 * 015 * @author Bob Jacobsen Copyright (C) 2001 016 * @author Andrew Crosland Copyright (C) 2009, 2021 017 */ 018public class CbusPowerManager extends AbstractPowerManager<CanSystemConnectionMemo> implements CanListener, Disposable { 019 020 private TrafficController tc; 021 022 public CbusPowerManager(CanSystemConnectionMemo memo) { 023 super(memo); 024 // connect to the TrafficManager 025 tc = memo.getTrafficController(); 026 addTc(tc); 027 } 028 029 @Override 030 public void setPower(int v) throws JmriException { 031 int old = power; 032 power = UNKNOWN; // while waiting for reply 033 checkTC(); 034 if (v == ON) { 035 // send "Enable main track" 036 tc.sendCanMessage(CbusMessage.getRequestTrackOn(tc.getCanid()), this); 037 } else if (v == OFF) { 038 // send "Kill main track" 039 tc.sendCanMessage(CbusMessage.getRequestTrackOff(tc.getCanid()), this); 040 } 041 firePowerPropertyChange(old, power); 042 } 043 044 /** 045 * Notification to JMRI of main track power state. Does not send to Layout. 046 * Only used to bypass having the PowerManager respond to messages from the 047 * command station because I don't know why the PowerManager should not do 048 * the job the PowerManager API was created to do in the CBus package. 049 * 050 * @param newPower New Power Status 051 */ 052 public void updatePower(int newPower) { 053 int oldPower = power; 054 if (oldPower != newPower) { 055 power = newPower; 056 firePowerPropertyChange(oldPower, power); 057 } 058 } 059 060 /** 061 * {@inheritDoc} 062 */ 063 @Override 064 public void dispose() { 065 removeTc(tc); 066 tc = null; 067 } 068 069 private void checkTC() throws JmriException { 070 if (tc == null) { 071 throw new JmriException("attempt to use CbusPowerManager after dispose"); 072 } 073 } 074 075 // to listen for status changes from Cbus system 076 @Override 077 public void reply(CanReply m) { 078 if (m.extendedOrRtr()) { 079 return; 080 } 081 int old = power; 082 if (CbusMessage.isTrackOff(m)) { 083 power = OFF; 084 } else if (CbusMessage.isTrackOn(m)) { 085 power = ON; 086 } else if (CbusMessage.isArst(m)) { 087 // Some CBUS command stations (e.g. CANCMD) will turn on the track 088 // power at start up, before sending ARST (System reset). Others, 089 // e.g., SPROG CBUS hardware can selectively turn on the track power 090 // so we selectively check for ARST here, based on connection settings. 091 if (memo.powerOnArst()) { 092 power = ON; 093 } 094 } 095 firePowerPropertyChange(old, power); 096 } 097 098 /** 099 * Does not listen to outgoing messages. {@inheritDoc} 100 */ 101 @Override 102 public void message(CanMessage m) { 103 // do nothing 104 } 105 106}