From 62df632e6da47ab2601777a92c4454c46541686c Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Fri, 19 Jul 2024 13:22:17 -0300 Subject: [PATCH 1/4] #10178 SetNTP + tests --- lib/devices/set_ntp.ex | 58 +++++++++++++++ test/devices/fixtures/set_ntp_response.xml | 8 ++ test/devices/set_ntp.exs | 85 ++++++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 lib/devices/set_ntp.ex create mode 100644 test/devices/fixtures/set_ntp_response.xml create mode 100644 test/devices/set_ntp.exs diff --git a/lib/devices/set_ntp.ex b/lib/devices/set_ntp.ex new file mode 100644 index 0000000..42340e4 --- /dev/null +++ b/lib/devices/set_ntp.ex @@ -0,0 +1,58 @@ +defmodule Onvif.Devices.SetNTP do + import SweetXml + import XmlBuilder + + alias Onvif.Device + alias Onvif.Devices.NTP + + def soap_action, do: "http://www.onvif.org/ver10/device/wsdl/SetNTP" + + @spec request(Device.t(), list) :: {:ok, any} | {:error, map()} + def request(device, args) do + Onvif.Devices.request(device, args, __MODULE__) + end + + def request_body(config: %NTP{} = ntp) do + element(:"s:Body", [ + element(:"tds:SetNTP", [ + element(:"tds:FromDHCP", ntp.from_dhcp), + ntp_manual_element(ntp, ntp.from_dhcp) |> List.flatten() + ]) + ]) + end + + defp ntp_manual_element(%NTP{} = _ntp, true), do: [] + + defp ntp_manual_element(%NTP{} = ntp, false) do + [element(:"tds:NTPManual", ntp_add_manual_element(ntp.ntp_manual))] + end + + defp ntp_add_manual_element(ntp_manual) do + [ + element(:"tt:Type", ntp_manual.type), + ntp_manual_element_data(ntp_manual) + ] + end + + defp ntp_manual_element_data(ntp_manual) do + case ntp_manual.type do + "IPv4" -> element(:"tt:IPv4Address", ntp_manual.ipv4_address) + "IPv6" -> element(:"tt:IPv6Address", ntp_manual.ipv6_address) + "DNS" -> element(:"tt:DNSname", ntp_manual.dns_name) + end + end + + def response(xml_response_body) do + res = + xml_response_body + |> parse(namespace_conformant: true, quiet: true) + |> xpath( + ~x"//s:Envelope/s:Body/tds:SetNTPResponse/text()"s + |> add_namespace("s", "http://www.w3.org/2003/05/soap-envelope") + |> add_namespace("tds", "http://www.onvif.org/ver10/device/wsdl") + |> add_namespace("tt", "http://www.onvif.org/ver10/schema") + ) + + {:ok, res} + end +end diff --git a/test/devices/fixtures/set_ntp_response.xml b/test/devices/fixtures/set_ntp_response.xml new file mode 100644 index 0000000..285e735 --- /dev/null +++ b/test/devices/fixtures/set_ntp_response.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/test/devices/set_ntp.exs b/test/devices/set_ntp.exs new file mode 100644 index 0000000..08202b4 --- /dev/null +++ b/test/devices/set_ntp.exs @@ -0,0 +1,85 @@ +defmodule Onvif.Devices.SetNTPTest do + use ExUnit.Case, async: true + + @moduletag capture_log: true + + describe "SetNTP/2" do + test "check a dhcp-based ntp" do + xml_response = File.read!("test/devices/fixtures/set_ntp_response.xml") + + device = Onvif.Factory.device() + + Mimic.expect(Tesla, :request, fn _client, _opts -> + {:ok, %{status: 200, body: xml_response}} + end) + + {:ok, service_capabilities} = + Onvif.Devices.SetNTP.request(device, config: %Onvif.Devices.NTP{from_dhcp: true}) + + assert service_capabilities == "" + end + + test "check a manual ntp with IPv4" do + xml_response = File.read!("test/devices/fixtures/set_ntp_response.xml") + + device = Onvif.Factory.device() + + Mimic.expect(Tesla, :request, fn _client, _opts -> + {:ok, %{status: 200, body: xml_response}} + end) + + {:ok, service_capabilities} = + Onvif.Devices.SetNTP.request(device, + config: %Onvif.Devices.NTP{ + from_dhcp: false, + ntp_manual: %Onvif.Devices.NTP.NTPManual{type: "IPv4", ipv4_address: "6.6.6.0"} + } + ) + + assert service_capabilities == "" + end + + test "check a manual ntp with IPv6" do + xml_response = File.read!("test/devices/fixtures/set_ntp_response.xml") + + device = Onvif.Factory.device() + + Mimic.expect(Tesla, :request, fn _client, _opts -> + {:ok, %{status: 200, body: xml_response}} + end) + + {:ok, service_capabilities} = + Onvif.Devices.SetNTP.request(device, + config: %Onvif.Devices.NTP{ + from_dhcp: false, + ntp_manual: %Onvif.Devices.NTP.NTPManual{ + type: "IPv6", + ipv6_address: "2001:0db8:85a3:0000:0000:8a2e:0370:7334" + } + } + ) + + assert service_capabilities == "" + end + + test "check a manual ntp with DNS" do + xml_response = File.read!("test/devices/fixtures/set_ntp_response.xml") + + device = Onvif.Factory.device() + + Mimic.expect(Tesla, :request, fn _client, _opts -> + {:ok, %{status: 200, body: xml_response}} + end) + + {:ok, service_capabilities} = + Onvif.Devices.SetNTP.request(device, + config: %Onvif.Devices.NTP{ + from_dhcp: false, + ntp_manual: %Onvif.Devices.NTP.NTPManual{type: "DNS", dns_name: "ntp.example.com"} + } + ) + + assert service_capabilities == "" + end + end +end From 852ce082860b94151c8021bdc386526bdb462704 Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Fri, 19 Jul 2024 14:44:22 -0300 Subject: [PATCH 2/4] #10178 fix pattern matching --- lib/devices/set_ntp.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/devices/set_ntp.ex b/lib/devices/set_ntp.ex index 42340e4..f887f73 100644 --- a/lib/devices/set_ntp.ex +++ b/lib/devices/set_ntp.ex @@ -16,14 +16,14 @@ defmodule Onvif.Devices.SetNTP do element(:"s:Body", [ element(:"tds:SetNTP", [ element(:"tds:FromDHCP", ntp.from_dhcp), - ntp_manual_element(ntp, ntp.from_dhcp) |> List.flatten() + ntp_manual_element(ntp) |> List.flatten() ]) ]) end - defp ntp_manual_element(%NTP{} = _ntp, true), do: [] + defp ntp_manual_element(%NTP{from_dhcp: true} = _ntp), do: [] - defp ntp_manual_element(%NTP{} = ntp, false) do + defp ntp_manual_element(%NTP{from_dhcp: false} = ntp) do [element(:"tds:NTPManual", ntp_add_manual_element(ntp.ntp_manual))] end From 308a8616ac208a81babaeee89f910be8487cacc2 Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Fri, 19 Jul 2024 14:50:04 -0300 Subject: [PATCH 3/4] #10178 replace cond with pattern matching --- lib/devices/set_ntp.ex | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/devices/set_ntp.ex b/lib/devices/set_ntp.ex index f887f73..209e3d3 100644 --- a/lib/devices/set_ntp.ex +++ b/lib/devices/set_ntp.ex @@ -34,13 +34,9 @@ defmodule Onvif.Devices.SetNTP do ] end - defp ntp_manual_element_data(ntp_manual) do - case ntp_manual.type do - "IPv4" -> element(:"tt:IPv4Address", ntp_manual.ipv4_address) - "IPv6" -> element(:"tt:IPv6Address", ntp_manual.ipv6_address) - "DNS" -> element(:"tt:DNSname", ntp_manual.dns_name) - end - end + defp ntp_manual_element_data(%NTP.NTPManual{type: "IPv4"} = ntp_manual), do: element(:"tt:IPv4Address", ntp_manual.ipv4_address) + defp ntp_manual_element_data(%NTP.NTPManual{type: "IPv6"} = ntp_manual), do: element(:"tt:IPv6Address", ntp_manual.ipv6_address) + defp ntp_manual_element_data(%NTP.NTPManual{type: "DNS"} = ntp_manual), do: element(:"tt:DNSname", ntp_manual.dns_name) def response(xml_response_body) do res = From d7dc839dd082847c1e5f759ad9ef992ffea8c5c2 Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Fri, 19 Jul 2024 15:23:07 -0300 Subject: [PATCH 4/4] #10178 fix key representation --- lib/devices/set_ntp.ex | 16 ++++++++++++---- test/devices/set_ntp.exs | 6 +++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/devices/set_ntp.ex b/lib/devices/set_ntp.ex index 209e3d3..2c66a76 100644 --- a/lib/devices/set_ntp.ex +++ b/lib/devices/set_ntp.ex @@ -29,14 +29,22 @@ defmodule Onvif.Devices.SetNTP do defp ntp_add_manual_element(ntp_manual) do [ - element(:"tt:Type", ntp_manual.type), + element( + :"tt:Type", + Keyword.fetch!(Ecto.Enum.mappings(ntp_manual.__struct__, :type), ntp_manual.type) + ), ntp_manual_element_data(ntp_manual) ] end - defp ntp_manual_element_data(%NTP.NTPManual{type: "IPv4"} = ntp_manual), do: element(:"tt:IPv4Address", ntp_manual.ipv4_address) - defp ntp_manual_element_data(%NTP.NTPManual{type: "IPv6"} = ntp_manual), do: element(:"tt:IPv6Address", ntp_manual.ipv6_address) - defp ntp_manual_element_data(%NTP.NTPManual{type: "DNS"} = ntp_manual), do: element(:"tt:DNSname", ntp_manual.dns_name) + defp ntp_manual_element_data(%NTP.NTPManual{type: :ipv4} = ntp_manual), + do: element(:"tt:IPv4Address", ntp_manual.ipv4_address) + + defp ntp_manual_element_data(%NTP.NTPManual{type: :ipv6} = ntp_manual), + do: element(:"tt:IPv6Address", ntp_manual.ipv6_address) + + defp ntp_manual_element_data(%NTP.NTPManual{type: :dns} = ntp_manual), + do: element(:"tt:DNSname", ntp_manual.dns_name) def response(xml_response_body) do res = diff --git a/test/devices/set_ntp.exs b/test/devices/set_ntp.exs index 08202b4..8cbe8d8 100644 --- a/test/devices/set_ntp.exs +++ b/test/devices/set_ntp.exs @@ -32,7 +32,7 @@ defmodule Onvif.Devices.SetNTPTest do Onvif.Devices.SetNTP.request(device, config: %Onvif.Devices.NTP{ from_dhcp: false, - ntp_manual: %Onvif.Devices.NTP.NTPManual{type: "IPv4", ipv4_address: "6.6.6.0"} + ntp_manual: %Onvif.Devices.NTP.NTPManual{type: :ipv4, ipv4_address: "6.6.6.0"} } ) @@ -53,7 +53,7 @@ defmodule Onvif.Devices.SetNTPTest do config: %Onvif.Devices.NTP{ from_dhcp: false, ntp_manual: %Onvif.Devices.NTP.NTPManual{ - type: "IPv6", + type: :ipv6, ipv6_address: "2001:0db8:85a3:0000:0000:8a2e:0370:7334" } } @@ -75,7 +75,7 @@ defmodule Onvif.Devices.SetNTPTest do Onvif.Devices.SetNTP.request(device, config: %Onvif.Devices.NTP{ from_dhcp: false, - ntp_manual: %Onvif.Devices.NTP.NTPManual{type: "DNS", dns_name: "ntp.example.com"} + ntp_manual: %Onvif.Devices.NTP.NTPManual{type: :dns, dns_name: "ntp.example.com"} } )