diff --git a/bat2nodes.py b/bat2nodes.py index 921b548..ce6e596 100755 --- a/bat2nodes.py +++ b/bat2nodes.py @@ -4,6 +4,7 @@ import json import fileinput import argparse import os +import time from batman import batman from alfred import alfred @@ -43,7 +44,8 @@ args = parser.parse_args() options = vars(args) -db = NodeDB() +db = NodeDB(int(time.time())) + if options['mesh']: for mesh_interface in options['mesh']: bm = batman(mesh_interface) @@ -69,6 +71,13 @@ db.count_clients() if options['obscure']: db.obscure_clients() +db.load_state("state.json") + +# remove nodes that have been offline for more than 30 days +db.prune_offline(time.time() - 30*86400) + +db.dump_state("state.json") + scriptdir = os.path.dirname(os.path.realpath(__file__)) m = D3MapBuilder(db) diff --git a/node.py b/node.py index 0fe35fb..a75f982 100644 --- a/node.py +++ b/node.py @@ -12,6 +12,7 @@ class Node(): self.gps = None self.firmware = None self.clientcount = 0 + self.lastseen = 0 def add_mac(self, mac): mac = mac.lower() diff --git a/nodedb.py b/nodedb.py index fa9caed..973861d 100644 --- a/nodedb.py +++ b/nodedb.py @@ -5,7 +5,8 @@ from node import Node, Interface from link import Link, LinkConnector class NodeDB: - def __init__(self): + def __init__(self, time=0): + self.time = time self._nodes = [] self._links = [] @@ -18,6 +19,46 @@ class NodeDB: def get_nodes(self): return self._nodes + # remove all offlines nodes with lastseen < timestamp + def prune_offline(self, timestamp): + self._nodes = list(filter(lambda x: x.lastseen >= timestamp, self._nodes)) + + # write persistent state to file + def dump_state(self, filename): + obj = [] + + for node in self._nodes: + if node.flags['client']: + continue + + obj.append({ 'id': node.id + , 'name': node.name + , 'lastseen': node.lastseen + , 'geo': node.gps + }) + + with open(filename, "w") as f: + json.dump(obj, f) + + # load persistent state from file + def load_state(self, filename): + try: + with open(filename, "r") as f: + obj = json.load(f) + for n in obj: + try: + node = self.maybe_node_by_id(n['id']) + except: + node = Node() + node.id = n['id'] + node.name = n['name'] + node.lastseen = n['lastseen'] + node.gps = n['geo'] + self._nodes.append(node) + + except: + pass + def maybe_node_by_fuzzy_mac(self, mac): mac_a = mac.lower() @@ -51,6 +92,7 @@ class NodeDB: node = self.maybe_node_by_mac((x['of'], x['secondary'])) except: node = Node() + node.lastseen = self.time node.flags['online'] = True if 'legacy' in x: node.flags['legacy'] = True @@ -66,6 +108,7 @@ class NodeDB: node = self.maybe_node_by_mac((x['router'], )) except: node = Node() + node.lastseen = self.time node.flags['online'] = True if 'legacy' in x: node.flags['legacy'] = True @@ -95,6 +138,7 @@ class NodeDB: node = self.maybe_node_by_mac((x['neighbor'], )) except: node = Node() + node.lastseen = self.time node.flags['online'] = True if x['label'] == 'TT': node.flags['client'] = True