Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/publish cell prb from NG-Scope #28

Merged
merged 2 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 51 additions & 15 deletions scripts/api_test_device_publisher.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,41 @@
#!/usr/bin/env python3

import argparse
from flask import Flask, jsonify

CELL_DATA_A = {
"cid": None,
"enodeB": 100344,
"pci": 62,
"type": "LTE",
"arfcn": 3350,
"band": "7",
"rssi": 110.7,
"rsrp": 90.7,
"rsrq": 11.3,
}
CELL_DATA_B = {
"cid": None,
"enodeB": 105059,
"pci": 5,
"type": "LTE",
"arfcn": 500,
"band": "1",
"rssi": 110.7,
"rsrp": 90.7,
"rsrq": 11.3,
}
DEFAULT_CELL_DATA_CHOICES = {
"A": CELL_DATA_A,
"B": CELL_DATA_B,
}

def default_cell_data() -> str:
return list(DEFAULT_CELL_DATA_CHOICES.keys())[0]

app = Flask(__name__)
cell_data = []

# Predefined response
cell_data = [
{
"cid": None,
"enodeB": 100344,
"pci": 62,
"type": "LTE",
"arfcn": 3350,
"band": "7",
"rssi": 110.7,
"rsrp": 90.7,
"rsrq": 11.3,
},
]

@app.route('/api/v1/celldata')
def get_cell_data_all():
Expand All @@ -27,5 +45,23 @@ def get_cell_data_all():
def get_cell_data_connected_all():
return jsonify(cell_data)

if __name__ == '__main__':

def parse_application_args():
parser = argparse.ArgumentParser(description='Test API to simulate DevicePublisher.')
parser.add_argument('--cell-data',
type=str,
choices=list(DEFAULT_CELL_DATA_CHOICES.keys()),
default=default_cell_data(),
help=f'Column to visualize (default: {default_cell_data()})')
return parser.parse_args()

def main():
args = parse_application_args()

global cell_data
cell_data = [ DEFAULT_CELL_DATA_CHOICES[args.cell_data] ]

app.run(debug=True, port=7353)

