001package jmri.jmrix.can.cbus.node; 002 003import javax.annotation.Nonnull; 004import org.slf4j.Logger; 005import org.slf4j.LoggerFactory; 006 007/** 008 * Class to get Node Statistics. 009 * 010 * @author Steve Young Copyright (C) 2019 011 */ 012public class CbusNodeStats { 013 014 private final CbusBasicNodeWithManagers _node; 015 016 /** 017 * Create a new CbusNodeStats 018 * 019 * @param node Node to provide stats for 020 */ 021 public CbusNodeStats ( CbusBasicNodeWithManagers node ){ 022 _node = node; 023 } 024 025 /** 026 * Node Type Name, if available. 027 * @return If Node Parameters 1 and 3 are set eg. "CANPAN", else potentially a NAME OPC return, else empty string. 028 * 029 */ 030 @Nonnull 031 public String getNodeTypeName() { 032 if (!CbusNodeConstants.getModuleType(_node.getNodeParamManager().getParameter(1),_node.getNodeParamManager().getParameter(3)).isEmpty() ){ 033 return CbusNodeConstants.getModuleType(_node.getNodeParamManager().getParameter(1),_node.getNodeParamManager().getParameter(3)); 034 } 035 else if ( _node instanceof CbusNode ){ 036 return ((CbusNode)_node).getNodeNameFromName(); 037 } 038 else { 039 return ""; 040 } 041 } 042 043 /** 044 * Get Node Number and name 045 * @return string eg "1234 UserName", no trailing space. 046 */ 047 @Nonnull 048 public String getNodeNumberName() { 049 if ( !_node.getUserName().isEmpty() ){ 050 return "" + _node.getNodeNumber() + " " + _node.getUserName(); 051 } 052 else if ( !getNodeTypeName().isEmpty() ){ 053 return "" + _node.getNodeNumber() + " " + getNodeTypeName(); 054 } 055 else { 056 return String.valueOf(_node.getNodeNumber()); 057 } 058 } 059 060 /** 061 * Get the total number of bytes to store in a backup file 062 * 063 * @return total number, else 0 if still waiting for a total number of events 064 */ 065 public int totalNodeFileBytes(){ 066 return Math.max(0,_node.getNodeParamManager().getParameter(0)) + 067 Math.max(0,_node.getNodeNvManager().getNV(0)) + 068 Math.max(0,_node.getNodeParamManager().getParameter(5) * _node.getNodeEventManager().getTotalNodeEvents()); 069 } 070 071 /** 072 * Get the total bytes to transfer all data currently on module 073 * 074 * @return total number, else -1 if still waiting for a total number of events 075 */ 076 public int totalNodeBytes() { 077 if ( ( _node.getNodeParamManager().getParameter(0) < 0 ) 078 || ( _node.getNodeParamManager().getParameter(6) < 0 ) 079 || ( _node.getNodeParamManager().getParameter(5) < 0 ) 080 || ( _node.getNodeEventManager().getTotalNodeEvents() < 0 ) ){ 081 return -1; 082 } 083 return _node.getNodeParamManager().getParameter(0) + /* Total Parameters */ 084 _node.getNodeParamManager().getParameter(6) + /* Total NV's */ 085 ( _node.getNodeParamManager().getParameter(5) * _node.getNodeEventManager().getTotalNodeEvents() ) + /* Ev Variables for All Events */ 086 ( _node.getNodeEventManager().getTotalNodeEvents() ); /* Events from index return */ 087 } 088 089 /** 090 * Get the number of data bytes outstanding to fetch from a node 091 * 092 * @return total number, else -1 if still waiting for a total number of events 093 */ 094 public int totalRemainingNodeBytes(){ 095 if ( ( _node.getNodeParamManager().getOutstandingParams() < 0 ) 096 || ( _node.getNodeNvManager().getOutstandingNvCount() < 0 ) 097 || ( _node.getNodeEventManager().getOutstandingEvVars() < 0 ) 098 || ( _node.getNodeEventManager().getOutstandingIndexNodeEvents() < 0 ) ){ 099 return -1; 100 } 101 102 return _node.getNodeParamManager().getOutstandingParams() + /* Total Parameters */ 103 _node.getNodeNvManager().getOutstandingNvCount() + /* Total NV's */ 104 _node.getNodeEventManager().getOutstandingEvVars() + 105 ( _node.getNodeEventManager().getOutstandingIndexNodeEvents() ); /* Events from index return */ 106 107 } 108 109 /** 110 * Get the amount of Node data known to JMRI 111 * in terms of percentage of total data fetch done so far. 112 * 113 * @return float min 0 max 1 114 */ 115 public float floatPercentageRemaining(){ 116 float soFar = ( 1.0f * ( totalNodeBytes() - totalRemainingNodeBytes() ) ) / ( totalNodeBytes() ); 117 if ( soFar > 0 && soFar < 1.000001 ) { 118 return soFar; 119 } 120 return 0.0f; 121 } 122 123 /** 124 * Check if node has finished loading all available data 125 * 126 * The first time that all data is loaded, saves new backup. 127 * 128 */ 129 protected void checkNodeFinishedLoad(){ 130 if ((!_node.getNodeBackupManager().getBackupStarted()) && totalRemainingNodeBytes() == 0) { 131 if (!_node.getNodeBackupManager().doStore(true,hasLoadErrors()) ) { 132 log.error("Unable to save Finished Load to Node Backup File"); 133 } 134 _node.notifyPropertyChangeListener("BACKUPS", null, null); 135 } 136 // reset value if node comes online after being offline 137 if (_node.getNodeBackupManager().getBackupStarted() && totalRemainingNodeBytes()>0) { 138 _node.getNodeBackupManager().setBackupStarted(false); 139 } 140 } 141 142 // 8 timers, 8 errors ? 143 public boolean hasLoadErrors() { 144 return _node.getNodeTimerManager().numEvTimeoutCount + _node.getNodeTimerManager().paramRequestTimeoutCount + _node.getNodeTimerManager().allEvTimeoutCount > 0; 145 } 146 147 private static final Logger log = LoggerFactory.getLogger(CbusNodeStats.class); 148 149}