Allow replaying traffic from file

This commit is contained in:
Christos Falas 2025-01-27 14:56:44 +00:00
parent 659525cefb
commit 1c4bf3e340
No known key found for this signature in database
8 changed files with 91 additions and 25 deletions

View File

@ -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")

View File

@ -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
View 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

View 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
View 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()))

View File

@ -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:

View 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: ...

View File

@ -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))