small cleanup for interface position hooks, updates to support using a provided altitude when sending emane events based on position hooks

This commit is contained in:
Blake Harnden 2020-03-19 16:40:43 -07:00
parent 102fa410fe
commit 3f17706c28
9 changed files with 76 additions and 61 deletions

View file

@ -705,7 +705,6 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
x = request.position.x x = request.position.x
y = request.position.y y = request.position.y
options.set_position(x, y) options.set_position(x, y)
lat, lon, alt = None, None, None
has_geo = request.HasField("geo") has_geo = request.HasField("geo")
if has_geo: if has_geo:
lat = request.geo.lat lat = request.geo.lat

View file

@ -369,8 +369,7 @@ class EmaneManager(ModelManager):
) )
emane_node.model.post_startup() emane_node.model.post_startup()
for netif in emane_node.netifs(): for netif in emane_node.netifs():
x, y, z = netif.node.position.get() netif.setposition()
emane_node.setnemposition(netif, x, y, z)
def reset(self) -> None: def reset(self) -> None:
""" """
@ -806,6 +805,7 @@ class EmaneManager(ModelManager):
# don"t use node.setposition(x,y,z) which generates an event # don"t use node.setposition(x,y,z) which generates an event
node.position.set(x, y, z) node.position.set(x, y, z)
node.position.set_geo(lon, lat, alt)
node_data = node.data(message_type=0, lat=lat, lon=lon, alt=alt) node_data = node.data(message_type=0, lat=lat, lon=lon, alt=alt)
self.session.broadcast_node(node_data) self.session.broadcast_node(node_data)
return True return True

View file

@ -4,7 +4,7 @@ share the same MAC+PHY model.
""" """
import logging import logging
from typing import TYPE_CHECKING, Dict, List, Optional, Type from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Type
from core.emulator.distributed import DistributedServer from core.emulator.distributed import DistributedServer
from core.emulator.enumerations import LinkTypes, NodeTypes, RegisterTlvs from core.emulator.enumerations import LinkTypes, NodeTypes, RegisterTlvs
@ -172,8 +172,7 @@ class EmaneNet(CoreNetworkBase):
# at this point we register location handlers for generating # at this point we register location handlers for generating
# EMANE location events # EMANE location events
netif.poshook = self.setnemposition netif.poshook = self.setnemposition
x, y, z = netif.node.position.get() netif.setposition()
self.setnemposition(netif, x, y, z)
def deinstallnetifs(self) -> None: def deinstallnetifs(self) -> None:
""" """
@ -186,28 +185,45 @@ class EmaneNet(CoreNetworkBase):
netif.shutdown() netif.shutdown()
netif.poshook = None netif.poshook = None
def setnemposition( def _nem_position(
self, netif: CoreInterface, x: float, y: float, z: float self, netif: CoreInterface
) -> None: ) -> Optional[Tuple[int, float, float, float]]:
""" """
Publish a NEM location change event using the EMANE event service. Creates nem position for emane event for a given interface.
:param netif: interface to get nem emane position for
:return: nem position tuple, None otherwise
""" """
if self.session.emane.service is None:
logging.info("position service not available")
return
nemid = self.getnemid(netif) nemid = self.getnemid(netif)
ifname = netif.localname ifname = netif.localname
if nemid is None: if nemid is None:
logging.info("nemid for %s is unknown", ifname) logging.info("nemid for %s is unknown", ifname)
return return
node = netif.node
x, y, z = node.getposition()
lat, lon, alt = self.session.location.getgeo(x, y, z) lat, lon, alt = self.session.location.getgeo(x, y, z)
event = LocationEvent() if node.position.alt is not None:
alt = node.position.alt
# altitude must be an integer or warning is printed # altitude must be an integer or warning is printed
# unused: yaw, pitch, roll, azimuth, elevation, velocity
alt = int(round(alt)) alt = int(round(alt))
event.append(nemid, latitude=lat, longitude=lon, altitude=alt) return nemid, lon, lat, alt
self.session.emane.service.publish(0, event)
def setnemposition(self, netif: CoreInterface) -> None:
"""
Publish a NEM location change event using the EMANE event service.
:param netif: interface to set nem position for
"""
if self.session.emane.service is None:
logging.info("position service not available")
return
position = self._nem_position(netif)
if position:
nemid, lon, lat, alt = position
event = LocationEvent()
event.append(nemid, latitude=lat, longitude=lon, altitude=alt)
self.session.emane.service.publish(0, event)
def setnempositions(self, moved_netifs: List[CoreInterface]) -> None: def setnempositions(self, moved_netifs: List[CoreInterface]) -> None:
""" """
@ -223,18 +239,9 @@ class EmaneNet(CoreNetworkBase):
return return
event = LocationEvent() event = LocationEvent()
i = 0
for netif in moved_netifs: for netif in moved_netifs:
nemid = self.getnemid(netif) position = self._nem_position(netif)
ifname = netif.localname if position:
if nemid is None: nemid, lon, lat, alt = position
logging.info("nemid for %s is unknown", ifname) event.append(nemid, latitude=lat, longitude=lon, altitude=alt)
continue
x, y, z = netif.node.getposition()
lat, lon, alt = self.session.location.getgeo(x, y, z)
# altitude must be an integer or warning is printed
alt = int(round(alt))
event.append(nemid, latitude=lat, longitude=lon, altitude=alt)
i += 1
self.session.emane.service.publish(0, event) self.session.emane.service.publish(0, event)

