#![allow(non_snake_case)]
#![allow(dead_code)]
use crate::{GetSetString, IDX_ORDER_QUICK, IDX_ORDER_READ, astro, get_last_error_message};
use std::os::raw::c_char;
unsafe extern "C" {
pub fn SensorInit(apAddr: i64) -> i32;
pub fn SensorGetInfo(infoStr: *const c_char);
pub fn SensorLoadFile(senFile: *const c_char) -> i32;
pub fn SensorLoadCard(card: *const c_char) -> i32;
pub fn SensorSaveFile(sensorFile: *const c_char, saveMode: i32, saveForm: i32) -> i32;
pub fn SensorRemove(senKey: i64) -> i32;
pub fn SensorRemoveAll() -> i32;
pub fn SensorGetCount() -> i32;
pub fn SensorGetLoaded(order: i32, senKeys: *mut i64);
pub fn SensorGetLocAll(
senKey: i64,
astroLat: *mut f64,
astroLon: *mut f64,
senPos: *mut [f64; 3],
senDesc: *const c_char,
orbSatNum: *mut i32,
secClass: *const c_char,
) -> i32;
pub fn SensorSetLocAll(
senKey: i64,
astroLat: f64,
astroLon: f64,
senPos: *const [f64; 3],
senDesc: *const c_char,
orbSatNum: i32,
secClass: c_char,
) -> i32;
pub fn SensorGetLocField(senKey: i64, xf_SenLoc: i32, strValue: *const c_char) -> i32;
pub fn SensorSetLocField(senKey: i64, xf_SenLoc: i32, strValue: *const c_char) -> i32;
pub fn SensorGet1L(
senKey: i64,
viewType: *const c_char,
obsType: *const c_char,
rngUnits: *mut i32,
maxRngLim: *mut f64,
boresight1: *const c_char,
elLim1: *mut f64,
elLim2: *mut f64,
azLim1: *mut f64,
azLim2: *mut f64,
interval: *mut f64,
visFlg: *mut i32,
rngLimFlg: *mut i32,
maxPPP: *mut i32,
minRngLim: *mut f64,
plntryRes: *mut i32,
rrLim: *mut f64,
) -> i32;
pub fn SensorSet1L(
senKey: i64,
viewType: c_char,
obsType: c_char,
rngUnits: i32,
maxRngLim: f64,
boresight1: c_char,
elLim1: f64,
elLim2: f64,
azLim1: f64,
azLim2: f64,
interval: f64,
visFlg: i32,
rngLimFlg: i32,
maxPPP: i32,
minRngLim: f64,
plntryRes: i32,
rrLim: f64,
) -> i32;
pub fn SensorGet2L(
senKey: i64,
boresight2: *const c_char,
elLim3: *mut f64,
elLim4: *mut f64,
azLim3: *mut f64,
azLim4: *mut f64,
earthBckgrnd: *mut i32,
earthLimb: *mut f64,
solarXAngle: *mut f64,
lunarXAngle: *mut f64,
minIllum: *mut f64,
twilit: *mut f64,
) -> i32;
pub fn SensorSet2L(
senKey: i64,
boresight2: c_char,
elLim3: f64,
elLim4: f64,
azLim3: f64,
azLim4: f64,
earthBckgrnd: i32,
earthLimb: f64,
solarXAngle: f64,
lunarXAngle: f64,
minIllum: f64,
twilit: f64,
) -> i32;
pub fn SensorGetLimField(senKey: i64, xf_SenLim: i32, strValue: *const c_char) -> i32;
pub fn SensorSetLimField(senKey: i64, xf_SenLim: i32, strValue: *const c_char) -> i32;
pub fn SensorGetBS(senKey: i64, xaf_senbs: *mut [f64; 16]) -> i32;
pub fn SensorSetBS(senKey: i64, xaf_senbs: *const [f64; 16]) -> i32;
pub fn SensorGetBSField(senKey: i64, xaf_senbs: i32, strValue: *const c_char) -> i32;
pub fn SensorSetBSField(senKey: i64, xaf_senbs: i32, strValue: *const c_char) -> i32;
pub fn SensorGetLines(senKey: i64, sCard: *const c_char, l1Card: *const c_char, l2Card: *const c_char) -> i32;
pub fn SensorGetBSLine(senKey: i64, bsCard: *const c_char) -> i32;
pub fn SensorGetOrbSatKey(senKey: i64, orbSatKey: *mut i64) -> i32;
pub fn SensorSetOrbSatKey(senKey: i64, orbSatKey: i64) -> i32;
pub fn SensorLoadAzElTable(senKey: i64, azElTableFile: *const c_char) -> i32;
pub fn SensorAddSegment(senKey: i64, segType: i32, xa_seg: *const [f64; 16]) -> i32;
pub fn SensorGetSegment(senKey: i64, segNum: i32, segType: *mut i32, xa_seg: *mut [f64; 16]) -> i32;
pub fn SetSenKeyMode(sen_keyMode: i32) -> i32;
pub fn GetSenKeyMode() -> i32;
pub fn SenNumOf(senKey: i64) -> i32;
pub fn SensorGetSenKey(senNum: i32) -> i64;
pub fn SensorGetSenKeyML(senNum: i32, senKey: *mut i64);
pub fn SensorAddFrArray(xa_sen: *const [f64; 128], xs_sen: *const c_char) -> i64;
pub fn SensorDataToArray(senKey: i64, xa_sen: *mut [f64; 128], xs_sen: *const c_char) -> i32;
}
pub fn get_dll_info() -> String {
let mut c_info = GetSetString::new();
unsafe { SensorGetInfo(c_info.pointer()) };
c_info.value()
}
pub static SEG_BCONE: i32 = 1;
pub static SEG_DOME: i32 = 2;
pub static XA_SEG_DOME_AZFR: i32 = 0;
pub static XA_SEG_DOME_AZTO: i32 = 1;
pub static XA_SEG_DOME_ELFR: i32 = 2;
pub static XA_SEG_DOME_ELTO: i32 = 3;
pub static XA_SEG_DOME_MINRNG: i32 = 4;
pub static XA_SEG_DOME_MAXRNG: i32 = 5;
pub static XA_SEG_DOME_SIZE: i32 = 16;
pub static XA_SEG_BCONE_BSAZ: i32 = 0;
pub static XA_SEG_BCONE_BSEL: i32 = 1;
pub static XA_SEG_BCONE_ANGFR: i32 = 2;
pub static XA_SEG_BCONE_ANGTO: i32 = 3;
pub static XA_SEG_BCONE_MINRNG: i32 = 4;
pub static XA_SEG_BCONE_MAXRNG: i32 = 5;
pub static XA_SEG_BCONE_MINEL: i32 = 6;
pub static XA_SEG_BCONE_SIZE: i32 = 16;
pub static SEN_KEYMODE_NODUP: i32 = 0;
pub static SEN_KEYMODE_DMA: i32 = 1;
pub static BADSENKEY: i32 = -1;
pub static DUPSENKEY: i32 = 0;
pub static VT_BCT: i32 = 2;
pub static VT_CON: i32 = 3;
pub static VT_OPT: i32 = 4;
pub static VT_FAN: i32 = 7;
pub static VT_ORB: i32 = 9;
pub static VT_FOR: i32 = 82;
pub static VT_FOV: i32 = 86;
pub const SENLOC_TYPE_ECR: i32 = 1;
pub const SENLOC_TYPE_EFG: i32 = 2;
pub const SENLOC_TYPE_LLH: i32 = 3;
pub const SENLOC_TYPE_ECI: i32 = 4;
pub const XA_SEN_GEN_SENNUM: usize = 0;
pub const XA_SEN_GEN_MINRNG: usize = 3;
pub const XA_SEN_GEN_MAXRNG: usize = 4;
pub const XA_SEN_GEN_RRLIM: usize = 5;
pub const XA_SEN_GEN_RNGLIMFLG: usize = 6;
pub const XA_SEN_GEN_SMSEN: usize = 7;
pub const XA_SEN_GRN_LOCTYPE: usize = 10;
pub const XA_SEN_GRN_POS1: usize = 11;
pub const XA_SEN_GRN_POS2: usize = 12;
pub const XA_SEN_GRN_POS3: usize = 13;
pub const XA_SEN_GRN_ASTROLAT: usize = 14;
pub const XA_SEN_GRN_ASTROLON: usize = 15;
pub const XA_SEN_GRN_ECITIME: usize = 16;
pub static XA_SEN_BCT_BRSGHTAZ: i32 = 20;
pub static XA_SEN_BCT_BRSGHTEL: i32 = 21;
pub static XA_SEN_BCT_HALFANG: i32 = 22;
pub static XA_SEN_BCT_MINEL: i32 = 23;
pub static XA_SEN_CON_SMSEN: i32 = 7;
pub static XA_SEN_CON_ELFR1: i32 = 20;
pub static XA_SEN_CON_ELTO1: i32 = 21;
pub static XA_SEN_CON_AZFR1: i32 = 22;
pub static XA_SEN_CON_AZTO1: i32 = 23;
pub static XA_SEN_CON_ELFR2: i32 = 24;
pub static XA_SEN_CON_ELTO2: i32 = 25;
pub static XA_SEN_CON_AZFR2: i32 = 26;
pub static XA_SEN_CON_AZTO2: i32 = 27;
pub static XA_SEN_OPT_ELFR1: i32 = 20;
pub static XA_SEN_OPT_ELTO1: i32 = 21;
pub static XA_SEN_OPT_AZFR1: i32 = 22;
pub static XA_SEN_OPT_AZTO1: i32 = 23;
pub static XA_SEN_OPT_ELFR2: i32 = 24;
pub static XA_SEN_OPT_ELTO2: i32 = 25;
pub static XA_SEN_OPT_AZFR2: i32 = 26;
pub static XA_SEN_OPT_AZTO2: i32 = 27;
pub static XA_SEN_OPT_SEA: i32 = 40;
pub static XA_SEN_OPT_TWILGHT: i32 = 41;
pub static XA_SEN_OPT_VISCHK: i32 = 42;
pub static XA_SEN_FAN_AZ: i32 = 20;
pub static XA_SEN_FAN_TILTANGLE: i32 = 21;
pub static XA_SEN_FAN_OBSANGLE: i32 = 23;
pub static XA_SEN_ORB_SATNUM: i32 = 10;
pub static XA_SEN_ORB_ELMIN1: i32 = 20;
pub static XA_SEN_ORB_ELMAX1: i32 = 21;
pub static XA_SEN_ORB_AZMIN1: i32 = 22;
pub static XA_SEN_ORB_AZMAX1: i32 = 23;
pub static XA_SEN_ORB_ELMIN2: i32 = 24;
pub static XA_SEN_ORB_ELMAX2: i32 = 25;
pub static XA_SEN_ORB_AZMIN2: i32 = 26;
pub static XA_SEN_ORB_AZMAX2: i32 = 27;
pub static XA_SEN_ORB_EARTHLIMB: i32 = 40;
pub static XA_SEN_ORB_SEA: i32 = 41;
pub static XA_SEN_ORB_LEA: i32 = 42;
pub static XA_SEN_ORB_MINILLUM: i32 = 43;
pub static XA_SEN_ORB_EARTHBRND: i32 = 44;
pub static XA_SEN_ORB_PLNTRYRES: i32 = 45;
pub static XA_SEN_FOV_BEAMWIDTH: i32 = 20;
pub static XA_SEN_FOV_TILTANGLE: i32 = 21;
pub static XA_SEN_GEN_UNIT: i32 = 90;
pub static XA_SEN_GEN_INTERVAL: i32 = 91;
pub static XA_SEN_GEN_PTSPERPAS: i32 = 92;
pub const XA_SEN_GEN_AZSIGMA: usize = 110;
pub const XA_SEN_GEN_ELSIGMA: usize = 111;
pub const XA_SEN_GEN_RGSIGMA: usize = 112;
pub const XA_SEN_GEN_RRSIGMA: usize = 113;
pub const XA_SEN_GEN_ARSIGMA: usize = 114;
pub const XA_SEN_GEN_ERSIGMA: usize = 115;
pub const XA_SEN_GEN_AZBIAS: usize = 116;
pub const XA_SEN_GEN_ELBIAS: usize = 117;
pub const XA_SEN_GEN_RGBIAS: usize = 118;
pub const XA_SEN_GEN_RRBIAS: usize = 119;
pub const XA_SEN_GEN_TIMEBIAS: usize = 120;
pub const XA_SEN_SIZE: usize = 128;
pub const XS_SEN_SECCLASS_0_1: usize = 0;
pub const XS_SEN_VIEWTYPE_1_1: usize = 1;
pub const XS_SEN_OBSTYPE_2_1: usize = 2;
pub const XS_SEN_DSCRPTN_3_24: usize = 3;
pub const XS_SEN_ORB_BSVEC1_27_1: usize = 27;
pub const XS_SEN_ORB_BSVEC2_28_1: usize = 28;
pub const XS_SEN_FOR_AZFILE_255_256: usize = 255;
pub const XS_SEN_LENGTH: usize = 512;
pub static XF_SENLOC_NUM: i32 = 1;
pub static XF_SENLOC_LAT: i32 = 2;
pub static XF_SENLOC_LON: i32 = 3;
pub static XF_SENLOC_POSX: i32 = 4;
pub static XF_SENLOC_POSY: i32 = 5;
pub static XF_SENLOC_POSZ: i32 = 6;
pub static XF_SENLOC_DESC: i32 = 7;
pub static XF_SENLOC_ORBSATNUM: i32 = 8;
pub static XF_SENLOC_SECCLASS: i32 = 9;
pub static XF_SENLIM_VIEWTYPE: i32 = 11;
pub static XF_SENLIM_OBSTYPE: i32 = 12;
pub static XF_SENLIM_UNIT: i32 = 13;
pub static XF_SENLIM_MAXRNG: i32 = 14;
pub static XF_SENLIM_MINRNG: i32 = 15;
pub static XF_SENLIM_INTERVAL: i32 = 16;
pub static XF_SENLIM_OPTVISFLG: i32 = 17;
pub static XF_SENLIM_RNGLIMFLG: i32 = 18;
pub static XF_SENLIM_PTSPERPAS: i32 = 19;
pub static XF_SENLIM_RRLIM: i32 = 20;
pub static XF_SENLIM_ELLIM1: i32 = 31;
pub static XF_SENLIM_ELLIM2: i32 = 32;
pub static XF_SENLIM_ELLIM3: i32 = 33;
pub static XF_SENLIM_ELLIM4: i32 = 34;
pub static XF_SENLIM_AZLIM1: i32 = 35;
pub static XF_SENLIM_AZLIM2: i32 = 36;
pub static XF_SENLIM_AZLIM3: i32 = 37;
pub static XF_SENLIM_AZLIM4: i32 = 38;
pub static XF_SENLIM_PLNTRYRES: i32 = 52;
pub static XF_SENLIM_BOREVEC1: i32 = 53;
pub static XF_SENLIM_BOREVEC2: i32 = 54;
pub static XF_SENLIM_KEARTH: i32 = 55;
pub static XF_SENLIM_ELIMB: i32 = 56;
pub static XF_SENLIM_SOLEXCANG: i32 = 57;
pub static XF_SENLIM_LUNEXCANG: i32 = 58;
pub static XF_SENLIM_MINIL: i32 = 59;
pub static XF_SENLIM_TWILIT: i32 = 60;
pub static XF_SENLIM_SMSEN: i32 = 61;
pub static XF_SENLIM_NUMSEGS: i32 = 62;
pub static XF_SENLIM_FILE: i32 = 63;
pub static XF_SENLIM_AZELROWS: i32 = 64;
pub static XA_SENLOC_NUM: i32 = 0;
pub static XA_SENLOC_LAT: i32 = 1;
pub static XA_SENLOC_LON: i32 = 2;
pub static XA_SENLOC_POSX: i32 = 3;
pub static XA_SENLOC_POSY: i32 = 4;
pub static XA_SENLOC_POSZ: i32 = 5;
pub static XA_SENLOC_SIZE: i32 = 16;
pub static XAF_SENBS_AZSIGMA: i32 = 0;
pub static XAF_SENBS_ELSIGMA: i32 = 1;
pub static XAF_SENBS_RGSIGMA: i32 = 2;
pub static XAF_SENBS_RRSIGMA: i32 = 3;
pub static XAF_SENBS_ARSIGMA: i32 = 4;
pub static XAF_SENBS_ERSIGMA: i32 = 5;
pub static XAF_SENBS_AZBIAS: i32 = 8;
pub static XAF_SENBS_ELBIAS: i32 = 9;
pub static XAF_SENBS_RGBIAS: i32 = 10;
pub static XAF_SENBS_RRBIAS: i32 = 11;
pub static XAF_SENBS_TIMEBIAS: i32 = 15;
pub static XAF_SENBS_SIZE: i32 = 16;
pub static OT_RRATE: i32 = 0;
pub static OT_AZEL: i32 = 1;
pub static OT_AZEL_RNG: i32 = 2;
pub static OT_AZEL_RNGRRATE: i32 = 3;
pub static OT_AZEL_ALL: i32 = 4;
pub static OT_RADEC: i32 = 5;
pub static OT_RNGONLY: i32 = 6;
pub static OT_AZEL_SENPOS: i32 = 8;
pub static OT_RADEC_SENPOS: i32 = 9;
pub static OT_VEL: i32 = 10;
pub static OT_POS: i32 = 11;
pub static OT_STAR: i32 = 12;
pub static OT_RF: i32 = 13;
pub static OT_SLR: i32 = 16;
pub static OT_M: i32 = 18;
pub static OT_O: i32 = 19;
pub static OT_RRATE_SELOB: i32 = 999;
pub struct ParsedSensor {
pub key: i64,
pub number: i32,
pub minimum_range: Option<f64>,
pub maximum_range: Option<f64>,
pub range_rate_limit: Option<f64>,
pub apply_range_limits: bool,
pub mobile: bool,
pub latitude: Option<f64>,
pub longitude: Option<f64>,
pub altitude: Option<f64>,
pub astronomical_latitude: f64,
pub astronomical_longitude: f64,
pub azimuth_noise: Option<f64>,
pub elevation_noise: Option<f64>,
pub range_noise: Option<f64>,
pub range_rate_noise: Option<f64>,
pub azimuth_rate_noise: Option<f64>,
pub elevation_rate_noise: Option<f64>,
pub description: Option<String>,
}
impl ParsedSensor {
pub fn from_number(number: i32) -> Result<ParsedSensor, String> {
let key = unsafe { SensorGetSenKey(number) };
if key > 0 {
ParsedSensor::from_key(key)
} else {
Err(get_last_error_message())
}
}
pub fn from_key(key: i64) -> Result<ParsedSensor, String> {
let (xa_sen, xs_sen) = get_arrays(key)?;
let description = match xs_sen[XS_SEN_DSCRPTN_3_24..XS_SEN_DSCRPTN_3_24 + 24].trim() {
"" => None,
desc => Some(desc.to_string()),
};
let minimum_range = if xa_sen[XA_SEN_GEN_MINRNG] != 0.0 {
Some(xa_sen[XA_SEN_GEN_MINRNG])
} else {
None
};
let maximum_range = if xa_sen[XA_SEN_GEN_MAXRNG] != 0.0 {
Some(xa_sen[XA_SEN_GEN_MAXRNG])
} else {
None
};
let range_rate_limit = if xa_sen[XA_SEN_GEN_RRLIM] != 0.0 {
Some(xa_sen[XA_SEN_GEN_RRLIM])
} else {
None
};
let lla = get_lla(key)?;
let mut latitude = None;
let mut longitude = None;
let mut altitude = None;
if let Some(lla_values) = lla {
latitude = Some(lla_values[0]);
longitude = Some(lla_values[1]);
altitude = Some(lla_values[2]);
}
let azimuth_noise = if xa_sen[XA_SEN_GEN_AZSIGMA] != 0.0 {
Some(xa_sen[XA_SEN_GEN_AZSIGMA])
} else {
None
};
let elevation_noise = if xa_sen[XA_SEN_GEN_ELSIGMA] != 0.0 {
Some(xa_sen[XA_SEN_GEN_ELSIGMA])
} else {
None
};
let range_noise = if xa_sen[XA_SEN_GEN_RGSIGMA] != 0.0 {
Some(xa_sen[XA_SEN_GEN_RGSIGMA])
} else {
None
};
let range_rate_noise = if xa_sen[XA_SEN_GEN_RRSIGMA] != 0.0 {
Some(xa_sen[XA_SEN_GEN_RRSIGMA])
} else {
None
};
let azimuth_rate_noise = if xa_sen[XA_SEN_GEN_ARSIGMA] != 0.0 {
Some(xa_sen[XA_SEN_GEN_ARSIGMA])
} else {
None
};
let elevation_rate_noise = if xa_sen[XA_SEN_GEN_ERSIGMA] != 0.0 {
Some(xa_sen[XA_SEN_GEN_ERSIGMA])
} else {
None
};
Ok(ParsedSensor {
key,
number: xa_sen[XA_SEN_GEN_SENNUM] as i32,
minimum_range,
maximum_range,
range_rate_limit,
apply_range_limits: xa_sen[XA_SEN_GEN_RNGLIMFLG] == 0.0,
mobile: xa_sen[XA_SEN_GEN_SMSEN] == 1.0,
latitude,
longitude,
altitude,
astronomical_latitude: xa_sen[XA_SEN_GRN_ASTROLAT],
astronomical_longitude: xa_sen[XA_SEN_GRN_ASTROLON],
azimuth_noise,
elevation_noise,
range_noise,
range_rate_noise,
azimuth_rate_noise,
elevation_rate_noise,
description,
})
}
}
pub fn parse_key(sen_key: i64) -> Result<ParsedSensor, String> {
ParsedSensor::from_key(sen_key)
}
pub fn prune_missing_locations() -> Result<(), String> {
let keys = get_keys(IDX_ORDER_QUICK);
for key in keys {
let lla = get_lla(key).unwrap_or(None);
if lla.is_none() {
remove(key)?;
}
}
Ok(())
}
pub fn parse_all() -> Result<Vec<ParsedSensor>, String> {
let keys = get_keys(IDX_ORDER_READ);
let mut sensors = Vec::new();
for key in keys {
let sensor = ParsedSensor::from_key(key)?;
sensors.push(sensor);
}
Ok(sensors)
}
pub fn get_astronomical_ll(sen_key: i64) -> Result<[f64; 2], String> {
let mut xa_sen = [0f64; XA_SEN_SIZE];
let mut xs_sen = GetSetString::new();
let result = unsafe { SensorDataToArray(sen_key, &mut xa_sen, xs_sen.pointer()) };
if result != 0 {
return Err(get_last_error_message());
}
Ok([xa_sen[XA_SEN_GRN_ASTROLAT], xa_sen[XA_SEN_GRN_ASTROLON]])
}
pub fn get_lla(sen_key: i64) -> Result<Option<[f64; 3]>, String> {
let mut xa_sen = [0f64; XA_SEN_SIZE];
let mut xs_sen = GetSetString::new();
let result = unsafe { SensorDataToArray(sen_key, &mut xa_sen, xs_sen.pointer()) };
if result != 0 {
return Err(get_last_error_message());
}
match xa_sen[XA_SEN_GRN_LOCTYPE] as i32 {
SENLOC_TYPE_LLH => Ok(Some([
xa_sen[XA_SEN_GRN_POS1],
xa_sen[XA_SEN_GRN_POS2],
xa_sen[XA_SEN_GRN_POS3],
])),
SENLOC_TYPE_EFG | SENLOC_TYPE_ECR => {
match astro::efg_to_lla(&[
xa_sen[XA_SEN_GRN_POS1],
xa_sen[XA_SEN_GRN_POS2],
xa_sen[XA_SEN_GRN_POS3],
]) {
Ok(lla) => Ok(Some(lla)),
Err(_) => Ok(None),
}
}
SENLOC_TYPE_ECI => Ok(None),
_ => Err("Unknown sensor location type.".to_string()),
}
}
pub fn get_keys(order: i32) -> Vec<i64> {
let count = count_loaded();
let mut keys = vec![0; count as usize];
unsafe {
SensorGetLoaded(order, keys.as_mut_ptr());
}
keys
}
pub fn load_card(card: &str) -> Result<(), String> {
let mut input_card: GetSetString = card.into();
let result = unsafe { SensorLoadCard(input_card.pointer()) };
match result {
0 => Ok(()),
_ => Err(get_last_error_message()),
}
}
pub fn remove(sen_key: i64) -> Result<(), String> {
let result = unsafe { SensorRemove(sen_key) };
match result {
0 => Ok(()),
_ => Err(get_last_error_message()),
}
}
pub fn count_loaded() -> i32 {
unsafe { SensorGetCount() }
}
pub fn load_file(file_path: &str) -> Result<(), String> {
let mut input_file: GetSetString = file_path.into();
let result = unsafe { SensorLoadFile(input_file.pointer()) };
match result {
0 => Ok(()),
_ => Err(get_last_error_message()),
}
}
pub fn clear() -> Result<(), String> {
let result = unsafe { SensorRemoveAll() };
match result {
0 => Ok(()),
_ => Err(get_last_error_message()),
}
}
pub fn get_arrays(sen_key: i64) -> Result<([f64; XA_SEN_SIZE], String), String> {
let mut xa_sen = [0f64; XA_SEN_SIZE];
let mut xs_sen = GetSetString::new();
let result = unsafe { SensorDataToArray(sen_key, &mut xa_sen, xs_sen.pointer()) };
match result {
0 => Ok((xa_sen, xs_sen.value())),
_ => Err(get_last_error_message()),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_lock::TEST_LOCK;
const SENSOR_CARD: &str = "211 3381724 -25333969 -1521161 -5083089 3530462 U SOCORRO CAM1 S";
const NOISE_CARD: &str = "211 5 0.0003 0.0003 0.0000 0.0000 -0.0005 -0.0003 0.0000 0.0000 0.0000 BS";
#[test]
fn test_load_file() {
let _lock = TEST_LOCK.lock().unwrap();
load_file("tests/data/sensors.dat").unwrap();
prune_missing_locations().unwrap();
assert_eq!(count_loaded(), 98);
let sensors = parse_all().unwrap();
clear().unwrap();
assert_eq!(count_loaded(), 0);
assert_eq!(sensors[0].number, 211);
assert_eq!(sensors[0].description.as_deref(), Some("SOCORRO CAM1"));
}
#[test]
fn test_get_arrays() {
let _lock = TEST_LOCK.lock().unwrap();
load_card(SENSOR_CARD).unwrap();
load_card(NOISE_CARD).unwrap();
let keys = get_keys(IDX_ORDER_READ);
let key = keys[keys.len() - 1];
let (xa_sen, xs_sen) = get_arrays(key).unwrap();
clear().unwrap();
assert_eq!(xa_sen[XA_SEN_GEN_SENNUM], 211.0);
assert_eq!(xa_sen[XA_SEN_GRN_POS1], -1521.161);
assert_eq!(xa_sen[XA_SEN_GRN_POS2], -5083.089);
assert_eq!(xa_sen[XA_SEN_GRN_POS3], 3530.462);
assert_eq!(xa_sen[XA_SEN_GRN_ASTROLAT], 33.81724);
assert_eq!(xa_sen[XA_SEN_GRN_ASTROLON], -253.33969);
assert_eq!(xa_sen[XA_SEN_GRN_ECITIME], 0.0);
assert_eq!(xa_sen[XA_SEN_GEN_RNGLIMFLG], 0.0);
assert_eq!(xa_sen[XA_SEN_GEN_SMSEN], 0.0);
assert_eq!(xa_sen[XA_SEN_GEN_MINRNG], 0.0);
assert_eq!(xa_sen[XA_SEN_GEN_MAXRNG], 0.0);
assert_eq!(xa_sen[XA_SEN_GEN_RRLIM], 0.0);
assert_eq!(xa_sen[XA_SEN_GRN_LOCTYPE], 1.0);
assert_eq!(xa_sen[XA_SEN_GEN_AZSIGMA], 0.0003);
assert_eq!(xa_sen[XA_SEN_GEN_ELSIGMA], 0.0003);
assert_eq!(xa_sen[XA_SEN_GEN_ARSIGMA], 0.0);
assert_eq!(xa_sen[XA_SEN_GEN_ERSIGMA], 0.0);
assert_eq!(xa_sen[XA_SEN_GEN_RGSIGMA], 0.0);
assert_eq!(xa_sen[XA_SEN_GEN_RRSIGMA], 0.0);
assert_eq!(xa_sen[XA_SEN_GEN_AZBIAS], -0.0005);
assert_eq!(xa_sen[XA_SEN_GEN_ELBIAS], -0.0003);
assert_eq!(xa_sen[XA_SEN_GEN_RGBIAS], 0.0);
assert_eq!(xa_sen[XA_SEN_GEN_RRBIAS], 0.0);
assert_eq!(xa_sen[XA_SEN_GEN_TIMEBIAS], 0.0);
assert_eq!(xs_sen.trim(), "U33SOCORRO CAM1");
}
fn test_parse_key() {
load_card(SENSOR_CARD).unwrap();
load_card(NOISE_CARD).unwrap();
let keys = get_keys(IDX_ORDER_READ);
let key = keys[keys.len() - 1];
let sensor = parse_key(key).unwrap();
clear().unwrap();
assert_eq!(sensor.number, 211);
assert!(sensor.minimum_range.is_none());
assert!(sensor.maximum_range.is_none());
assert!(sensor.range_rate_limit.is_none());
assert!(sensor.apply_range_limits);
assert!(!sensor.mobile);
assert_eq!(sensor.latitude.unwrap(), 33.817242266703744);
assert_eq!(sensor.longitude.unwrap(), 253.33970533290127);
assert_eq!(sensor.altitude.unwrap(), 1.509809294541032);
assert_eq!(sensor.astronomical_latitude, 33.81724);
assert_eq!(sensor.astronomical_longitude, -253.33969);
assert_eq!(sensor.azimuth_noise.unwrap(), 0.0003);
assert_eq!(sensor.elevation_noise.unwrap(), 0.0003);
assert!(sensor.range_noise.is_none());
assert!(sensor.range_rate_noise.is_none());
assert!(sensor.azimuth_rate_noise.is_none());
assert!(sensor.elevation_rate_noise.is_none());
assert_eq!(sensor.description.as_deref(), Some("SOCORRO CAM1"));
}
}