Allow replaying traffic from file
This commit is contained in:
parent
659525cefb
commit
1c4bf3e340
@ -6,13 +6,12 @@ import numpy.typing as npt
|
||||
import typer
|
||||
|
||||
from .. import visualise
|
||||
from ..collection import ingest
|
||||
from ..config import config
|
||||
from ..processing.aoa import AoA
|
||||
from ..processing.preprocess import Preprocessor
|
||||
from . import file
|
||||
from . import file, globals
|
||||
|
||||
app = typer.Typer()
|
||||
app = typer.Typer(callback=globals.main)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -27,6 +26,9 @@ def antennas() -> None:
|
||||
"""
|
||||
from ..utils import antenna_order
|
||||
|
||||
if not globals.is_live:
|
||||
raise ValueError("This command only works with live data")
|
||||
|
||||
antenna_order.main()
|
||||
|
||||
|
||||
@ -48,7 +50,8 @@ def heatmap() -> None:
|
||||
if not webapp_queue.full():
|
||||
webapp_queue.put(aoa)
|
||||
|
||||
ingest.start_processing(callback)
|
||||
globals.csi_producer(csi_callback=callback)
|
||||
logger.info("Finished processing CSI data")
|
||||
|
||||
|
||||
app.add_typer(file.app, name="file", help="Commands for working with CSI files")
|
||||
|
||||
@ -7,7 +7,8 @@ import numpy as np
|
||||
import numpy.typing as npt
|
||||
import typer
|
||||
|
||||
from ..collection import ingest
|
||||
from . import globals
|
||||
|
||||
|
||||
app = typer.Typer()
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -24,17 +25,4 @@ def capture(output_path: Path) -> None:
|
||||
logger.info(f"Got final CSI data with shape {antenna_data.shape}")
|
||||
file.create_dataset(datetime.now().isoformat(), data=antenna_data)
|
||||
|
||||
ingest.start_processing(callback)
|
||||
|
||||
|
||||
@app.command()
|
||||
def replay(input_path: Path) -> None:
|
||||
"""Replay CSI data from a file"""
|
||||
logger.info(f"Replaying data from {input_path}")
|
||||
|
||||
start_time = datetime.now()
|
||||
|
||||
with h5py.File(input_path, "r") as file:
|
||||
for key in file:
|
||||
logger.info(f"Sending data from {key}")
|
||||
ingest.send_data(file[key][:])
|
||||
globals.csi_producer(csi_callback=callback)
|
||||
|
||||
18
src/cli/globals.py
Normal file
18
src/cli/globals.py
Normal file
@ -0,0 +1,18 @@
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
|
||||
from .. import collection
|
||||
from ..collection import file, ingest
|
||||
|
||||
csi_producer: collection.CSIProducer = collection.noop
|
||||
is_live = True
|
||||
|
||||
|
||||
def main(from_file: Path | None = None) -> None:
|
||||
global csi_producer, is_live
|
||||
if from_file:
|
||||
csi_producer = partial(file.start_processing, file_path=from_file)
|
||||
is_live = False
|
||||
else:
|
||||
csi_producer = ingest.start_processing
|
||||
is_live = True
|
||||
9
src/collection/__init__.py
Normal file
9
src/collection/__init__.py
Normal file
@ -0,0 +1,9 @@
|
||||
from . import file, ingest
|
||||
from .protocols import CSICallback, CSIProducer
|
||||
|
||||
|
||||
def noop(csi_callback: CSICallback | None = None) -> None:
|
||||
del csi_callback
|
||||
|
||||
|
||||
__all__ = ["file", "ingest", "noop", "CSIProducer", "CSICallback"]
|
||||
39
src/collection/file.py
Normal file
39
src/collection/file.py
Normal file
@ -0,0 +1,39 @@
|
||||
import logging
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
|
||||
import h5py
|
||||
|
||||
from . import protocols
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def start_processing(
|
||||
file_path: Path,
|
||||
csi_callback: protocols.CSICallback | None = None,
|
||||
) -> None:
|
||||
logger.info(f"Replaying CSI data from {file_path}")
|
||||
with h5py.File(file_path, "r") as file:
|
||||
try:
|
||||
for key in file:
|
||||
datetime.fromisoformat(key)
|
||||
except ValueError as e:
|
||||
logger.exception(
|
||||
"The file provided was not generated using this software", e
|
||||
)
|
||||
|
||||
start_time = datetime.fromisoformat(list(file.keys())[0])
|
||||
target_offset = datetime.now() - start_time
|
||||
for key in file:
|
||||
logger.debug(f"Sending data from {key} at {datetime.now().isoformat()}")
|
||||
csi_callback(file[key][:])
|
||||
curr_time_virtual = datetime.fromisoformat(key)
|
||||
new_offset = datetime.now() - curr_time_virtual
|
||||
logger.debug(f"New offset {new_offset}, target is {target_offset}")
|
||||
if new_offset > target_offset + timedelta(seconds=1):
|
||||
logger.warning(
|
||||
f"Data is {new_offset - target_offset} behind, lagging behind..."
|
||||
)
|
||||
time.sleep(max(0, (target_offset - new_offset).total_seconds()))
|
||||
@ -9,13 +9,12 @@ from datetime import datetime
|
||||
from typing import Callable, NamedTuple
|
||||
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
|
||||
from ..config import config
|
||||
from .csi_frame import CSI
|
||||
from .protocols import CSICallback
|
||||
|
||||
Host = tuple[str, int]
|
||||
CSICallback = Callable[[npt.NDArray[np.complex128]], None]
|
||||
|
||||
|
||||
class FeitHost:
|
||||
|
||||
10
src/collection/protocols.py
Normal file
10
src/collection/protocols.py
Normal file
@ -0,0 +1,10 @@
|
||||
from typing import Callable, Protocol
|
||||
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
|
||||
CSICallback = Callable[[npt.NDArray[np.complex128]], None]
|
||||
|
||||
|
||||
class CSIProducer(Protocol):
|
||||
def __call__(self, csi_callback: CSICallback | None = None) -> None: ...
|
||||
@ -28,12 +28,12 @@ def callback(antenna_data: dict[ingest.Host, ingest.CSI]) -> None:
|
||||
)
|
||||
for host, csi in antenna_data.items():
|
||||
antenna_average[(host, 0)] = (
|
||||
antenna_average.get((host, 0), csi.header.rssi1) * 0.9
|
||||
+ csi.header.rssi1 * 0.1
|
||||
antenna_average.get((host, 0), csi.header.rssi1) * 0.99
|
||||
+ csi.header.rssi1 * 0.01
|
||||
)
|
||||
antenna_average[(host, 1)] = (
|
||||
antenna_average.get((host, 1), csi.header.rssi2) * 0.9
|
||||
+ csi.header.rssi2 * 0.1
|
||||
antenna_average.get((host, 1), csi.header.rssi2) * 0.99
|
||||
+ csi.header.rssi2 * 0.01
|
||||
)
|
||||
if csi.header.rssi1 > antenna_average[(host, 0)] + RSSI_THRESHOLD:
|
||||
unplugged.add((host, 0))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user