@@ -222,7 +222,7 @@ def showInfo(self, file=sys.stdout) -> str: # pylint: disable=W0613
222222 return infos
223223
224224 def showNodes (
225- self , includeSelf : bool = True
225+ self , includeSelf : bool = True , showFields : Optional [ List [ str ]] = None
226226 ) -> str : # pylint: disable=W0613
227227 """Show table summary of nodes in mesh"""
228228
@@ -246,6 +246,23 @@ def getTimeAgo(ts) -> Optional[str]:
246246 return None # not handling a timestamp from the future
247247 return _timeago (delta_secs )
248248
249+ def getNestedValue (node_dict : Dict [str , Any ], key_path : str ) -> Any :
250+ keys = key_path .split ("." )
251+ value = node_dict
252+ for key in keys :
253+ if isinstance (value , dict ):
254+ value = value .get (key )
255+ else :
256+ return None
257+ return value
258+
259+ if showFields is None or showFields .count == 0 :
260+ # The default set of fields to show (e.g., the status quo)
261+ showFields = ["N" , "User" , "ID" , "AKA" , "Hardware" , "Pubkey" , "Role" , "Latitude" , "Longitude" , "Altitude" , "Battery" , "Channel util." , "Tx air util." , "SNR" , "Hops" , "Channel" , "LastHeard" , "Since" ]
262+ else :
263+ # Always at least include the row number.
264+ showFields .insert (0 , "N" )
265+
249266 rows : List [Dict [str , Any ]] = []
250267 if self .nodesByNum :
251268 logging .debug (f"self.nodes:{ self .nodes } " )
@@ -287,11 +304,12 @@ def getTimeAgo(ts) -> Optional[str]:
287304 if metrics :
288305 batteryLevel = metrics .get ("batteryLevel" )
289306 if batteryLevel is not None :
290- if batteryLevel == 0 :
307+ if batteryLevel in ( 0 , 101 ): # Note: for boards without battery pin or PMU, 101% battery means 'the board is using external power'
291308 batteryString = "Powered"
292309 else :
293310 batteryString = str (batteryLevel ) + "%"
294311 row .update ({"Battery" : batteryString })
312+
295313 row .update (
296314 {
297315 "Channel util." : formatFloat (
@@ -313,7 +331,21 @@ def getTimeAgo(ts) -> Optional[str]:
313331 }
314332 )
315333
316- rows .append (row )
334+ # This allows the user to specify fields that wouldn't otherwise be included.
335+ extraFields = {}
336+ for field in showFields :
337+ if field in row :
338+ # We already have it, move along.
339+ continue
340+ elif "." in field :
341+ extraFields [field ] = getNestedValue (node , field )
342+ else :
343+ extraFields [field ] = node .get (field )
344+
345+ # Filter out any field in the data set that was not specified.
346+ filteredData = {key : value for key , value in row .items () if key in showFields }
347+ filteredData .update (extraFields )
348+ rows .append (filteredData )
317349
318350 rows .sort (key = lambda r : r .get ("LastHeard" ) or "0000" , reverse = True )
319351 for i , row in enumerate (rows ):
0 commit comments