Skip to content

Commit 8fdfb65

Browse files
authored
GetVideoSourceConfigurations (#105)
1 parent a28e2f6 commit 8fdfb65

File tree

5 files changed

+122
-0
lines changed

5 files changed

+122
-0
lines changed

lib/media/ver10/profile/video_source_configuration.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ defmodule Onvif.Media.Ver10.Profile.VideoSourceConfiguration do
8888
)
8989
end
9090

91+
def to_struct(parsed) do
92+
%__MODULE__{}
93+
|> changeset(parsed)
94+
|> apply_action(:validate)
95+
end
96+
9197
def changeset(module, attrs) do
9298
module
9399
|> cast(attrs, [:reference_token, :name, :use_count, :view_mode, :source_token])
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
defmodule Onvif.Media.Ver20.GetVideoSourceConfigurations do
2+
import SweetXml
3+
import XmlBuilder
4+
5+
require Logger
6+
7+
alias Onvif.Device
8+
alias Onvif.Media.Ver10.Profile.VideoSourceConfiguration
9+
10+
@spec soap_action :: String.t()
11+
def soap_action, do: "http://www.onvif.org/ver20/media/wsdl/GetVideoSourceConfigurations"
12+
13+
@spec request(Device.t(), list) :: {:ok, any} | {:error, map()}
14+
def request(device, args \\ []),
15+
do: Onvif.Media.Ver20.Media.request(device, args, __MODULE__)
16+
17+
def request_body(configuration_token \\ nil, profile_token \\ nil) do
18+
config =
19+
with_configuration_token([], configuration_token) |> with_profile_token(profile_token)
20+
21+
element(:"s:Body", [
22+
element(:"tr2:GetVideoSourceConfigurations", config)
23+
])
24+
end
25+
26+
@spec response(any) :: {:error, Ecto.Changeset.t()} | {:ok, struct()}
27+
def response(xml_response_body) do
28+
response =
29+
xml_response_body
30+
|> parse(namespace_conformant: true, quiet: true)
31+
|> xpath(
32+
~x"//s:Envelope/s:Body/tr2:GetVideoSourceConfigurationsResponse/tr2:Configurations"el
33+
|> add_namespace("s", "http://www.w3.org/2003/05/soap-envelope")
34+
|> add_namespace("tr2", "http://www.onvif.org/ver20/media/wsdl")
35+
|> add_namespace("tt", "http://www.onvif.org/ver20/schema")
36+
)
37+
|> Enum.map(&VideoSourceConfiguration.parse/1)
38+
|> Enum.reduce([], fn raw_config, acc ->
39+
case VideoSourceConfiguration.to_struct(raw_config) do
40+
{:ok, config} ->
41+
[config | acc]
42+
43+
{:error, changeset} ->
44+
Logger.error("Discarding invalid Video config: #{inspect(changeset)}")
45+
acc
46+
end
47+
end)
48+
49+
{:ok, response}
50+
end
51+
52+
defp with_configuration_token(config, nil), do: config
53+
54+
defp with_configuration_token(config, configuration_token) do
55+
[element(:"tr2:ConfigurationToken", configuration_token) | config]
56+
end
57+
58+
defp with_profile_token(config, nil), do: config
59+
60+
defp with_profile_token(config, profile_token) do
61+
[element(:"tr2:ProfileToken", profile_token) | config]
62+
end
63+
end
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:c14n="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsa5="http://www.w3.org/2005/08/addressing" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:tnsaxis="http://www.axis.com/2009/event/topics" xmlns:tev="http://www.onvif.org/ver10/events/wsdl" xmlns:tr2="http://www.onvif.org/ver20/media/wsdl" xmlns:axt="http://www.onvif.org/ver20/analytics" xmlns:ter="http://www.onvif.org/ver10/error"><SOAP-ENV:Header></SOAP-ENV:Header><SOAP-ENV:Body><tr2:GetVideoSourceConfigurationsResponse><tr2:Configurations token="0"><tt:Name>user0</tt:Name><tt:UseCount>4</tt:UseCount><tt:SourceToken>0</tt:SourceToken><tt:Bounds height="2160" width="3840" y="0" x="0"></tt:Bounds><tt:Extension><tt:Rotate><tt:Mode>AUTO</tt:Mode></tt:Rotate></tt:Extension></tr2:Configurations></tr2:GetVideoSourceConfigurationsResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:SOAP-ENC=\"http://www.w3.org/2003/05/soap-encoding\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:c14n=\"http://www.w3.org/2001/10/xml-exc-c14n#\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsa5=\"http://www.w3.org/2005/08/addressing\" xmlns:tt=\"http://www.onvif.org/ver10/schema\" xmlns:wsnt=\"http://docs.oasis-open.org/wsn/b-2\" xmlns:tns1=\"http://www.onvif.org/ver10/topics\" xmlns:tnsaxis=\"http://www.axis.com/2009/event/topics\" xmlns:tev=\"http://www.onvif.org/ver10/events/wsdl\" xmlns:tr2=\"http://www.onvif.org/ver20/media/wsdl\" xmlns:axt=\"http://www.onvif.org/ver20/analytics\" xmlns:ter=\"http://www.onvif.org/ver10/error\"><SOAP-ENV:Header></SOAP-ENV:Header><SOAP-ENV:Body><SOAP-ENV:Fault><SOAP-ENV:Code><SOAP-ENV:Value>SOAP-ENV:Receiver</SOAP-ENV:Value><SOAP-ENV:Subcode><SOAP-ENV:Value>ter:Action</SOAP-ENV:Value></SOAP-ENV:Subcode></SOAP-ENV:Code><SOAP-ENV:Reason><SOAP-ENV:Text xml:lang=\"en\">Action failed</SOAP-ENV:Text></SOAP-ENV:Reason><SOAP-ENV:Detail><SOAP-ENV:Text>The requested SOAP action failed</SOAP-ENV:Text></SOAP-ENV:Detail></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>"
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
defmodule Onvif.Media.Ver20.GetVideoSourceConfigurationsTest do
2+
use ExUnit.Case, async: true
3+
4+
@moduletag capture_log: true
5+
6+
describe "GetVideoSourceConfigurations/1" do
7+
test "should parse with correct values" do
8+
xml_response = File.read!("test/media/ver20/fixtures/get_video_source_configurations.xml")
9+
10+
device = Onvif.Factory.device()
11+
12+
Mimic.expect(Tesla, :request, fn _client, _opts ->
13+
{:ok, %{status: 200, body: xml_response}}
14+
end)
15+
16+
{:ok, [response]} = Onvif.Media.Ver20.GetVideoSourceConfigurations.request(device, [])
17+
18+
assert %Onvif.Media.Ver10.Profile.VideoSourceConfiguration{
19+
name: "user0",
20+
reference_token: "0",
21+
source_token: "0",
22+
use_count: 4,
23+
bounds: %Onvif.Media.Ver10.Profile.VideoSourceConfiguration.Bounds{
24+
height: 2160,
25+
width: 3840,
26+
x: 0,
27+
y: 0
28+
}
29+
} == response
30+
end
31+
32+
test "should return error when response is invalid" do
33+
xml_response =
34+
File.read!("test/media/ver20/fixtures/invalid_get_video_source_configurations.xml")
35+
36+
device = Onvif.Factory.device()
37+
38+
Mimic.expect(Tesla, :request, fn _client, _opts ->
39+
{:ok, %{status: 400, body: xml_response}}
40+
end)
41+
42+
{:error, %{status: status, reason: reason, response: response}} =
43+
Onvif.Media.Ver20.GetVideoSourceConfigurations.request(device, ["1"])
44+
45+
assert status == 400
46+
assert reason == "Received 400 from Elixir.Onvif.Media.Ver20.GetVideoSourceConfigurations"
47+
assert response == xml_response
48+
end
49+
end
50+
end

0 commit comments

Comments
 (0)