if __name__ == '__main__':
main()
23 changes: 0 additions & 23 deletions src/cell_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ pub struct SingleCell {
pub cell_id: u64,
pub cell_type: CellularType,
/// Number of PRB per slot
pub nof_prb: u16,
pub frequency: u64,
pub rssi: f64,
pub rsrp: f64,
Expand Down Expand Up @@ -313,7 +312,6 @@ impl CellInfo {
let mut single_cell: SingleCell = SingleCell {
cell_id: 0,
cell_type: CellularType::LTE,
nof_prb: 100,
frequency: 0,
rssi: 0.0,
rsrp: 0.0,
Expand All @@ -329,7 +327,6 @@ impl CellInfo {
single_cell.rssi = cgi_response_extract_rssi(response_value)?;
single_cell.rsrq = cgi_response_extract_rsrp(response_value)?;
single_cell.rsrp = cgi_response_extract_rsrq(response_value)?;
single_cell.nof_prb = prb_from_cell_id(single_cell.cell_id);
// TODO: Evaluate: Add estimated bandwidth?
Ok(CellInfo {
cells: [single_cell].to_vec(),
Expand All @@ -343,40 +340,20 @@ impl CellInfo {
cell_id: cell.safe_id(),
cell_type: CellularType::from_str(&cell.r#type)?,
frequency: 0,
nof_prb: 100,
rssi: cell.rssi,
rsrp: cell.rsrp,
rsrq: cell.rsrq,
dl_est: cell.estimatedDownBandwidth,
ul_est: cell.estimatedUpBandwidth,
};
single_cell.frequency = arfcn_to_frequency(cell.arfcn, &single_cell.cell_type)?;
single_cell.nof_prb = prb_from_cell_id(single_cell.cell_id);
cell_info.cells.push(single_cell);
}

Ok(cell_info)
}
}

// Quick fix for setting the nof PRB.
fn prb_from_cell_id(cell_id: u64) -> u16 {
match cell_id {
/* O2 */
21 => 50,
41 => 100,
51 => 100,
61 => 100,
63 => 100,
/* Telekom */
6 => 50,
11 => 50, // LTE 800 DD (EARFCN 6500)
7 => 100,
8 => 100,
_ => 100,
}
}

/* --------------------------- */
/* Milesight cgi helpers */
/* --------------------------- */
Expand Down
96 changes: 68 additions & 28 deletions src/logic/downloader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub const DOWNLOADING_IDLE_SLEEP_TIME_MS: u64 = 20;
pub const RECOVERY_SLEEP_TIME_MS: u64 = 2_000;
pub const BETWEEN_DOWNLOADS_SLEEP_TIME_MS: u64 = 1_000;
pub const RESTART_TIMEOUT_US: u64 = 2_000_000;
pub const POST_DOWNLOAD_TIME_US: u64 = 2_000_000;

pub const TCP_STREAM_READ_BUFFER_SIZE: usize = 100_000;

Expand All @@ -40,6 +41,7 @@ pub struct DownloadStreamState {
pub rnti_share_type: u8,
pub last_rtt_us: Option<u64>,
pub start_timestamp_us: u64,
pub finish_timestamp_us: Option<u64>,
pub timedata: HashMap<u64, TcpLogStats>,
pub dci_total_dl_bit: u64,
pub dci_rnti_dl_bit: u64,
Expand Down Expand Up @@ -229,6 +231,9 @@ fn run(run_args: &mut RunArgs) -> Result<()> {
Box::new(DownloaderState::StartDownload),
)
}
DownloaderState::PostDownload => {
handle_post_download(&mut current_download)
}
}
}

Expand Down Expand Up @@ -262,19 +267,27 @@ fn unpack_all_dci_messages(
downloader_state: &DownloaderState,
rnti_option: Option<u16>
) -> Result<()> {

loop {
match rx_dci.try_recv() {
Ok(dci) => {
if DownloaderState::Downloading == *downloader_state &&
dci.ngscope_dci.time_stamp >= download_stream_state.start_timestamp_us {
download_stream_state.add_ngscope_dci(dci.ngscope_dci, rnti_option);
while let Ok(dci) = rx_dci.try_recv() {
if let DownloaderState::Downloading | DownloaderState::PostDownload = downloader_state {
if let MessageDci::CellDci(ngscope_dci) = dci {
if ngscope_dci.time_stamp >= download_stream_state.start_timestamp_us {
if let Some(finish_timestamp_us) = download_stream_state.finish_timestamp_us {
if ngscope_dci.time_stamp > finish_timestamp_us {
continue;
} else {
print_debug("DEBUG [download] Collecting DCI in PostDownload state!!!");
}
}
download_stream_state.add_ngscope_dci(*ngscope_dci, rnti_option);
}
}
Err(TryRecvError::Empty) => break,
Err(TryRecvError::Disconnected) => return Err(anyhow!("[download] error: rx_dci disconnected"))
};
}
}

if let Err(TryRecvError::Disconnected) = rx_dci.try_recv() {
return Err(anyhow!("[download] error: rx_dci disconnected"));
}

Ok(())
}

Expand Down Expand Up @@ -326,6 +339,7 @@ fn handle_downloading(params: DownloadingParameters) -> DownloaderState {
rnti_share_type,
last_rtt_us,
start_timestamp_us,
finish_timestamp_us,
timedata,
dci_total_dl_bit,
dci_rnti_dl_bit,
Expand All @@ -340,26 +354,11 @@ fn handle_downloading(params: DownloadingParameters) -> DownloaderState {
Ok(chunk_size) => {
if chunk_size == 0 {
// End of stream
let download_finish_timestamp_us = chrono::Local::now().timestamp_micros() as u64;
let total_download_bytes = determine_average_download_bytes(timedata);
let average_rtt_us = determine_average_rtt_us(timedata);
DownloaderState::FinishDownload(DownloadFinishParameters {
base_addr: base_addr.to_string(),
path: path.to_string(),
start_timestamp_us: *start_timestamp_us,
finish_timestamp_us: download_finish_timestamp_us,
average_rtt_us,
total_download_bytes,
dci_total_dl_bit: *dci_total_dl_bit,
dci_total_dl_prb_with_tbs: *dci_total_dl_prb_with_tbs,
dci_total_dl_prb_no_tbs: *dci_total_dl_prb_no_tbs,
dci_rnti_dl_bit: *dci_rnti_dl_bit,
dci_rnti_dl_prb_with_tbs: *dci_rnti_dl_prb_with_tbs,
dci_rnti_dl_prb_no_tbs: *dci_rnti_dl_prb_no_tbs,
})
*finish_timestamp_us = Some(chrono::Local::now().timestamp_micros() as u64);
DownloaderState::PostDownload

} else {
let now_us = chrono::Local::now().timestamp_micros() as u64;

if let Some(rtt_us) = try_to_decode_rtt(&stream_buffer[0..chunk_size], last_rtt_us) {
timedata.entry(now_us).or_insert(TcpLogStats {
received_bytes: chunk_size as u64,
Expand Down Expand Up @@ -414,6 +413,47 @@ fn handle_downloading(params: DownloadingParameters) -> DownloaderState {
}
}

fn handle_post_download(download_stream_state: &mut DownloadStreamState) -> DownloaderState {
let DownloadStreamState {
base_addr,
path,
start_timestamp_us,
finish_timestamp_us,
timedata,
dci_total_dl_bit,
dci_rnti_dl_bit,
dci_total_dl_prb_with_tbs,
dci_total_dl_prb_no_tbs,
dci_rnti_dl_prb_with_tbs,
dci_rnti_dl_prb_no_tbs,
..
} = download_stream_state;

let now_us = chrono::Local::now().timestamp_micros() as u64;
if now_us < (finish_timestamp_us.unwrap() + POST_DOWNLOAD_TIME_US) {
// Stay in PostDownload and keep collecting DCI
DownloaderState::PostDownload
} else {
let total_download_bytes = determine_average_download_bytes(timedata);
let average_rtt_us = determine_average_rtt_us(timedata);
DownloaderState::FinishDownload(DownloadFinishParameters {
base_addr: base_addr.to_string(),
path: path.to_string(),
start_timestamp_us: *start_timestamp_us,
finish_timestamp_us: finish_timestamp_us.unwrap(),
average_rtt_us,
total_download_bytes,
dci_total_dl_bit: *dci_total_dl_bit,
dci_total_dl_prb_with_tbs: *dci_total_dl_prb_with_tbs,
dci_total_dl_prb_no_tbs: *dci_total_dl_prb_no_tbs,
dci_rnti_dl_bit: *dci_rnti_dl_bit,
dci_rnti_dl_prb_with_tbs: *dci_rnti_dl_prb_with_tbs,
dci_rnti_dl_prb_no_tbs: *dci_rnti_dl_prb_no_tbs,
})
}

}

fn create_download_stream(base_addr: &str, path: &str) -> Result<TcpStream> {
let mut stream = TcpStream::connect(base_addr)?;

Expand Down
8 changes: 5 additions & 3 deletions src/logic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use bus::BusReader;
use crate::cell_info::CellInfo;
use crate::logic::rnti_matcher::TrafficCollection;
use crate::ngscope::config::NgScopeConfig;
use crate::ngscope::types::NgScopeCellDci;
use crate::ngscope::types::{NgScopeCellDci, NgScopeCellConfig};

use self::downloader::{DownloadConfig, DownloadFinishParameters};

Expand Down Expand Up @@ -244,6 +244,7 @@ pub enum DownloaderState {
StartDownload,
ErrorStartingDownload(String),
Downloading,
PostDownload,
FinishDownload(DownloadFinishParameters),
}

Expand All @@ -268,8 +269,9 @@ impl WorkerState for DownloaderState {

#[allow(dead_code)]
#[derive(Clone, Debug)]
pub struct MessageDci {
ngscope_dci: NgScopeCellDci,
pub enum MessageDci {
CellDci(Box<NgScopeCellDci>),
CellConfig(Box<NgScopeCellConfig>),
}

#[allow(dead_code)]
Expand Down
Loading
Loading