001package jmri.jmrix.loconet.logixng.swing; 002 003import java.awt.Frame; 004import java.awt.event.WindowAdapter; 005import java.awt.event.WindowEvent; 006import java.awt.event.ActionEvent; 007 008import javax.swing.BoxLayout; 009import javax.swing.*; 010 011import jmri.*; 012import jmri.jmrix.loconet.*; 013import jmri.util.ThreadingUtil; 014 015/** 016 * This dialog tests how many slots the command station has for engines. 017 * 018 * @author Daniel Bergqvist Copyright 2020 019 */ 020public class GetNumSlotsDialog extends JDialog implements ThrottleListener, SlotListener { 021 022 private static final int NUM_LOCO_TO_REQUEST = 119; 023 024 private final LocoNetSystemConnectionMemo _memo; 025 private JTextField _numEnginesField; 026 private JTextField _requestLocoField; 027 private JLabel _status; 028 private int _maxNumLocos = 0; 029 private boolean _freeSlots = false; 030 private final JTextField _textField; 031 private volatile boolean _abort = false; 032 033 034 public GetNumSlotsDialog(LocoNetSystemConnectionMemo memo, JTextField textField) { 035 super((Frame)null, true); 036 _memo = memo; 037 _textField = textField; 038 } 039 040 public void initComponents() { 041 setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 042 043 this.addWindowListener(new WindowAdapter() { 044 @Override 045 public void windowClosing(WindowEvent windowEvent) { 046 _abort = true; 047 releaseThrottles(); 048 } 049 }); 050 051 getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 052 053 JPanel numEnginesPanel = new JPanel(); 054 numEnginesPanel.add(new JLabel("Current number of engines: ")); 055 _numEnginesField = new JTextField("0"); 056 _numEnginesField.setColumns(5); 057 _numEnginesField.setEnabled(false); 058 numEnginesPanel.add(_numEnginesField); 059 060 JPanel requestLocoPanel = new JPanel(); 061 _requestLocoField = new JTextField("0"); 062 _requestLocoField.setColumns(5); 063 _requestLocoField.setEnabled(false); 064 JButton cancelRequestLocoField = new JButton(Bundle.getMessage("ButtonCancel")); 065 cancelRequestLocoField.addActionListener((ActionEvent e) -> { 066// new GetNumSlotsDialog().initComponents(); 067 }); 068 requestLocoPanel.add(new JLabel("Request loco: ")); 069 requestLocoPanel.add(_requestLocoField); 070 requestLocoPanel.add(cancelRequestLocoField); 071 072 getContentPane().add(numEnginesPanel); 073 getContentPane().add(requestLocoPanel); 074 075 _status = new JLabel("aaa"); 076 getContentPane().add(_status); 077 078 JButton buttonOK = new JButton(Bundle.getMessage("ButtonOK")); 079 buttonOK.addActionListener((ActionEvent e) -> { 080 _abort = true; 081 releaseThrottles(); 082 dispose(); 083 }); 084 getContentPane().add(buttonOK); 085 086 pack(); 087 setLocationRelativeTo(null); 088 089 _memo.getSlotManager().addSlotListener(this); 090 091 ThreadingUtil.runOnGUIEventually(() -> { 092 _freeSlots = true; 093 _memo.getSlotManager().update(); 094 }); 095 096 // Wait 10 seconds before starting to try request throttles 097 ThreadingUtil.runOnGUIDelayed(() -> { 098 _freeSlots = false; 099 requestThrottle(1); 100 },10000); 101 102 setVisible(true); 103 } 104 105 private void requestThrottle(int address) { 106// System.out.format("Request throttle: %d%n", address); 107 ThreadingUtil.runOnGUI(() -> { 108 _requestLocoField.setText(Integer.toString(address)); 109 }); 110// boolean result = InstanceManager.getDefault(ThrottleManager.class) 111 boolean result = _memo.getThrottleManager().requestThrottle(address, this); 112 if (!result && (address < NUM_LOCO_TO_REQUEST)) requestThrottle(address+1); 113 } 114 115 private void updateNumLocos() { 116// System.out.format("Update num locos%n"); 117 // _maxNumLocos 118 int numLocos = 0; 119 SlotManager slotManager = _memo.getSlotManager(); 120 for (int i=1; i <= 119; i++) { 121 LocoNetSlot slot = slotManager.slot(i); 122 if ((slot.slotStatus() & LnConstants.LOCOSTAT_MASK) != LnConstants.LOCO_FREE) { 123 numLocos++; 124 } 125 } 126 127 if (numLocos > _maxNumLocos) { 128 _maxNumLocos = numLocos; 129 ThreadingUtil.runOnGUI(() -> { 130 _numEnginesField.setText(Integer.toString(_maxNumLocos)); 131 _textField.setText(Integer.toString(_maxNumLocos)); 132 }); 133 } 134 } 135 136 private void releaseThrottles() { 137 for (int i=1; i < 120; i++) { 138 LocoNetSlot slot = _memo.getSlotManager().slot(i); 139 if ((slot.slotStatus() & LnConstants.LOCOSTAT_MASK) != LnConstants.LOCO_FREE) { 140 _memo.getLnTrafficController().sendLocoNetMessage(slot.writeStatus(LnConstants.LOCO_FREE)); 141// _memo.getLnTrafficController().sendLocoNetMessage(slot.releaseSlot()); 142 } 143 } 144 } 145 146 @Override 147 public void notifyThrottleFound(DccThrottle t) { 148// System.out.format("Throttle found: %d%n", t.getLocoAddress().getNumber()); 149 updateNumLocos(); 150 ThreadingUtil.runOnGUI(() -> { 151 _status.setText("Throttle was added"); 152 }); 153 if (!_abort && (t.getLocoAddress().getNumber() < NUM_LOCO_TO_REQUEST)) { 154 ThreadingUtil.runOnGUIDelayed(() -> { 155 requestThrottle(t.getLocoAddress().getNumber()+1); 156 }, 200); 157// ThreadingUtil.runOnGUIEventually(() -> { 158// requestThrottle(t.getLocoAddress().getNumber()+1); 159// }); 160 } 161 } 162 163 @Override 164 public void notifyFailedThrottleRequest(LocoAddress address, String reason) { 165// System.out.format("Throttle failed%n"); 166 ThreadingUtil.runOnGUI(() -> { 167 _status.setText(reason); 168 }); 169 if (!_abort && (address.getNumber() < NUM_LOCO_TO_REQUEST)) { 170 ThreadingUtil.runOnGUIDelayed(() -> { 171 requestThrottle(address.getNumber()+1); 172 }, 200); 173// ThreadingUtil.runOnGUIEventually(() -> { 174// requestThrottle(address.getNumber()+1); 175// }); 176 } 177 } 178 179 @Override 180 public void notifyDecisionRequired(LocoAddress address, DecisionType question) { 181// System.out.format("Decision required%n"); 182// throw new UnsupportedOperationException("Not supported."); 183 } 184 185 @Override 186 public void notifyChangedSlot(LocoNetSlot s) { 187// System.out.format("notifyChangedSlot: %d%n", s.getSlot()); 188 189 // Try to free slot 190 if (_freeSlots 191 && (s.getSlot() != 0) 192 && (s.slotStatus() != LnConstants.LOCO_FREE) 193 && (s.slotStatus() != LnConstants.LOCO_COMMON)) { 194// System.out.format("Send message: %s%n", s.releaseSlot().toMonitorString()); 195 _memo.getLnTrafficController().sendLocoNetMessage(s.releaseSlot()); 196 } 197 } 198 199}