class GenericTopo(NodeManager): """ Creates a generic topology (that is not tied to TOSSIM). This can be useful to generate and save different topologies that can be examined and/or loaded later without needing to integrate with TOSSIM. Since these are not real motes, the only TOSSIM Mote-like property they have is an ID. """ #TODO: support link model generation def __init__(self): self._nodes = [None] * TOSSIM_MAX_NODES self._links = {} self.model = BasicLinkModel() def getNode(self, i): n = self._nodes[i] if not n: n = GenericNode() extendMote(n, txmap=self.model.txmap) n.id = lambda: i # give it an ID self._nodes[i] = n return n def maxNodes(self): return TOSSIM_MAX_NODES def nodes(self): return filter(lambda n: n is not None, self._nodes) def gain(self, a, b): return self._links.get((a.id(), b.id())) def needsRebuild(self): raise NotImplementedError def rebuildModel(self): nodes = self.nodes() for i, a in enumerate(nodes): ai = a.id() for b in map(lambda x: nodes[x], range(i+1, len(nodes))): bi = b.id() (ga, gb) = self.model.gain(a, b) self._links[(ai, bi)] = ga self._links[(bi, ai)] = gb
class GenericTopo(NodeManager): """ Creates a generic topology (that is not tied to TOSSIM). This can be useful to generate and save different topologies that can be examined and/or loaded later without needing to integrate with TOSSIM. Since these are not real motes, the only TOSSIM Mote-like property they have is an ID. """ #TODO: support link model generation def __init__(self): self._nodes = [None] * TOSSIM_MAX_NODES self._links = {} self.model = BasicLinkModel() def getNode(self, i): n = self._nodes[i] if not n: n = GenericNode() extendMote(n, txmap=self.model.txmap) n.id = lambda: i # give it an ID self._nodes[i] = n return n def maxNodes(self): return TOSSIM_MAX_NODES def nodes(self): return filter(lambda n: n is not None, self._nodes) def gain(self, a, b): return self._links.get((a.id(), b.id())) def needsRebuild(self): raise NotImplementedError def rebuildModel(self): nodes = self.nodes() for i, a in enumerate(nodes): ai = a.id() for b in map(lambda x: nodes[x], range(i + 1, len(nodes))): bi = b.id() (ga, gb) = self.model.gain(a, b) self._links[(ai, bi)] = ga self._links[(bi, ai)] = gb
class _DynManager(_Manager): def __init__(self, *opts, **kws): _Manager.__init__(self, *opts, **kws) # of type TopoNode, index is ID self.model = BasicLinkModel() self.block_reenter = False self.dynamic = True def moteOnChange(self, mote): """ Invoked by a mote whenever an internal change occurs. """ if self.block_reenter: return # Rebuild txgain (should check if txgain is modified and # use flag) try: self.block_reenter = True self.rebuildLinks_Isolated(mote) finally: self.block_reenter = False _Manager.moteOnChange(self, mote) def getNode(self, i, **kws): return _Manager.getNode(self, i, txmap=self.model.txmap) def needsRebuild(self): """ Returns True iff at least one of the nodes is "dirty". """ return any(True for x in self.nodes() if x.dirty) def rebuildModel(self): """ Completely re-builds the radio-model. This should be called after a TX-power or position change or a change to the topology in general. **I have NO IDEA how and/or if this will work with the TOSSIM/T2 noise model. (For now I just ignore it.) """ nodes = self.nodes() for a in nodes: for b in a.neighbors: (gain_a, gain_b) = self.model.gain(a, b) a.add(b, gain_a) b.add(a, gain_b) for n in nodes: n.mark_clean() def rebuildLinks_Isolated(self, node, link_in=True): """ Rebuilds information for a single node. If link_in is True then neighbor links will be re-applied as well. (Not rebuilding neighbors is useful for a txgain change; the node positions are the same but the outward gain is reduced.) """ for other in node.neighbors: (gain_out, gain_in) = self.model.gain(node, other) node.add(other, gain_out) if link_in: other.add(node, gain_in) # TODO: This is broken, the node isn't necc. entirely clean node.mark_clean()