grpc: implemened initial support for streaming emane pathloss events
This commit is contained in:
parent
7048aa7867
commit
3b0ca1638c
6 changed files with 85 additions and 3 deletions
|
@ -31,6 +31,8 @@ from core.api.grpc.emane_pb2 import (
|
||||||
EmaneLinkRequest,
|
EmaneLinkRequest,
|
||||||
EmaneLinkResponse,
|
EmaneLinkResponse,
|
||||||
EmaneModelConfig,
|
EmaneModelConfig,
|
||||||
|
EmanePathlossesRequest,
|
||||||
|
EmanePathlossesResponse,
|
||||||
GetEmaneConfigRequest,
|
GetEmaneConfigRequest,
|
||||||
GetEmaneConfigResponse,
|
GetEmaneConfigResponse,
|
||||||
GetEmaneEventChannelRequest,
|
GetEmaneEventChannelRequest,
|
||||||
|
@ -1229,6 +1231,17 @@ class CoreGrpcClient:
|
||||||
)
|
)
|
||||||
return self.stub.WlanLink(request)
|
return self.stub.WlanLink(request)
|
||||||
|
|
||||||
|
def emane_pathlosses(
|
||||||
|
self, pathloss_iter: Iterable[EmanePathlossesRequest]
|
||||||
|
) -> EmanePathlossesResponse:
|
||||||
|
"""
|
||||||
|
Stream EMANE pathloss events.
|
||||||
|
|
||||||
|
:param pathloss_iter: iterator for sending EMANE pathloss events
|
||||||
|
:return: EMANE pathloss response
|
||||||
|
"""
|
||||||
|
return self.stub.EmanePathlosses(pathloss_iter)
|
||||||
|
|
||||||
def connect(self) -> None:
|
def connect(self) -> None:
|
||||||
"""
|
"""
|
||||||
Open connection to server, must be closed manually.
|
Open connection to server, must be closed manually.
|
||||||
|
|
|
@ -2,7 +2,9 @@ import logging
|
||||||
import time
|
import time
|
||||||
from typing import Any, Dict, List, Tuple, Type
|
from typing import Any, Dict, List, Tuple, Type
|
||||||
|
|
||||||
|
import grpc
|
||||||
import netaddr
|
import netaddr
|
||||||
|
from grpc import ServicerContext
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
from core.api.grpc import common_pb2, core_pb2
|
from core.api.grpc import common_pb2, core_pb2
|
||||||
|
@ -13,7 +15,7 @@ from core.emulator.data import LinkData
|
||||||
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
|
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
|
||||||
from core.emulator.enumerations import LinkTypes, NodeTypes
|
from core.emulator.enumerations import LinkTypes, NodeTypes
|
||||||
from core.emulator.session import Session
|
from core.emulator.session import Session
|
||||||
from core.nodes.base import NodeBase
|
from core.nodes.base import CoreNode, NodeBase
|
||||||
from core.nodes.interface import CoreInterface
|
from core.nodes.interface import CoreInterface
|
||||||
from core.services.coreservices import CoreService
|
from core.services.coreservices import CoreService
|
||||||
|
|
||||||
|
@ -478,3 +480,23 @@ def interface_to_proto(interface: CoreInterface) -> core_pb2.Interface:
|
||||||
ip6=ip6,
|
ip6=ip6,
|
||||||
ip6mask=ip6mask,
|
ip6mask=ip6mask,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_nem_id(node: CoreNode, netif_id: int, context: ServicerContext) -> int:
|
||||||
|
"""
|
||||||
|
Get nem id for a given node and interface id.
|
||||||
|
|
||||||
|
:param node: node to get nem id for
|
||||||
|
:param netif_id: id of interface on node to get nem id for
|
||||||
|
:param context: request context
|
||||||
|
:return: nem id
|
||||||
|
"""
|
||||||
|
netif = node.netif(netif_id)
|
||||||
|
if not netif:
|
||||||
|
message = f"{node.name} missing interface {netif_id}"
|
||||||
|
context.abort(grpc.StatusCode.NOT_FOUND, message)
|
||||||
|
net = netif.net
|
||||||
|
if not isinstance(net, EmaneNet):
|
||||||
|
message = f"{node.name} interface {netif_id} is not an EMANE network"
|
||||||
|
context.abort(grpc.StatusCode.INVALID_ARGUMENT, message)
|
||||||
|
return net.getnemid(netif)
|
||||||
|
|
|
@ -6,7 +6,7 @@ import tempfile
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from concurrent import futures
|
from concurrent import futures
|
||||||
from typing import Type
|
from typing import Iterable, Type
|
||||||
|
|
||||||
import grpc
|
import grpc
|
||||||
from grpc import ServicerContext
|
from grpc import ServicerContext
|
||||||
|
@ -39,6 +39,8 @@ from core.api.grpc.core_pb2 import ExecuteScriptResponse
|
||||||
from core.api.grpc.emane_pb2 import (
|
from core.api.grpc.emane_pb2 import (
|
||||||
EmaneLinkRequest,
|
EmaneLinkRequest,
|
||||||
EmaneLinkResponse,
|
EmaneLinkResponse,
|
||||||
|
EmanePathlossesRequest,
|
||||||
|
EmanePathlossesResponse,
|
||||||
GetEmaneConfigRequest,
|
GetEmaneConfigRequest,
|
||||||
GetEmaneConfigResponse,
|
GetEmaneConfigResponse,
|
||||||
GetEmaneEventChannelRequest,
|
GetEmaneEventChannelRequest,
|
||||||
|
@ -1751,3 +1753,17 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
wlan.model.sendlinkmsg(n1_netif, n2_netif, unlink=not request.linked)
|
wlan.model.sendlinkmsg(n1_netif, n2_netif, unlink=not request.linked)
|
||||||
result = True
|
result = True
|
||||||
return WlanLinkResponse(result=result)
|
return WlanLinkResponse(result=result)
|
||||||
|
|
||||||
|
def EmanePathlosses(
|
||||||
|
self,
|
||||||
|
request_iterator: Iterable[EmanePathlossesRequest],
|
||||||
|
context: ServicerContext,
|
||||||
|
) -> EmanePathlossesResponse:
|
||||||
|
for request in request_iterator:
|
||||||
|
session = self.get_session(request.session_id, context)
|
||||||
|
n1 = self.get_node(session, request.node_one, context, CoreNode)
|
||||||
|
nem1 = grpcutils.get_nem_id(n1, request.interface_one_id, context)
|
||||||
|
n2 = self.get_node(session, request.node_two, context, CoreNode)
|
||||||
|
nem2 = grpcutils.get_nem_id(n2, request.interface_two_id, context)
|
||||||
|
session.emane.publish_pathloss(nem1, nem2, request.rx_one, request.rx_two)
|
||||||
|
return EmanePathlossesResponse()
|
||||||
|
|
|
@ -37,7 +37,7 @@ if TYPE_CHECKING:
|
||||||
from core.emulator.session import Session
|
from core.emulator.session import Session
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from emane.events import EventService
|
from emane.events import EventService, PathlossEvent
|
||||||
from emane.events import LocationEvent
|
from emane.events import LocationEvent
|
||||||
from emane.events.eventserviceexception import EventServiceException
|
from emane.events.eventserviceexception import EventServiceException
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -48,6 +48,7 @@ except ImportError:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
EventService = None
|
EventService = None
|
||||||
LocationEvent = None
|
LocationEvent = None
|
||||||
|
PathlossEvent = None
|
||||||
EventServiceException = None
|
EventServiceException = None
|
||||||
logging.debug("compatible emane python bindings not installed")
|
logging.debug("compatible emane python bindings not installed")
|
||||||
|
|
||||||
|
@ -868,6 +869,21 @@ class EmaneManager(ModelManager):
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def publish_pathloss(self, nem1: int, nem2: int, rx1: float, rx2: float) -> None:
|
||||||
|
"""
|
||||||
|
Publish pathloss events between provided nems, using provided rx power.
|
||||||
|
:param nem1: interface one for pathloss
|
||||||
|
:param nem2: interface two for pathloss
|
||||||
|
:param rx1: received power from nem2 to nem1
|
||||||
|
:param rx2: received power from nem1 to nem2
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
event = PathlossEvent()
|
||||||
|
event.append(nem1, forward=rx1)
|
||||||
|
event.append(nem2, forward=rx2)
|
||||||
|
self.service.publish(nem1, event)
|
||||||
|
self.service.publish(nem2, event)
|
||||||
|
|
||||||
|
|
||||||
class EmaneGlobalModel:
|
class EmaneGlobalModel:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -149,6 +149,8 @@ service CoreApi {
|
||||||
}
|
}
|
||||||
rpc GetEmaneEventChannel (emane.GetEmaneEventChannelRequest) returns (emane.GetEmaneEventChannelResponse) {
|
rpc GetEmaneEventChannel (emane.GetEmaneEventChannelRequest) returns (emane.GetEmaneEventChannelResponse) {
|
||||||
}
|
}
|
||||||
|
rpc EmanePathlosses (stream emane.EmanePathlossesRequest) returns (emane.EmanePathlossesResponse) {
|
||||||
|
}
|
||||||
|
|
||||||
// xml rpc
|
// xml rpc
|
||||||
rpc SaveXml (SaveXmlRequest) returns (SaveXmlResponse) {
|
rpc SaveXml (SaveXmlRequest) returns (SaveXmlResponse) {
|
||||||
|
|
|
@ -90,3 +90,16 @@ message EmaneModelConfig {
|
||||||
string model = 3;
|
string model = 3;
|
||||||
map<string, string> config = 4;
|
map<string, string> config = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message EmanePathlossesRequest {
|
||||||
|
int32 session_id = 1;
|
||||||
|
int32 node_one = 2;
|
||||||
|
float rx_one = 3;
|
||||||
|
int32 interface_one_id = 4;
|
||||||
|
int32 node_two = 5;
|
||||||
|
float rx_two = 6;
|
||||||
|
int32 interface_two_id = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EmanePathlossesResponse {
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue