001package jmri.jmrix.can.cbus.node; 002 003import javax.annotation.Nonnull; 004import jmri.jmrix.can.CanSystemConnectionMemo; 005import jmri.jmrix.can.cbus.CbusPreferences; 006 007// import org.slf4j.Logger; 008// import org.slf4j.LoggerFactory; 009 010/** 011 * Table data model for display of CBUS Nodes 012 * 013 * @author Steve Young (c) 2019 014 * 015 */ 016public class CbusBasicNodeTableFetch extends CbusBasicNodeTableOperations { 017 018 protected CbusNodeTrickleFetch trickleFetch; 019 020 public CbusBasicNodeTableFetch(@Nonnull CanSystemConnectionMemo memo, int row, int column) { 021 super(memo,row,column); 022 } 023 024 private int urgentNode = -1; 025 private int nodebefore = -1; 026 private int nodeafter = -1; 027 private boolean urgentActive=false; // feature active, set false for background fetch 028 029 /** 030 * Notify the table that the Node data fetch is more urgent 031 */ 032 public void startUrgentFetch() { 033 urgentActive = true; 034 startBackgroundFetch(); 035 } 036 037 /** 038 * Notify the table that the Node data fetch is more urgent 039 * @param nodeNum the Node to prioritise in the fetch 040 */ 041 protected void setUrgentNode( int nodeNum ){ 042 urgentNode = nodeNum; 043 urgentActive = true; 044 startBackgroundFetch(); 045 } 046 047 /** 048 * Fetch data in order of priority based on what user is currently viewing 049 * @param nodenum number of Node to prioritise in the fetch 050 * @param urgentNodeBefore number of the Node in main table row above 051 * @param urgentNodeAfter number of the Node in main table row below 052 */ 053 public void setUrgentFetch(int nodenum, int urgentNodeBefore, int urgentNodeAfter){ 054 urgentNode = nodenum; 055 nodebefore = urgentNodeBefore; 056 nodeafter = urgentNodeAfter; 057 urgentActive = true; 058 startBackgroundFetch(); 059 } 060 061 /** 062 * Request the table send the next urgent fetch 063 */ 064 public void triggerUrgentFetch(){ 065 if (urgentActive) { 066 sendNextBackgroundFetch(); 067 } 068 } 069 070 /** 071 * Starts background fetching for all table data as per user prefs 072 * Call whenever a node has been added to table or node edited 073 */ 074 public void startBackgroundFetch(){ 075 if (!(this instanceof CbusNodeTableDataModel)){ 076 return; 077 } 078 CbusPreferences pref = ((CbusNodeTableDataModel)this).preferences; 079 // reset if already running 080 if ( trickleFetch != null ){ 081 trickleFetch.dispose(); 082 } 083 trickleFetch = null; 084 if ( ( pref != null ) && (pref.getNodeBackgroundFetchDelay() > 0 ) ) { 085 trickleFetch = new CbusNodeTrickleFetch( _memo, this, pref.getNodeBackgroundFetchDelay() ); 086 } 087 } 088 089 private boolean hasActiveTimers(){ 090 for (int i = 0; i < getRowCount(); i++) { 091 // _mainArray.get(i).startLoadFromXml(); 092 _mainArray.get(i).getNodeBackupManager().doLoad(); 093 if ( _mainArray.get(i).getNodeTimerManager().hasActiveTimers() ){ 094 return true; 095 } 096 _mainArray.get(i).getNodeStats().checkNodeFinishedLoad(); 097 } 098 return false; 099 } 100 101 // prioritise command station 102 // get parameters 103 // get node variables 1-16 104 private boolean sentCommandStationFetch(){ 105 for (int i = 0; i < getRowCount(); i++) { 106 if ( _mainArray.get(i).getCsNum() > -1 ) { // is a command station 107 if ( sentOutstandingParam(_mainArray.get(i)) ) { // this param 108 return true; 109 } 110 if (( _mainArray.get(i).getNodeParamManager().getParameter(6) > 15 ) // If CS does has have more than 15 NV's 111 && ( _mainArray.get(i).getNodeNvManager().getNV(16) < 0 )) { 112 _mainArray.get(i).getNodeNvManager().sendNextNVToFetch(); 113 return true; 114 } 115 } 116 } 117 return false; 118 } 119 120 private boolean sentAnAllNodeParam(){ 121 // Get all node parameters fetched so basic node details ( type, num nv's etc. ) are known 122 for (int i = 0; i < getRowCount(); i++) { 123 if ( sentOutstandingParam(_mainArray.get(i)) ) { // this param 124 return true; 125 } 126 } 127 return false; 128 } 129 130 private boolean sentOutstandingNvs(CbusNode thisnode){ 131 if ( thisnode!=null && thisnode.getNodeNvManager().getOutstandingNvCount() > 0 ){ // this nv 132 thisnode.getNodeNvManager().sendNextNVToFetch(); 133 return true; 134 } 135 return false; 136 } 137 138 private boolean sentOutstandingEvs(CbusNode thisnode) { 139 if ( thisnode!=null && thisnode.getNodeEventManager().getOutstandingEvVars() > 0 ) { // this events 140 thisnode.getNodeEventManager().sendNextEvVarToFetch(); 141 return true; 142 } 143 return false; 144 } 145 146 private boolean sentOutstandingNvsOrEvs(CbusNode thisnode) { 147 return sentOutstandingNvs(thisnode) || sentOutstandingEvs(thisnode); 148 } 149 150 private boolean sentOutstandingParam(CbusNode thisnode) { 151 if ( thisnode!=null && thisnode.getNodeParamManager().getOutstandingParams() > 0 ) { // this params 152 thisnode.getNodeParamManager().sendRequestNextParam(); 153 return true; 154 } 155 return false; 156 } 157 158 private boolean sentUrgentFetches() { 159 160 // If a node is selected in the node manager the details for this are fetched next 161 CbusNode _urgentNode = getNodeByNodeNum(urgentNode); 162 CbusNode _beforeNode = getNodeByNodeNum(nodebefore); 163 CbusNode _afterNode = getNodeByNodeNum(nodeafter); 164 165 if (sentOutstandingNvsOrEvs(_urgentNode)) { 166 return true; 167 } 168 169 if ( sentOutstandingNvs(_afterNode) || sentOutstandingNvs(_beforeNode) ){ 170 return true; 171 } 172 173 if (sentOutstandingEvs(_afterNode) || sentOutstandingEvs(_beforeNode) ) { 174 return true; 175 } 176 177 // the node selected in table has been synched, 178 // along with the row above and below in case user scolls 179 urgentActive=false; 180 181 return false; 182 183 } 184 185 /** 186 * Send the next parameter request, ev var request or nv request. 187 * Triggered from either background or active fetch. 188 * Triggers loading the node backup xml file 189 * Triggers the check for node data fetch complete 190 * 191 * The order of the fetch changes depending on 192 * If node is a Command station 193 * If a node is currently selected in a node table pane 194 * The node above or below the currently selected row 195 * If event or nv tab is displayed in a node table pane 196 * 197 * Default order is Params 0,1,3,6,5,7,2, event total, 198 * remaining parameters, NVs, event index, event vars. 199 */ 200 protected void sendNextBackgroundFetch(){ 201 202 if ( getAnyNodeInLearnMode()>0 || hasActiveTimers()){ 203 return; 204 } 205 206 if (sentCommandStationFetch() || sentAnAllNodeParam()){ 207 return; 208 } 209 210 if (sentUrgentFetches()){ 211 return; 212 } 213 214 // default lookup routine for NV's then Events. 215 // parameters should already be known 216 for (int i = 0; i < getRowCount(); i++) { 217 if (sentOutstandingNvsOrEvs(_mainArray.get(i))){ 218 return; 219 } 220 } 221 222 // if all done dispose trickle fetch 223 if ( trickleFetch != null ) { 224 trickleFetch.dispose(); 225 } 226 trickleFetch = null; 227 } 228 229 // private final static Logger log = LoggerFactory.getLogger(CbusBasicNodeTableFetch.class); 230}