View file

@ -806,6 +806,7 @@ class Session:
using_lat_lon_alt = has_empty_position and has_lat_lon_alt using_lat_lon_alt = has_empty_position and has_lat_lon_alt
if using_lat_lon_alt: if using_lat_lon_alt:
x, y, _ = self.location.getxyz(lat, lon, alt) x, y, _ = self.location.getxyz(lat, lon, alt)
node.position.set_geo(lon, lat, alt)
# set position and broadcast # set position and broadcast
if None not in [x, y]: if None not in [x, y]:

View file

@ -370,20 +370,16 @@ class BasicRangeModel(WirelessModel):
with self._netifslock: with self._netifslock:
return self._netifs[netif] return self._netifs[netif]
def set_position( def set_position(self, netif: CoreInterface) -> None:
self, netif: CoreInterface, x: float = None, y: float = None, z: float = None
) -> None:
""" """
A node has moved; given an interface, a new (x,y,z) position has A node has moved; given an interface, a new (x,y,z) position has
been set; calculate the new distance between other nodes and link or been set; calculate the new distance between other nodes and link or
unlink node pairs based on the configured range. unlink node pairs based on the configured range.
:param netif: network interface to set position for :param netif: network interface to set position for
:param x: x position
:param y: y position
:param z: z position
:return: nothing :return: nothing
""" """
x, y, z = netif.node.position.get()
self._netifslock.acquire() self._netifslock.acquire()
self._netifs[netif] = (x, y, z) self._netifs[netif] = (x, y, z)
if x is None or y is None: if x is None or y is None:

View file

