use super::OnvifClient;
use crate::error::OnvifError;
use crate::soap::{find_response, parse_soap_body};
use crate::types::{FindRecordingResults, RecordingItem, xml_escape};
impl OnvifClient {
pub async fn get_recordings(
&self,
recording_url: &str,
) -> Result<Vec<RecordingItem>, OnvifError> {
const ACTION: &str = "http://www.onvif.org/ver10/recording/wsdl/GetRecordings";
const BODY: &str = "<trc:GetRecordings/>";
let xml = self.call(recording_url, ACTION, BODY).await?;
let body_node = parse_soap_body(&xml)?;
let resp = find_response(&body_node, "GetRecordingsResponse")?;
RecordingItem::vec_from_xml(resp)
}
pub async fn find_recordings(
&self,
search_url: &str,
max_matches: Option<u32>,
keep_alive_timeout: &str,
) -> Result<String, OnvifError> {
const ACTION: &str = "http://www.onvif.org/ver10/search/wsdl/FindRecordings";
let max_el = max_matches
.map(|m| format!("<tse:MaxMatches>{m}</tse:MaxMatches>"))
.unwrap_or_default();
let body = format!(
"<tse:FindRecordings>\
{max_el}\
<tse:KeepAliveTime>{keep_alive_timeout}</tse:KeepAliveTime>\
</tse:FindRecordings>"
);
let xml = self.call(search_url, ACTION, &body).await?;
let body_node = parse_soap_body(&xml)?;
let resp = find_response(&body_node, "FindRecordingsResponse")?;
resp.child("SearchToken")
.map(|n| n.text().to_string())
.ok_or_else(|| crate::soap::SoapError::missing("SearchToken").into())
}
pub async fn get_recording_search_results(
&self,
search_url: &str,
search_token: &str,
max_results: u32,
wait_time: &str,
) -> Result<FindRecordingResults, OnvifError> {
const ACTION: &str = "http://www.onvif.org/ver10/search/wsdl/GetRecordingSearchResults";
let search_token = xml_escape(search_token);
let body = format!(
"<tse:GetRecordingSearchResults>\
<tse:SearchToken>{search_token}</tse:SearchToken>\
<tse:MaxResults>{max_results}</tse:MaxResults>\
<tse:WaitTime>{wait_time}</tse:WaitTime>\
</tse:GetRecordingSearchResults>"
);
let xml = self.call(search_url, ACTION, &body).await?;
let body_node = parse_soap_body(&xml)?;
let resp = find_response(&body_node, "GetRecordingSearchResultsResponse")?;
FindRecordingResults::from_xml(resp)
}
pub async fn end_search(&self, search_url: &str, search_token: &str) -> Result<(), OnvifError> {
const ACTION: &str = "http://www.onvif.org/ver10/search/wsdl/EndSearch";
let search_token = xml_escape(search_token);
let body = format!(
"<tse:EndSearch>\
<tse:SearchToken>{search_token}</tse:SearchToken>\
</tse:EndSearch>"
);
let xml = self.call(search_url, ACTION, &body).await?;
let body_node = parse_soap_body(&xml)?;
find_response(&body_node, "EndSearchResponse")?;
Ok(())
}
pub async fn get_replay_uri(
&self,
replay_url: &str,
recording_token: &str,
stream_type: &str,
protocol: &str,
) -> Result<String, OnvifError> {
const ACTION: &str = "http://www.onvif.org/ver10/replay/wsdl/GetReplayUri";
let recording_token = xml_escape(recording_token);
let stream_type = xml_escape(stream_type);
let protocol = xml_escape(protocol);
let body = format!(
"<trp:GetReplayUri>\
<trp:StreamSetup>\
<tt:Stream>{stream_type}</tt:Stream>\
<tt:Transport><tt:Protocol>{protocol}</tt:Protocol></tt:Transport>\
</trp:StreamSetup>\
<trp:RecordingToken>{recording_token}</trp:RecordingToken>\
</trp:GetReplayUri>"
);
let xml = self.call(replay_url, ACTION, &body).await?;
let body_node = parse_soap_body(&xml)?;
let resp = find_response(&body_node, "GetReplayUriResponse")?;
resp.child("Uri")
.map(|n| n.text().to_string())
.ok_or_else(|| crate::soap::SoapError::missing("Uri").into())
}
}