diff --git a/lib/device.ex b/lib/device.ex
index 612e912..640dc15 100644
--- a/lib/device.ex
+++ b/lib/device.ex
@@ -333,6 +333,4 @@ defmodule Onvif.Device do
%Onvif.Device.Service{} = service -> service.xaddr |> URI.parse() |> Map.get(:path)
end
end
-
-
end
diff --git a/lib/recording/create_recording.ex b/lib/recording/create_recording.ex
index 3416e23..d866f64 100644
--- a/lib/recording/create_recording.ex
+++ b/lib/recording/create_recording.ex
@@ -53,8 +53,9 @@ defmodule Onvif.Recording.CreateRecording do
def gen_maximum_retention_time(nil), do: []
def gen_maximum_retention_time(""), do: []
- def gen_maximum_retention_time(maximum_retention_time), do: element(:"tt:MaximumRetentionTime", maximum_retention_time)
+ def gen_maximum_retention_time(maximum_retention_time),
+ do: element(:"tt:MaximumRetentionTime", maximum_retention_time)
def response(xml_response_body) do
recording_token =
diff --git a/lib/recording/create_recording_job.ex b/lib/recording/create_recording_job.ex
index da1ca52..9614d8b 100644
--- a/lib/recording/create_recording_job.ex
+++ b/lib/recording/create_recording_job.ex
@@ -31,6 +31,7 @@ defmodule Onvif.Recording.CreateRecordingJob do
|> add_namespace("trc", "http://www.onvif.org/ver10/recording/wsdl")
|> add_namespace("tt", "http://www.onvif.org/ver10/schema")
)
+
{:ok, parsed_result}
end
end
diff --git a/lib/search/find_events.ex b/lib/search/find_events.ex
new file mode 100644
index 0000000..93ff136
--- /dev/null
+++ b/lib/search/find_events.ex
@@ -0,0 +1,39 @@
+defmodule Onvif.Search.FindEvents do
+ import SweetXml
+ import XmlBuilder
+ require Logger
+
+ def soap_action, do: "http://www.onvif.org/ver10/search/wsdl/FindEvents"
+
+ def request(device, args) do
+ Onvif.Search.request(device, args, __MODULE__)
+ end
+
+ def request_body([included_recordings, start_point, end_point, search_filter, keep_alive_time]) do
+ element(:"s:Body", [
+ element(:"tse:FindEvents", [
+ element(:"tse:StartPoint", start_point),
+ element(:"tse:EndPoint", end_point),
+ element(:"tse:scope", [
+ Enum.map(included_recordings, fn ir -> element(:"tt:IncludedRecordings", [ir]) end)
+ ]),
+ element(:"tt:SearchFilter", [search_filter]),
+ element(:"tse:IncludeStartState", false),
+ element(:"tse:KeepAliveTime", keep_alive_time)
+ ])
+ ])
+ end
+
+ def response(xml_response_body) do
+ parsed_result =
+ xml_response_body
+ |> parse(namespace_conformant: true, quiet: true)
+ |> xpath(
+ ~x"//tse:SearchToken/text()"s
+ |> add_namespace("s", "http://www.w3.org/2003/05/soap-envelope")
+ |> add_namespace("tse", "http://www.onvif.org/ver10/search/wsdl")
+ )
+
+ {:ok, parsed_result}
+ end
+end
diff --git a/lib/search/get_recording_summary.ex b/lib/search/get_recording_summary.ex
new file mode 100644
index 0000000..e818814
--- /dev/null
+++ b/lib/search/get_recording_summary.ex
@@ -0,0 +1,35 @@
+defmodule Onvif.Search.GetRecordingSummary do
+ import SweetXml
+ import XmlBuilder
+ require Logger
+
+ def soap_action, do: "http://www.onvif.org/ver10/search/wsdl/GetRecordingSummary"
+
+ def request(device) do
+ Onvif.Search.request(device, __MODULE__)
+ end
+
+ def request_body() do
+ element(:"s:Body", [
+ element(:"tse:GetRecordingSummary")
+ ])
+ end
+
+ def response(xml_response_body) do
+ doc = parse(xml_response_body, namespace_conformant: true, quiet: true)
+
+ parsed_result =
+ xpath(
+ doc,
+ ~x"//s:Envelope/s:Body/tse:GetRecordingSummaryResponse/tse:Summary"
+ |> add_namespace("s", "http://www.w3.org/2003/05/soap-envelope")
+ |> add_namespace("tse", "http://www.onvif.org/ver10/search/wsdl")
+ |> add_namespace("tt", "http://www.onvif.org/ver10/schema"),
+ data_from: ~x"//tt:DataFrom/text()"so,
+ data_until: ~x"//tt:DataUntil/text()"so,
+ number_recordings: ~x"//tt:NumberRecordings/text()"so
+ )
+
+ {:ok, parsed_result}
+ end
+end
diff --git a/test/recording/create_recording_job_test.exs b/test/recording/create_recording_job_test.exs
index 2437cb9..465bd32 100644
--- a/test/recording/create_recording_job_test.exs
+++ b/test/recording/create_recording_job_test.exs
@@ -13,7 +13,12 @@ defmodule Onvif.Recording.CreateRecordingJobTest do
{:ok, %{status: 200, body: xml_response}}
end)
- {:ok, response} = Onvif.Recording.CreateRecordingJob.request(device, ["SD_DISK_20241120_211729_9C896594", "9", "Active"])
+ {:ok, response} =
+ Onvif.Recording.CreateRecordingJob.request(device, [
+ "SD_DISK_20241120_211729_9C896594",
+ "9",
+ "Active"
+ ])
assert response == "SD_DISK_20241120_211729_9C896594"
end
diff --git a/test/recording/create_recording_test.exs b/test/recording/create_recording_test.exs
index 65042cd..5dc4f83 100644
--- a/test/recording/create_recording_test.exs
+++ b/test/recording/create_recording_test.exs
@@ -13,15 +13,17 @@ defmodule Onvif.Recording.CreateRecordingTest do
{:ok, %{status: 200, body: xml_response}}
end)
- {:ok, response_uri} = Onvif.Recording.CreateRecording.request(
- device,
- config: %Onvif.Recording.Recording.Configuration{
+ {:ok, response_uri} =
+ Onvif.Recording.CreateRecording.request(
+ device,
+ config: %Onvif.Recording.Recording.Configuration{
content: "test",
maximum_retention_time: "PT1H",
source: %Onvif.Recording.Recording.Configuration.Source{
- name: "test",
+ name: "test"
}
- })
+ }
+ )
assert response_uri == "SD_DISK_20200422_123501_A2388AB3"
end
diff --git a/test/search/find_events_test.exs b/test/search/find_events_test.exs
new file mode 100644
index 0000000..a0d5da0
--- /dev/null
+++ b/test/search/find_events_test.exs
@@ -0,0 +1,28 @@
+defmodule Onvif.Search.FindEventsTest do
+ use ExUnit.Case, async: true
+
+ @moduletag capture_log: true
+
+ describe "FindEvents/2" do
+ test "get an event search token" do
+ xml_response = File.read!("test/search/fixtures/find_events__success.xml")
+
+ device = Onvif.Factory.device()
+
+ Mimic.expect(Tesla, :request, fn _client, _opts ->
+ {:ok, %{status: 200, body: xml_response}}
+ end)
+
+ {:ok, response} =
+ Onvif.Search.FindEvents.request(device, [
+ ["Record_004"],
+ "2024-12-06T19:00:00.0Z",
+ "2024-12-06T19:02:00.0Z",
+ "tns1:RecordingHistory/Track/State",
+ "PT1M"
+ ])
+
+ assert response == "SearchToken[1]"
+ end
+ end
+end
diff --git a/test/search/fixtures/find_events__success.xml b/test/search/fixtures/find_events__success.xml
new file mode 100644
index 0000000..6023b58
--- /dev/null
+++ b/test/search/fixtures/find_events__success.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+ SearchToken[1]
+
+
+
\ No newline at end of file
diff --git a/test/search/fixtures/get_recording_summary__success.xml b/test/search/fixtures/get_recording_summary__success.xml
new file mode 100644
index 0000000..8130e42
--- /dev/null
+++ b/test/search/fixtures/get_recording_summary__success.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+ 1970-01-01T00:00:00Z
+ 2024-12-13T08:08:49Z
+ 8
+
+
+
+
diff --git a/test/search/get_recording_summary_test.exs b/test/search/get_recording_summary_test.exs
new file mode 100644
index 0000000..30f466d
--- /dev/null
+++ b/test/search/get_recording_summary_test.exs
@@ -0,0 +1,25 @@
+defmodule Onvif.Search.GetRecordingSummaryTest do
+ use ExUnit.Case, async: true
+
+ @moduletag capture_log: true
+
+ describe "GetRecordingSummary/0" do
+ test "get an event search token" do
+ xml_response = File.read!("test/search/fixtures/get_recording_summary__success.xml")
+
+ device = Onvif.Factory.device()
+
+ Mimic.expect(Tesla, :request, fn _client, _opts ->
+ {:ok, %{status: 200, body: xml_response}}
+ end)
+
+ {:ok, response} =
+ Onvif.Search.GetRecordingSummary.request(device)
+
+ assert response == %{
+ data_from: "1970-01-01T00:00:00Z",
+ data_until: "2024-12-13T08:08:49Z",
+ number_recordings: "8"}
+ end
+ end
+end