@ -422,7 +422,7 @@ class CoreNodeBase(NodeBase):
changed = super().setposition(x, y, z) changed = super().setposition(x, y, z)
if changed: if changed:
for netif in self.netifs(sort=True): for netif in self.netifs(sort=True):
netif.setposition(x, y, z) netif.setposition()
def commonnets( def commonnets(
self, obj: "CoreNodeBase", want_ctrl: bool = False self, obj: "CoreNodeBase", want_ctrl: bool = False
@ -1173,11 +1173,13 @@ class Position:
:param x: x position :param x: x position
:param y: y position :param y: y position
:param z: z position :param z: z position
:return:
""" """
self.x = x self.x = x
self.y = y self.y = y
self.z = z self.z = z
self.lon = None
self.lat = None
self.alt = None
def set(self, x: float = None, y: float = None, z: float = None) -> bool: def set(self, x: float = None, y: float = None, z: float = None) -> bool:
""" """
@ -1202,3 +1204,24 @@ class Position:
:return: x,y,z position tuple :return: x,y,z position tuple
""" """
return self.x, self.y, self.z return self.x, self.y, self.z
def set_geo(self, lon: float, lat: float, alt: float) -> None:
"""
Set geo position lon, lat, alt.
:param lon: longitude value
:param lat: latitude value
:param alt: altitude value
:return: nothing
"""
self.lon = lon
self.lat = lat
self.alt = alt
def get_geo(self) -> Tuple[float, float, float]:
"""
Retrieve current geo position lon, lat, alt.
:return: lon, lat, alt position tuple
"""
return self.lon, self.lat, self.alt

View file

@ -50,7 +50,7 @@ class CoreInterface:
self.addrlist = [] self.addrlist = []
self.hwaddr = None self.hwaddr = None
# placeholder position hook # placeholder position hook
self.poshook = lambda a, b, c, d: None self.poshook = lambda x: None
# used with EMANE # used with EMANE
self.transport_type = None self.transport_type = None
# node interface index # node interface index
@ -209,16 +209,14 @@ class CoreInterface:
self._params = getattr(self, name) self._params = getattr(self, name)
setattr(self, name, tmp) setattr(self, name, tmp)
def setposition(self, x: float, y: float, z: float) -> None: def setposition(self) -> None:
""" """
Dispatch position hook handler. Dispatch position hook handler when possible.
:param x: x position
:param y: y position
:param z: z position
:return: nothing :return: nothing
""" """
self.poshook(self, x, y, z) if self.poshook and self.node:
self.poshook(self)
def __lt__(self, other: "CoreInterface") -> bool: def __lt__(self, other: "CoreInterface") -> bool:
""" """

View file

@ -1079,11 +1079,7 @@ class WlanNode(CoreNetwork):
super().attach(netif) super().attach(netif)
if self.model: if self.model:
netif.poshook = self.model.position_callback netif.poshook = self.model.position_callback
if netif.node is None: netif.setposition()
return
x, y, z = netif.node.position.get()
# invokes any netif.poshook
netif.setposition(x, y, z)
def setmodel(self, model: "WirelessModelType", config: Dict[str, str]): def setmodel(self, model: "WirelessModelType", config: Dict[str, str]):
""" """
@ -1098,9 +1094,7 @@ class WlanNode(CoreNetwork):
self.model = model(session=self.session, _id=self.id) self.model = model(session=self.session, _id=self.id)
for netif in self.netifs(): for netif in self.netifs():
netif.poshook = self.model.position_callback netif.poshook = self.model.position_callback
if netif.poshook and netif.node: netif.setposition()
x, y, z = netif.node.position.get()
netif.poshook(netif, x, y, z)
self.updatemodel(config) self.updatemodel(config)
elif model.config_type == RegisterTlvs.MOBILITY.value: elif model.config_type == RegisterTlvs.MOBILITY.value:
self.mobility = model(session=self.session, _id=self.id) self.mobility = model(session=self.session, _id=self.id)
@ -1119,9 +1113,7 @@ class WlanNode(CoreNetwork):
) )
self.model.update_config(config) self.model.update_config(config)
for netif in self.netifs(): for netif in self.netifs():
if netif.poshook and netif.node: netif.setposition()
x, y, z = netif.node.position.get()
netif.poshook(netif, x, y, z)
def all_link_data(self, flags: int) -> List[LinkData]: def all_link_data(self, flags: int) -> List[LinkData]:
""" """

View file

@ -517,7 +517,7 @@ class Rj45Node(CoreNodeBase, CoreInterface):
if self.old_up: if self.old_up:
self.net_client.device_up(self.localname) self.net_client.device_up(self.localname)
def setposition(self, x: float = None, y: float = None, z: float = None) -> bool: def setposition(self, x: float = None, y: float = None, z: float = None) -> None:
""" """
Uses setposition from both parent classes. Uses setposition from both parent classes.
@ -526,9 +526,8 @@ class Rj45Node(CoreNodeBase, CoreInterface):
:param z: z position :param z: z position
:return: True if position changed, False otherwise :return: True if position changed, False otherwise
""" """
result = CoreNodeBase.setposition(self, x, y, z) CoreNodeBase.setposition(self, x, y, z)
CoreInterface.setposition(self, x, y, z) CoreInterface.setposition(self)
return result
def termcmdstring(self, sh: str) -> str: def termcmdstring(self, sh: str) -> str:
""" """