use super::xml_str;
use crate::error::OnvifError;
use crate::soap::{SoapError, XmlNode};
#[derive(Debug, Clone)]
pub struct PtzPreset {
pub token: String,
pub name: String,
pub pan_tilt: Option<(f32, f32)>,
pub zoom: Option<f32>,
}
impl PtzPreset {
pub(crate) fn vec_from_xml(resp: &XmlNode) -> Result<Vec<Self>, OnvifError> {
resp.children_named("Preset")
.map(|p| {
let token = p
.attr("token")
.filter(|t| !t.is_empty())
.ok_or_else(|| SoapError::missing("Preset/@token"))?
.to_string();
Ok(Self {
token,
name: xml_str(p, "Name").unwrap_or_default(),
pan_tilt: p.path(&["PTZPosition", "PanTilt"]).and_then(|n| {
let x = n.attr("x")?.parse().ok()?;
let y = n.attr("y")?.parse().ok()?;
Some((x, y))
}),
zoom: p
.path(&["PTZPosition", "Zoom"])
.and_then(|n| n.attr("x")?.parse().ok()),
})
})
.collect()
}
}
#[derive(Debug, Clone)]
pub struct PtzStatus {
pub pan: Option<f32>,
pub tilt: Option<f32>,
pub zoom: Option<f32>,
pub pan_tilt_status: String,
pub zoom_status: String,
}
impl PtzStatus {
pub(crate) fn from_xml(resp: &XmlNode) -> Result<Self, OnvifError> {
let status = resp
.child("PTZStatus")
.ok_or_else(|| SoapError::missing("PTZStatus"))?;
let (pan, tilt) = status
.path(&["Position", "PanTilt"])
.and_then(|n| {
let x = n.attr("x")?.parse().ok()?;
let y = n.attr("y")?.parse().ok()?;
Some((Some(x), Some(y)))
})
.unwrap_or((None, None));
let zoom = status
.path(&["Position", "Zoom"])
.and_then(|n| n.attr("x")?.parse().ok());
Ok(Self {
pan,
tilt,
zoom,
pan_tilt_status: status
.path(&["MoveStatus", "PanTilt"])
.map(|n| n.text().to_string())
.unwrap_or_default(),
zoom_status: status
.path(&["MoveStatus", "Zoom"])
.map(|n| n.text().to_string())
.unwrap_or_default(),
})
}
}