From bf464bb732b0a01eaf8d420da47d306366e96711 Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Mon, 8 Jul 2024 21:57:24 +0100 Subject: [PATCH 01/20] #10471 Create SystemDateAndTime schema --- lib/devices/system_date_and_time.ex | 178 +++++++++++++++++++++++++++- 1 file changed, 177 insertions(+), 1 deletion(-) diff --git a/lib/devices/system_date_and_time.ex b/lib/devices/system_date_and_time.ex index 7022d61..4397d02 100644 --- a/lib/devices/system_date_and_time.ex +++ b/lib/devices/system_date_and_time.ex @@ -1,3 +1,179 @@ defmodule Onvif.Devices.SystemDateAndTime do - defstruct [:datetime, :ntp, :current_diff] + use Ecto.Schema + import Ecto.Changeset + import SweetXml + + @primary_key false + @derive Jason.Encoder + @required [:date_time_type, :daylight_savings] + @optional [] + + embedded_schema do + field :date_time_type, Ecto.Enum, values: [manual: "Manual", ntp: "NTP"] + field :daylight_savings, :boolean, default: true + field :datetime, :utc_datetime + field :current_diff, :integer + + embeds_one :time_zone, TimeZone, primary_key: false, on_replace: :update do + @derive Jason.Encoder + field(:tz, :string) + end + + embeds_one :utc_date_time, UTCDateTime, primary_key: false, on_replace: :update do + @derive Jason.Encoder + + embeds_one :time, Time, primary_key: false, on_replace: :update do + @derive Jason.Encoder + field(:hour, :integer) + field(:minute, :integer) + field(:second, :integer) + end + + embeds_one :date, Date, primary_key: false, on_replace: :update do + @derive Jason.Encoder + field(:year, :integer) + field(:month, :integer) + field(:day, :integer) + end + end + + embeds_one :local_date_time, UTCDateTime, primary_key: false, on_replace: :update do + @derive Jason.Encoder + + embeds_one :time, Time, primary_key: false, on_replace: :update do + @derive Jason.Encoder + field(:hour, :integer) + field(:minute, :integer) + field(:second, :integer) + end + + embeds_one :date, Date, primary_key: false, on_replace: :update do + @derive Jason.Encoder + field(:year, :integer) + field(:month, :integer) + field(:day, :integer) + end + end + end + + def parse(nil), do: nil + def parse([]), do: nil + + def parse(doc) do + xmap( + doc, + date_time_type: ~x"./tt:DateTimeType/text()"so, + daylight_savings: ~x"./tt:DaylightSavings/text()"so, + time_zone: ~x"./tt:TimeZone"eo |> transform_by(&parse_time_zone/1), + utc_date_time: ~x"./tt:UTCDateTime"eo |> transform_by(&parse_date_time/1), + local_date_time: ~x"./tt:LocalDateTime"eo |> transform_by(&parse_date_time/1) + ) + end + + defp parse_time_zone([]), do: nil + defp parse_time_zone(nil), do: nil + defp parse_time_zone(doc) do + xmap( + doc, + tz: ~x"./tt:TZ/text()"s + ) + end + + defp parse_date_time([]), do: nil + defp parse_date_time(nil), do: nil + defp parse_date_time(doc) do + xmap( + doc, + time: ~x"./tt:Time"eo |> transform_by(&parse_time/1), + date: ~x"./tt:Date"eo |> transform_by(&parse_date/1), + ) + end + + defp parse_time([]), do: nil + defp parse_time(nil), do: nil + defp parse_time(doc) do + xmap( + doc, + hour: ~x"./tt:Hour/text()"i, + minute: ~x"./tt:Minute/text()"i, + second: ~x"./tt:Second/text()"i + ) + end + defp parse_date([]), do: nil + defp parse_date(nil), do: nil + defp parse_date(doc) do + xmap( + doc, + year: ~x"./tt:Year/text()"i, + month: ~x"./tt:Month/text()"i, + day: ~x"./tt:Day/text()"i + ) + end + + def to_struct(parsed) do + %__MODULE__{} + |> changeset(parsed) + |> apply_action(:validate) + end + + @spec to_json(%__MODULE__{}) :: + {:error, + %{ + :__exception__ => any, + :__struct__ => Jason.EncodeError | Protocol.UndefinedError, + optional(atom) => any + }} + | {:ok, binary} + def to_json(%__MODULE__{} = schema) do + Jason.encode(schema) + end + + + def changeset(module, attrs) do + module + |> cast(attrs, @required ++ @optional) + |> validate_required(@required) + |> cast_embed(:time_zone, with: &time_zone_changeset/2) + |> cast_embed(:utc_date_time, with: &date_time_changeset/2) + |> cast_embed(:local_date_time, with: &date_time_changeset/2) + |> put_datetime + |> put_current_diff + end + + defp put_datetime(changeset) do + case get_field(changeset, :utc_date_time) do + nil -> changeset + utc_date_time -> + {:ok, date} = Date.new(utc_date_time.date.year, utc_date_time.date.month, utc_date_time.date.day) + {:ok, time} = Time.new(utc_date_time.time.hour, utc_date_time.time.minute, utc_date_time.time.second) + {:ok, datetime} = DateTime.new(date, time) + put_change(changeset, :datetime, datetime) + end + end + + defp put_current_diff(changeset) do + case get_field(changeset, :datetime) do + nil -> changeset + datetime -> + current = DateTime.utc_now() + diff = DateTime.diff(datetime, current) + put_change(changeset, :current_diff, diff) + end + end + + defp time_zone_changeset(module, attrs) do + cast(module, attrs, [:tz]) + end + defp date_time_changeset(module, attrs) do + cast(module, attrs, []) + |> cast_embed(:date, with: &date_changeset/2) + |> cast_embed(:time, with: &time_changeset/2) + end + defp date_changeset(module, attrs) do + cast(module, attrs, [:year, :month, :day]) + end + defp time_changeset(module, attrs) do + cast(module, attrs, [:hour, :minute, :second]) + end + end From b1f4225054b14a92a5914958133f7be8d85af69b Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Mon, 8 Jul 2024 21:58:54 +0100 Subject: [PATCH 02/20] #10471 Update the functions structure --- lib/device.ex | 7 +++++-- lib/devices/devices.ex | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/device.ex b/lib/device.ex index 3de9653..a329bf5 100644 --- a/lib/device.ex +++ b/lib/device.ex @@ -21,7 +21,8 @@ defmodule Onvif.Device do :auth_type, :time_diff_from_system_secs, :port, - :device_service_path + :device_service_path, + :system_date_time ] @type t :: %__MODULE__{} @@ -41,6 +42,7 @@ defmodule Onvif.Device do field(:ntp, :string) field(:media_ver10_service_path, :string) field(:media_ver20_service_path, :string) + embeds_one(:system_date_time, Onvif.Devices.SystemDateAndTime) embeds_many(:services, Onvif.Device.Service) field(:auth_type, Ecto.Enum, @@ -84,6 +86,7 @@ defmodule Onvif.Device do def changeset(%__MODULE__{} = device, attrs \\ %{}) do device |> cast(attrs, @required ++ @optional) + |> cast_embed(:system_date_time, with: &Onvif.Devices.SystemDateAndTime.changeset/2) |> cast_embed(:services, with: &Onvif.Device.Service.changeset/2) |> validate_required(@required) end @@ -235,7 +238,7 @@ defmodule Onvif.Device do defp get_date_time(device) do with {:ok, res} <- Onvif.Devices.GetSystemDateAndTime.request(device) do - updated_device = %{device | time_diff_from_system_secs: res.current_diff, ntp: res.ntp} + updated_device = %{device | time_diff_from_system_secs: res.current_diff, ntp: res.date_time_type, system_date_time: res } {:ok, updated_device} end end diff --git a/lib/devices/devices.ex b/lib/devices/devices.ex index 0bd567e..8262a38 100644 --- a/lib/devices/devices.ex +++ b/lib/devices/devices.ex @@ -26,7 +26,22 @@ defmodule Onvif.Devices do |> parse_response(operation) end + def request(%Device{} = device, args, operation) do + content = generate_content(operation, args) + soap_action = operation.soap_action() + + device + |> Onvif.API.client() + |> Tesla.request( + method: :post, + headers: [{"Content-Type", "application/soap+xml"}, {"SOAPAction", soap_action}], + body: %Onvif.Request{content: content, namespaces: @namespaces} + ) + |> parse_response(operation) + end + defp generate_content(operation), do: operation.request_body() + defp generate_content(operation, args), do: apply(operation, :request_body, args) defp parse_response({:ok, %{status: 200, body: body}}, operation) do operation.response(body) From 7376aa8219608de0defc2078151a0b9d0c9ad2b9 Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Mon, 8 Jul 2024 21:59:28 +0100 Subject: [PATCH 03/20] #10471 Update GetSystemDateAndTime --- lib/devices/get_system_date_and_time.ex | 56 +++++-------------------- 1 file changed, 10 insertions(+), 46 deletions(-) diff --git a/lib/devices/get_system_date_and_time.ex b/lib/devices/get_system_date_and_time.ex index 2cad683..eccd3a3 100644 --- a/lib/devices/get_system_date_and_time.ex +++ b/lib/devices/get_system_date_and_time.ex @@ -18,51 +18,15 @@ defmodule Onvif.Devices.GetSystemDateAndTime do 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/tds:GetSystemDateAndTimeResponse/tds:SystemDateAndTime" - |> add_namespace("s", "http://www.w3.org/2003/05/soap-envelope") - |> add_namespace("tds", "http://www.onvif.org/ver10/device/wsdl"), - hour: - ~x"./tt:UTCDateTime/tt:Time/tt:Hour/text()"i - |> add_namespace("tt", "http://www.onvif.org/ver10/schema"), - minute: - ~x"./tt:UTCDateTime/tt:Time/tt:Minute/text()"i - |> add_namespace("tt", "http://www.onvif.org/ver10/schema"), - second: - ~x"./tt:UTCDateTime/tt:Time/tt:Second/text()"i - |> add_namespace("tt", "http://www.onvif.org/ver10/schema"), - year: - ~x"./tt:UTCDateTime/tt:Date/tt:Year/text()"i - |> add_namespace("tt", "http://www.onvif.org/ver10/schema"), - month: - ~x"./tt:UTCDateTime/tt:Date/tt:Month/text()"i - |> add_namespace("tt", "http://www.onvif.org/ver10/schema"), - day: - ~x"./tt:UTCDateTime/tt:Date/tt:Day/text()"i - |> add_namespace("tt", "http://www.onvif.org/ver10/schema"), - timezone: - ~x"./tt:Timezone/tt:TZ/text()"s - |> add_namespace("tt", "http://www.onvif.org/ver10/schema"), - ntp: - ~x"./tt:DateTimeType/text()"s - |> add_namespace("tt", "http://www.onvif.org/ver10/schema") - ) - - current = DateTime.utc_now() - {:ok, date} = Date.new(parsed_result.year, parsed_result.month, parsed_result.day) - {:ok, time} = Time.new(parsed_result.hour, parsed_result.minute, parsed_result.second) - {:ok, datetime} = DateTime.new(date, time) - diff_between_device = DateTime.diff(datetime, current) - - {:ok, - %Onvif.Devices.SystemDateAndTime{ - datetime: datetime, - ntp: parsed_result.ntp, - current_diff: diff_between_device - }} + xml_response_body + |> parse(namespace_conformant: true, quiet: true) + |> xpath( + ~x"//s:Envelope/s:Body/tds:GetSystemDateAndTimeResponse/tds:SystemDateAndTime"e + |> 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") + ) + |> Onvif.Devices.SystemDateAndTime.parse() + |> Onvif.Devices.SystemDateAndTime.to_struct() end end From 352e9b39008ab3deec7b38c956885a8a9a802341 Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Mon, 8 Jul 2024 21:59:59 +0100 Subject: [PATCH 04/20] #10471 Create SetSystemDateAndTime --- lib/devices/set_system_date_and_time.ex | 59 +++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 lib/devices/set_system_date_and_time.ex diff --git a/lib/devices/set_system_date_and_time.ex b/lib/devices/set_system_date_and_time.ex new file mode 100644 index 0000000..12c7216 --- /dev/null +++ b/lib/devices/set_system_date_and_time.ex @@ -0,0 +1,59 @@ +defmodule Onvif.Devices.SetSystemDateAndTime do + import SweetXml + import XmlBuilder + + alias Onvif.Device + alias Onvif.Devices.SystemDateAndTime + + def soap_action, do: "http://www.onvif.org/ver10/device/wsdl/SetSystemDateAndTime" + + @spec request(Device.t(), list) :: {:ok, any} | {:error, map()} + def request(device, args) do + Onvif.Devices.request(device, args, __MODULE__) + end + + def request_body(%SystemDateAndTime{} = system_date_time) do + element(:"s:Body", [ + element(:"tds:SetSystemDateAndTime", [ + element(:"tds:DateAndTime", system_date_time.date_time_type ), + element(:"tds:DaylightSavings", system_date_time.daylight_savings ), + element( + :"tds:TimeZone", + [ + element(:"tt:TZ", system_date_time.time_zone.tz ) + ] + ), + + element( + :"tds:UTCDateTime", + [ + element(:"tt:Time", [ + element(:"tt:Hour", system_date_time.utc_date_time.time.hour ), + element(:"tt:Minute", system_date_time.utc_date_time.time.minute ), + element(:"tt:Second", system_date_time.utc_date_time.time.second ) + ]), + element(:"tt:Date", [ + element(:"tt:Year", system_date_time.utc_date_time.date.year ), + element(:"tt:Month", system_date_time.utc_date_time.date.month ), + element(:"tt:Day", system_date_time.utc_date_time.date.day ) + ]) + ] + ) + + ]) + ]) + end + + def response(xml_response_body) do + res = + xml_response_body + |> parse(namespace_conformant: true, quiet: true) + |> xpath( + ~x"//s:Envelope/s:Body/tds:SetSystemDateAndTimeResponse/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 From 62052bf26dab29168335ba3483830284167c7a07 Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Tue, 9 Jul 2024 15:10:39 +0100 Subject: [PATCH 05/20] #10471 Update set_time opetion | WIP --- lib/devices/set_system_date_and_time.ex | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/devices/set_system_date_and_time.ex b/lib/devices/set_system_date_and_time.ex index 12c7216..41433bc 100644 --- a/lib/devices/set_system_date_and_time.ex +++ b/lib/devices/set_system_date_and_time.ex @@ -13,6 +13,13 @@ defmodule Onvif.Devices.SetSystemDateAndTime do end def request_body(%SystemDateAndTime{} = system_date_time) do + request_body([config: system_date_time, set_time?: false]) + end + + #def request_body(%SystemDateAndTime{} = system_date_time, opts) do + def request_body([config: %SystemDateAndTime{} = system_date_time] = opts) do + IO.inspect(opts) + set_time? = Keyword.get(opts, :set_time?, false) element(:"s:Body", [ element(:"tds:SetSystemDateAndTime", [ element(:"tds:DateAndTime", system_date_time.date_time_type ), @@ -23,7 +30,13 @@ defmodule Onvif.Devices.SetSystemDateAndTime do element(:"tt:TZ", system_date_time.time_zone.tz ) ] ), + List.flatten([utc_date_time_element(system_date_time, set_time?)]) + ]) + ]) + end + def utc_date_time_element(system_date_time, false) do [] end + def utc_date_time_element(system_date_time, true) do element( :"tds:UTCDateTime", [ @@ -39,9 +52,6 @@ defmodule Onvif.Devices.SetSystemDateAndTime do ]) ] ) - - ]) - ]) end def response(xml_response_body) do From 08b3e653cbab67a41aa5cced78483f90848d2994 Mon Sep 17 00:00:00 2001 From: Logeshwaran Murugesan <9105503+waranlogesh@users.noreply.github.com> Date: Tue, 9 Jul 2024 19:53:35 +0530 Subject: [PATCH 06/20] Change signature --- lib/device.ex | 8 +++- lib/devices/devices.ex | 2 +- lib/devices/set_system_date_and_time.ex | 51 +++++++++++++------------ lib/devices/system_date_and_time.ex | 48 ++++++++++++++--------- lib/media/ver10/service_capabilities.ex | 2 +- 5 files changed, 66 insertions(+), 45 deletions(-) diff --git a/lib/device.ex b/lib/device.ex index a329bf5..079add4 100644 --- a/lib/device.ex +++ b/lib/device.ex @@ -238,7 +238,13 @@ defmodule Onvif.Device do defp get_date_time(device) do with {:ok, res} <- Onvif.Devices.GetSystemDateAndTime.request(device) do - updated_device = %{device | time_diff_from_system_secs: res.current_diff, ntp: res.date_time_type, system_date_time: res } + updated_device = %{ + device + | time_diff_from_system_secs: res.current_diff, + ntp: res.date_time_type, + system_date_time: res + } + {:ok, updated_device} end end diff --git a/lib/devices/devices.ex b/lib/devices/devices.ex index 8262a38..88485df 100644 --- a/lib/devices/devices.ex +++ b/lib/devices/devices.ex @@ -41,7 +41,7 @@ defmodule Onvif.Devices do end defp generate_content(operation), do: operation.request_body() - defp generate_content(operation, args), do: apply(operation, :request_body, args) + defp generate_content(operation, args), do: operation.request_body(args) defp parse_response({:ok, %{status: 200, body: body}}, operation) do operation.response(body) diff --git a/lib/devices/set_system_date_and_time.ex b/lib/devices/set_system_date_and_time.ex index 41433bc..6fa4931 100644 --- a/lib/devices/set_system_date_and_time.ex +++ b/lib/devices/set_system_date_and_time.ex @@ -12,22 +12,19 @@ defmodule Onvif.Devices.SetSystemDateAndTime do Onvif.Devices.request(device, args, __MODULE__) end - def request_body(%SystemDateAndTime{} = system_date_time) do - request_body([config: system_date_time, set_time?: false]) - end - - #def request_body(%SystemDateAndTime{} = system_date_time, opts) do - def request_body([config: %SystemDateAndTime{} = system_date_time] = opts) do + # def request_body(%SystemDateAndTime{} = system_date_time, opts) do + def request_body([config: %SystemDateAndTime{} = system_date_time, set_time?: set_time?] = opts) do IO.inspect(opts) set_time? = Keyword.get(opts, :set_time?, false) + element(:"s:Body", [ element(:"tds:SetSystemDateAndTime", [ - element(:"tds:DateAndTime", system_date_time.date_time_type ), - element(:"tds:DaylightSavings", system_date_time.daylight_savings ), + element(:"tds:DateAndTime", system_date_time.date_time_type), + element(:"tds:DaylightSavings", system_date_time.daylight_savings), element( :"tds:TimeZone", [ - element(:"tt:TZ", system_date_time.time_zone.tz ) + element(:"tt:TZ", system_date_time.time_zone.tz) ] ), List.flatten([utc_date_time_element(system_date_time, set_time?)]) @@ -35,23 +32,26 @@ defmodule Onvif.Devices.SetSystemDateAndTime do ]) end - def utc_date_time_element(system_date_time, false) do [] end + def utc_date_time_element(system_date_time, false) do + [] + end + def utc_date_time_element(system_date_time, true) do - element( - :"tds:UTCDateTime", - [ - element(:"tt:Time", [ - element(:"tt:Hour", system_date_time.utc_date_time.time.hour ), - element(:"tt:Minute", system_date_time.utc_date_time.time.minute ), - element(:"tt:Second", system_date_time.utc_date_time.time.second ) - ]), - element(:"tt:Date", [ - element(:"tt:Year", system_date_time.utc_date_time.date.year ), - element(:"tt:Month", system_date_time.utc_date_time.date.month ), - element(:"tt:Day", system_date_time.utc_date_time.date.day ) - ]) - ] - ) + element( + :"tds:UTCDateTime", + [ + element(:"tt:Time", [ + element(:"tt:Hour", system_date_time.utc_date_time.time.hour), + element(:"tt:Minute", system_date_time.utc_date_time.time.minute), + element(:"tt:Second", system_date_time.utc_date_time.time.second) + ]), + element(:"tt:Date", [ + element(:"tt:Year", system_date_time.utc_date_time.date.year), + element(:"tt:Month", system_date_time.utc_date_time.date.month), + element(:"tt:Day", system_date_time.utc_date_time.date.day) + ]) + ] + ) end def response(xml_response_body) do @@ -64,6 +64,7 @@ defmodule Onvif.Devices.SetSystemDateAndTime do |> 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/lib/devices/system_date_and_time.ex b/lib/devices/system_date_and_time.ex index 4397d02..40c80c5 100644 --- a/lib/devices/system_date_and_time.ex +++ b/lib/devices/system_date_and_time.ex @@ -9,10 +9,10 @@ defmodule Onvif.Devices.SystemDateAndTime do @optional [] embedded_schema do - field :date_time_type, Ecto.Enum, values: [manual: "Manual", ntp: "NTP"] - field :daylight_savings, :boolean, default: true - field :datetime, :utc_datetime - field :current_diff, :integer + field(:date_time_type, Ecto.Enum, values: [manual: "Manual", ntp: "NTP"]) + field(:daylight_savings, :boolean, default: true) + field(:datetime, :utc_datetime) + field(:current_diff, :integer) embeds_one :time_zone, TimeZone, primary_key: false, on_replace: :update do @derive Jason.Encoder @@ -62,16 +62,17 @@ defmodule Onvif.Devices.SystemDateAndTime do def parse(doc) do xmap( doc, - date_time_type: ~x"./tt:DateTimeType/text()"so, - daylight_savings: ~x"./tt:DaylightSavings/text()"so, - time_zone: ~x"./tt:TimeZone"eo |> transform_by(&parse_time_zone/1), - utc_date_time: ~x"./tt:UTCDateTime"eo |> transform_by(&parse_date_time/1), - local_date_time: ~x"./tt:LocalDateTime"eo |> transform_by(&parse_date_time/1) + date_time_type: ~x"./tt:DateTimeType/text()"so, + daylight_savings: ~x"./tt:DaylightSavings/text()"so, + time_zone: ~x"./tt:TimeZone"eo |> transform_by(&parse_time_zone/1), + utc_date_time: ~x"./tt:UTCDateTime"eo |> transform_by(&parse_date_time/1), + local_date_time: ~x"./tt:LocalDateTime"eo |> transform_by(&parse_date_time/1) ) end defp parse_time_zone([]), do: nil defp parse_time_zone(nil), do: nil + defp parse_time_zone(doc) do xmap( doc, @@ -81,16 +82,18 @@ defmodule Onvif.Devices.SystemDateAndTime do defp parse_date_time([]), do: nil defp parse_date_time(nil), do: nil + defp parse_date_time(doc) do xmap( doc, time: ~x"./tt:Time"eo |> transform_by(&parse_time/1), - date: ~x"./tt:Date"eo |> transform_by(&parse_date/1), + date: ~x"./tt:Date"eo |> transform_by(&parse_date/1) ) end defp parse_time([]), do: nil defp parse_time(nil), do: nil + defp parse_time(doc) do xmap( doc, @@ -99,8 +102,10 @@ defmodule Onvif.Devices.SystemDateAndTime do second: ~x"./tt:Second/text()"i ) end + defp parse_date([]), do: nil defp parse_date(nil), do: nil + defp parse_date(doc) do xmap( doc, @@ -117,7 +122,7 @@ defmodule Onvif.Devices.SystemDateAndTime do end @spec to_json(%__MODULE__{}) :: - {:error, + {:error, %{ :__exception__ => any, :__struct__ => Jason.EncodeError | Protocol.UndefinedError, @@ -128,7 +133,6 @@ defmodule Onvif.Devices.SystemDateAndTime do Jason.encode(schema) end - def changeset(module, attrs) do module |> cast(attrs, @required ++ @optional) @@ -142,10 +146,16 @@ defmodule Onvif.Devices.SystemDateAndTime do defp put_datetime(changeset) do case get_field(changeset, :utc_date_time) do - nil -> changeset + nil -> + changeset + utc_date_time -> - {:ok, date} = Date.new(utc_date_time.date.year, utc_date_time.date.month, utc_date_time.date.day) - {:ok, time} = Time.new(utc_date_time.time.hour, utc_date_time.time.minute, utc_date_time.time.second) + {:ok, date} = + Date.new(utc_date_time.date.year, utc_date_time.date.month, utc_date_time.date.day) + + {:ok, time} = + Time.new(utc_date_time.time.hour, utc_date_time.time.minute, utc_date_time.time.second) + {:ok, datetime} = DateTime.new(date, time) put_change(changeset, :datetime, datetime) end @@ -153,7 +163,9 @@ defmodule Onvif.Devices.SystemDateAndTime do defp put_current_diff(changeset) do case get_field(changeset, :datetime) do - nil -> changeset + nil -> + changeset + datetime -> current = DateTime.utc_now() diff = DateTime.diff(datetime, current) @@ -164,16 +176,18 @@ defmodule Onvif.Devices.SystemDateAndTime do defp time_zone_changeset(module, attrs) do cast(module, attrs, [:tz]) end + defp date_time_changeset(module, attrs) do cast(module, attrs, []) |> cast_embed(:date, with: &date_changeset/2) |> cast_embed(:time, with: &time_changeset/2) end + defp date_changeset(module, attrs) do cast(module, attrs, [:year, :month, :day]) end + defp time_changeset(module, attrs) do cast(module, attrs, [:hour, :minute, :second]) end - end diff --git a/lib/media/ver10/service_capabilities.ex b/lib/media/ver10/service_capabilities.ex index 5d4d9b3..c3f9578 100644 --- a/lib/media/ver10/service_capabilities.ex +++ b/lib/media/ver10/service_capabilities.ex @@ -24,7 +24,7 @@ defmodule Onvif.Media.Ver10.ServiceCapabilities do field(:temporary_osd_text, :boolean, default: false) field(:exi_compression, :boolean, default: false) - embeds_one :profile_capabilities, ProfileCapabilities, primary_key: false, on_replace: :update do + embeds_one :profile_capabilities, ProfileCapailities, primary_key: false, on_replace: :update do @derive Jason.Encoder field(:maximum_number_of_profiles, :integer) end From 28121893e3aeb9fd6d8f3af55e9ac6442004a0fe Mon Sep 17 00:00:00 2001 From: Logeshwaran Murugesan <9105503+waranlogesh@users.noreply.github.com> Date: Tue, 9 Jul 2024 19:57:11 +0530 Subject: [PATCH 07/20] Undo media changes --- lib/media/ver10/service_capabilities.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/media/ver10/service_capabilities.ex b/lib/media/ver10/service_capabilities.ex index c3f9578..5d4d9b3 100644 --- a/lib/media/ver10/service_capabilities.ex +++ b/lib/media/ver10/service_capabilities.ex @@ -24,7 +24,7 @@ defmodule Onvif.Media.Ver10.ServiceCapabilities do field(:temporary_osd_text, :boolean, default: false) field(:exi_compression, :boolean, default: false) - embeds_one :profile_capabilities, ProfileCapailities, primary_key: false, on_replace: :update do + embeds_one :profile_capabilities, ProfileCapabilities, primary_key: false, on_replace: :update do @derive Jason.Encoder field(:maximum_number_of_profiles, :integer) end From 05eae73e3c34c15c243df351cb074c48e5bc6e92 Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Tue, 9 Jul 2024 15:43:15 +0100 Subject: [PATCH 08/20] #10471 fix all function signatures --- lib/devices/set_system_date_and_time.ex | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/devices/set_system_date_and_time.ex b/lib/devices/set_system_date_and_time.ex index 6fa4931..d3f7daa 100644 --- a/lib/devices/set_system_date_and_time.ex +++ b/lib/devices/set_system_date_and_time.ex @@ -12,11 +12,11 @@ defmodule Onvif.Devices.SetSystemDateAndTime do Onvif.Devices.request(device, args, __MODULE__) end - # def request_body(%SystemDateAndTime{} = system_date_time, opts) do - def request_body([config: %SystemDateAndTime{} = system_date_time, set_time?: set_time?] = opts) do - IO.inspect(opts) - set_time? = Keyword.get(opts, :set_time?, false) + def request_body([config: %SystemDateAndTime{} = system_date_time] = opts) do + request_body([config: system_date_time, set_time?: false]) + end + def request_body([config: %SystemDateAndTime{} = system_date_time, set_time?: set_time?] = opts) do element(:"s:Body", [ element(:"tds:SetSystemDateAndTime", [ element(:"tds:DateAndTime", system_date_time.date_time_type), @@ -32,9 +32,7 @@ defmodule Onvif.Devices.SetSystemDateAndTime do ]) end - def utc_date_time_element(system_date_time, false) do - [] - end + def utc_date_time_element(_system_date_time, false), do: [] def utc_date_time_element(system_date_time, true) do element( From 272c1de3fa267713d618496786c54bc910c09a15 Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Tue, 9 Jul 2024 15:49:53 +0100 Subject: [PATCH 09/20] #10471 after running mix format --- lib/devices/set_system_date_and_time.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/devices/set_system_date_and_time.ex b/lib/devices/set_system_date_and_time.ex index d3f7daa..f64a8a0 100644 --- a/lib/devices/set_system_date_and_time.ex +++ b/lib/devices/set_system_date_and_time.ex @@ -13,7 +13,7 @@ defmodule Onvif.Devices.SetSystemDateAndTime do end def request_body([config: %SystemDateAndTime{} = system_date_time] = opts) do - request_body([config: system_date_time, set_time?: false]) + request_body(config: system_date_time, set_time?: false) end def request_body([config: %SystemDateAndTime{} = system_date_time, set_time?: set_time?] = opts) do From 7ecf27a4817bbbfb8b4456fb050850396ed498da Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Tue, 9 Jul 2024 20:02:04 +0100 Subject: [PATCH 10/20] #10471 refactor base structure --- lib/devices/devices.ex | 17 +++++------------ lib/devices/set_system_date_and_time.ex | 4 ++-- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/lib/devices/devices.ex b/lib/devices/devices.ex index 88485df..1a4169a 100644 --- a/lib/devices/devices.ex +++ b/lib/devices/devices.ex @@ -14,27 +14,20 @@ defmodule Onvif.Devices do @spec request(Device.t(), module()) :: {:ok, any} | {:error, map()} def request(%Device{} = device, operation) do content = generate_content(operation) - soap_action = operation.soap_action() - - device - |> Onvif.API.client() - |> Tesla.request( - method: :post, - headers: [{"Content-Type", "application/soap+xml"}, {"SOAPAction", soap_action}], - body: %Onvif.Request{content: content, namespaces: @namespaces} - ) - |> parse_response(operation) + do_request(device, operation, content) end def request(%Device{} = device, args, operation) do content = generate_content(operation, args) - soap_action = operation.soap_action() + do_request(device, operation, content) + end + defp do_request(device, operation, content) do device |> Onvif.API.client() |> Tesla.request( method: :post, - headers: [{"Content-Type", "application/soap+xml"}, {"SOAPAction", soap_action}], + headers: [{"Content-Type", "application/soap+xml"}, {"SOAPAction", operation.soap_action()}], body: %Onvif.Request{content: content, namespaces: @namespaces} ) |> parse_response(operation) diff --git a/lib/devices/set_system_date_and_time.ex b/lib/devices/set_system_date_and_time.ex index f64a8a0..e4e7376 100644 --- a/lib/devices/set_system_date_and_time.ex +++ b/lib/devices/set_system_date_and_time.ex @@ -12,11 +12,11 @@ defmodule Onvif.Devices.SetSystemDateAndTime do Onvif.Devices.request(device, args, __MODULE__) end - def request_body([config: %SystemDateAndTime{} = system_date_time] = opts) do + def request_body(config: %SystemDateAndTime{} = system_date_time) do request_body(config: system_date_time, set_time?: false) end - def request_body([config: %SystemDateAndTime{} = system_date_time, set_time?: set_time?] = opts) do + def request_body(config: %SystemDateAndTime{} = system_date_time, set_time?: set_time?) do element(:"s:Body", [ element(:"tds:SetSystemDateAndTime", [ element(:"tds:DateAndTime", system_date_time.date_time_type), From bb4e6bc1e7afedf3bf4f55dad94bcbdd7b69a8c9 Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Tue, 9 Jul 2024 22:12:22 +0100 Subject: [PATCH 11/20] #10471 update to work on axis --- lib/devices/devices.ex | 3 ++- lib/devices/set_system_date_and_time.ex | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/devices/devices.ex b/lib/devices/devices.ex index 1a4169a..1ed9d2c 100644 --- a/lib/devices/devices.ex +++ b/lib/devices/devices.ex @@ -8,7 +8,8 @@ defmodule Onvif.Devices do alias Onvif.Device @namespaces [ - "xmlns:tds": "http://www.onvif.org/ver10/device/wsdl" + "xmlns:tds": "http://www.onvif.org/ver10/device/wsdl", + "xmlns:tt": "http://www.onvif.org/ver10/schema" ] @spec request(Device.t(), module()) :: {:ok, any} | {:error, map()} diff --git a/lib/devices/set_system_date_and_time.ex b/lib/devices/set_system_date_and_time.ex index e4e7376..71b3f2f 100644 --- a/lib/devices/set_system_date_and_time.ex +++ b/lib/devices/set_system_date_and_time.ex @@ -19,7 +19,13 @@ defmodule Onvif.Devices.SetSystemDateAndTime do def request_body(config: %SystemDateAndTime{} = system_date_time, set_time?: set_time?) do element(:"s:Body", [ element(:"tds:SetSystemDateAndTime", [ - element(:"tds:DateAndTime", system_date_time.date_time_type), + element( + :"tds:DateTimeType", + Keyword.fetch!( + Ecto.Enum.mappings(system_date_time.__struct__, :date_time_type), + system_date_time.date_time_type + ) + ), element(:"tds:DaylightSavings", system_date_time.daylight_savings), element( :"tds:TimeZone", From 4d772edc63e6c1517868573ab508555dfd3a007f Mon Sep 17 00:00:00 2001 From: Logeshwaran Murugesan <9105503+waranlogesh@users.noreply.github.com> Date: Wed, 10 Jul 2024 16:59:58 +0530 Subject: [PATCH 12/20] Remove redefied module warning --- lib/devices/system_date_and_time.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/devices/system_date_and_time.ex b/lib/devices/system_date_and_time.ex index 40c80c5..a22083c 100644 --- a/lib/devices/system_date_and_time.ex +++ b/lib/devices/system_date_and_time.ex @@ -37,7 +37,7 @@ defmodule Onvif.Devices.SystemDateAndTime do end end - embeds_one :local_date_time, UTCDateTime, primary_key: false, on_replace: :update do + embeds_one :local_date_time, LocalDateTime, primary_key: false, on_replace: :update do @derive Jason.Encoder embeds_one :time, Time, primary_key: false, on_replace: :update do From 117db60078271bc9975f92621bfd48c1840a8c8f Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Wed, 10 Jul 2024 17:05:36 +0100 Subject: [PATCH 13/20] #10471 add documentation --- lib/devices/set_system_date_and_time.ex | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/devices/set_system_date_and_time.ex b/lib/devices/set_system_date_and_time.ex index 71b3f2f..cd26239 100644 --- a/lib/devices/set_system_date_and_time.ex +++ b/lib/devices/set_system_date_and_time.ex @@ -1,4 +1,13 @@ defmodule Onvif.Devices.SetSystemDateAndTime do + @moduledoc """ + Module used to set the device system date and time as well as their configuration such as daylight saving and NTP or Manual update type on an ONVIF device. + If system time and date are set manually, the request shall include UTCDateTime. + A TimeZone token which is not formed according to the rules of IEEE 1003.1 section 8.3 is considered as invalid timezone. + The DayLightSavings flag should be set to true to activate any DST settings of the TimeZone string. Clear the DayLightSavings flag if the DST portion of the TimeZone settings should be ignored. + The configuration requires a %Onvif.Devices.SystemDateAndTime{} config and a bolean set_time? to manually change the time. It will be ignored if using NTP. + + Ref: https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl#op.SetSystemDateAndTime + """ import SweetXml import XmlBuilder From 9d96e882a64a0665ee1aeea61cdd79fe53f0e6f3 Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Thu, 11 Jul 2024 14:31:51 +0100 Subject: [PATCH 14/20] #10471 add tests --- .../fixture/get_system_date_and_time.xml | 38 +++++++++++++ .../devices/get_system_date_and_time_test.exs | 54 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 test/devices/fixture/get_system_date_and_time.xml create mode 100644 test/devices/get_system_date_and_time_test.exs diff --git a/test/devices/fixture/get_system_date_and_time.xml b/test/devices/fixture/get_system_date_and_time.xml new file mode 100644 index 0000000..a270fed --- /dev/null +++ b/test/devices/fixture/get_system_date_and_time.xml @@ -0,0 +1,38 @@ + + + + + + Manual + true + + BRT3 + + + + 19 + 49 + 6 + + + 2024 + 7 + 9 + + + + + 16 + 49 + 6 + + + 2024 + 7 + 9 + + + + + + \ No newline at end of file diff --git a/test/devices/get_system_date_and_time_test.exs b/test/devices/get_system_date_and_time_test.exs new file mode 100644 index 0000000..7b0ed41 --- /dev/null +++ b/test/devices/get_system_date_and_time_test.exs @@ -0,0 +1,54 @@ +defmodule Onvif.Devices.GetSystemDateAndTimeTest do + use ExUnit.Case, async: true + + @moduletag capture_log: true + + describe "GetSystemDateAndTime/1" do + test "should parse with correct values" do + xml_response = File.read!("test/devices/fixtures/get_system_date_and_time.xml") + + device = Onvif.Factory.device() + + Mimic.expect(Tesla, :request, fn _client, _opts -> + {:ok, %{status: 200, body: xml_response}} + end) + + {:ok, service_capabilities} = Onvif.Devices.GetSystemDateAndTime.request(device) + + assert service_capabilities == Onvif.Devices.SystemDateAndTime{ + current_diff: -572, + date_time_type: :manual, + datetime: ~U[2024-07-09 16:49:06Z], + daylight_savings: true, + local_date_time: %Onvif.Devices.SystemDateAndTime.UTCDateTime{ + date: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Date{ + day: 9, + month: 7, + year: 2024 + }, + time: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Time{ + hour: 19, + minute: 49, + second: 06 + } + }, + time_zone: %Onvif.Devices.SystemDateAndTime.TimeZone{ + tz: "BRT3BRST,M3.2.0/2,M11.1.0/2" + }, + utc_date_time: %Onvif.Devices.SystemDateAndTime.UTCDateTime{ + date: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Date{ + day: 9, + month: 7, + year: 2024 + }, + time: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Time{ + hour: 16, + minute: 49, + second: 06 + } + } + } + end + end + +end From 27dd3e3887ba558e5836e4309cb86cd58f44bacd Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Thu, 11 Jul 2024 14:41:31 +0100 Subject: [PATCH 15/20] #10471 fixing test --- test/devices/get_system_date_and_time_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/devices/get_system_date_and_time_test.exs b/test/devices/get_system_date_and_time_test.exs index 7b0ed41..c1c3c27 100644 --- a/test/devices/get_system_date_and_time_test.exs +++ b/test/devices/get_system_date_and_time_test.exs @@ -15,7 +15,7 @@ defmodule Onvif.Devices.GetSystemDateAndTimeTest do {:ok, service_capabilities} = Onvif.Devices.GetSystemDateAndTime.request(device) - assert service_capabilities == Onvif.Devices.SystemDateAndTime{ + assert service_capabilities == %Onvif.Devices.SystemDateAndTime{ current_diff: -572, date_time_type: :manual, datetime: ~U[2024-07-09 16:49:06Z], From ade96e1dffbbb5859f45237b6767238b1b0cf9a3 Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Thu, 11 Jul 2024 14:48:31 +0100 Subject: [PATCH 16/20] #10471 fixing tests --- .../get_system_date_and_time.xml | 0 .../devices/get_system_date_and_time_test.exs | 65 +++++++++---------- 2 files changed, 32 insertions(+), 33 deletions(-) rename test/devices/{fixture => fixtures}/get_system_date_and_time.xml (100%) diff --git a/test/devices/fixture/get_system_date_and_time.xml b/test/devices/fixtures/get_system_date_and_time.xml similarity index 100% rename from test/devices/fixture/get_system_date_and_time.xml rename to test/devices/fixtures/get_system_date_and_time.xml diff --git a/test/devices/get_system_date_and_time_test.exs b/test/devices/get_system_date_and_time_test.exs index c1c3c27..a68fce3 100644 --- a/test/devices/get_system_date_and_time_test.exs +++ b/test/devices/get_system_date_and_time_test.exs @@ -16,39 +16,38 @@ defmodule Onvif.Devices.GetSystemDateAndTimeTest do {:ok, service_capabilities} = Onvif.Devices.GetSystemDateAndTime.request(device) assert service_capabilities == %Onvif.Devices.SystemDateAndTime{ - current_diff: -572, - date_time_type: :manual, - datetime: ~U[2024-07-09 16:49:06Z], - daylight_savings: true, - local_date_time: %Onvif.Devices.SystemDateAndTime.UTCDateTime{ - date: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Date{ - day: 9, - month: 7, - year: 2024 - }, - time: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Time{ - hour: 19, - minute: 49, - second: 06 - } - }, - time_zone: %Onvif.Devices.SystemDateAndTime.TimeZone{ - tz: "BRT3BRST,M3.2.0/2,M11.1.0/2" - }, - utc_date_time: %Onvif.Devices.SystemDateAndTime.UTCDateTime{ - date: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Date{ - day: 9, - month: 7, - year: 2024 - }, - time: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Time{ - hour: 16, - minute: 49, - second: 06 - } - } - } + current_diff: -572, + date_time_type: :manual, + datetime: ~U[2024-07-09 16:49:06Z], + daylight_savings: true, + local_date_time: %Onvif.Devices.SystemDateAndTime.UTCDateTime{ + date: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Date{ + day: 9, + month: 7, + year: 2024 + }, + time: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Time{ + hour: 19, + minute: 49, + second: 06 + } + }, + time_zone: %Onvif.Devices.SystemDateAndTime.TimeZone{ + tz: "BRT3BRST,M3.2.0/2,M11.1.0/2" + }, + utc_date_time: %Onvif.Devices.SystemDateAndTime.UTCDateTime{ + date: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Date{ + day: 9, + month: 7, + year: 2024 + }, + time: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Time{ + hour: 16, + minute: 49, + second: 06 + } + } + } end end - end From 7ecb033d95b9003b265ddb155e0e3e0625a0a149 Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Thu, 11 Jul 2024 14:52:13 +0100 Subject: [PATCH 17/20] #10471 fix test generated values --- test/devices/get_system_date_and_time_test.exs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/devices/get_system_date_and_time_test.exs b/test/devices/get_system_date_and_time_test.exs index a68fce3..f54cef7 100644 --- a/test/devices/get_system_date_and_time_test.exs +++ b/test/devices/get_system_date_and_time_test.exs @@ -16,9 +16,9 @@ defmodule Onvif.Devices.GetSystemDateAndTimeTest do {:ok, service_capabilities} = Onvif.Devices.GetSystemDateAndTime.request(device) assert service_capabilities == %Onvif.Devices.SystemDateAndTime{ - current_diff: -572, + current_diff: -151215, date_time_type: :manual, - datetime: ~U[2024-07-09 16:49:06Z], + datetime: ~U[2024-07-09 19:49:06Z], daylight_savings: true, local_date_time: %Onvif.Devices.SystemDateAndTime.UTCDateTime{ date: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Date{ @@ -29,11 +29,11 @@ defmodule Onvif.Devices.GetSystemDateAndTimeTest do time: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Time{ hour: 19, minute: 49, - second: 06 + second: 6 } }, time_zone: %Onvif.Devices.SystemDateAndTime.TimeZone{ - tz: "BRT3BRST,M3.2.0/2,M11.1.0/2" + tz: "BRT3" }, utc_date_time: %Onvif.Devices.SystemDateAndTime.UTCDateTime{ date: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Date{ @@ -44,7 +44,7 @@ defmodule Onvif.Devices.GetSystemDateAndTimeTest do time: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Time{ hour: 16, minute: 49, - second: 06 + second: 6 } } } From 4077b43325fec02ebda3bf1a3a63001d5bac9fd2 Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Thu, 11 Jul 2024 14:54:28 +0100 Subject: [PATCH 18/20] #10471 fix test generated values --- test/devices/get_system_date_and_time_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/devices/get_system_date_and_time_test.exs b/test/devices/get_system_date_and_time_test.exs index f54cef7..ace0fb1 100644 --- a/test/devices/get_system_date_and_time_test.exs +++ b/test/devices/get_system_date_and_time_test.exs @@ -16,7 +16,7 @@ defmodule Onvif.Devices.GetSystemDateAndTimeTest do {:ok, service_capabilities} = Onvif.Devices.GetSystemDateAndTime.request(device) assert service_capabilities == %Onvif.Devices.SystemDateAndTime{ - current_diff: -151215, + current_diff: -151435, date_time_type: :manual, datetime: ~U[2024-07-09 19:49:06Z], daylight_savings: true, From dbf5aaa69f34418dbb668f0d969c9679f13bd590 Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Thu, 11 Jul 2024 15:08:54 +0100 Subject: [PATCH 19/20] #10471 mock Datetime.now on tests --- test/devices/get_system_date_and_time_test.exs | 16 ++++++++++------ test/test_helper.exs | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/test/devices/get_system_date_and_time_test.exs b/test/devices/get_system_date_and_time_test.exs index ace0fb1..495fc98 100644 --- a/test/devices/get_system_date_and_time_test.exs +++ b/test/devices/get_system_date_and_time_test.exs @@ -13,21 +13,25 @@ defmodule Onvif.Devices.GetSystemDateAndTimeTest do {:ok, %{status: 200, body: xml_response}} end) + Mimic.expect(DateTime, :utc_now, fn -> + ~U[2024-07-09 20:00:00.227234Z] + end) + {:ok, service_capabilities} = Onvif.Devices.GetSystemDateAndTime.request(device) assert service_capabilities == %Onvif.Devices.SystemDateAndTime{ - current_diff: -151435, + current_diff: -654, date_time_type: :manual, datetime: ~U[2024-07-09 19:49:06Z], daylight_savings: true, - local_date_time: %Onvif.Devices.SystemDateAndTime.UTCDateTime{ - date: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Date{ + local_date_time: %Onvif.Devices.SystemDateAndTime.LocalDateTime{ + date: %Onvif.Devices.SystemDateAndTime.LocalDateTime.Date{ day: 9, month: 7, year: 2024 }, - time: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Time{ - hour: 19, + time: %Onvif.Devices.SystemDateAndTime.LocalDateTime.Time{ + hour: 16, minute: 49, second: 6 } @@ -42,7 +46,7 @@ defmodule Onvif.Devices.GetSystemDateAndTimeTest do year: 2024 }, time: %Onvif.Devices.SystemDateAndTime.UTCDateTime.Time{ - hour: 16, + hour: 19, minute: 49, second: 6 } diff --git a/test/test_helper.exs b/test/test_helper.exs index 54ba313..36825c7 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1,3 +1,4 @@ ExUnit.start() Mimic.copy(Tesla) +Mimic.copy(DateTime) From 1c960b5bfe9505fa21ccc59244f718e1732dc199 Mon Sep 17 00:00:00 2001 From: Paolo Oliveira Date: Thu, 11 Jul 2024 15:34:19 +0100 Subject: [PATCH 20/20] #10471 assert invalid test results --- .../invalid_system_date_and_time_response.xml | 2 ++ test/devices/get_system_date_and_time_test.exs | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 test/devices/fixtures/invalid_system_date_and_time_response.xml diff --git a/test/devices/fixtures/invalid_system_date_and_time_response.xml b/test/devices/fixtures/invalid_system_date_and_time_response.xml new file mode 100644 index 0000000..a967fba --- /dev/null +++ b/test/devices/fixtures/invalid_system_date_and_time_response.xml @@ -0,0 +1,2 @@ + +SOAP-ENV:Senderter:WellFormedWell-formed errorXML well-formed violation occurred \ No newline at end of file diff --git a/test/devices/get_system_date_and_time_test.exs b/test/devices/get_system_date_and_time_test.exs index 495fc98..31643db 100644 --- a/test/devices/get_system_date_and_time_test.exs +++ b/test/devices/get_system_date_and_time_test.exs @@ -53,5 +53,21 @@ defmodule Onvif.Devices.GetSystemDateAndTimeTest do } } end + + test "should return error when response is invalid" do + xml_response = File.read!("test/devices/fixtures/invalid_system_date_and_time_response.xml") + device = Onvif.Factory.device() + + Mimic.expect(Tesla, :request, fn _client, _opts -> + {:ok, %{status: 400, body: xml_response}} + end) + + {:error, %{status: status, reason: reason, response: response}} = + Onvif.Devices.GetSystemDateAndTime.request(device) + + assert status == 400 + assert reason == "Received 400 from Elixir.Onvif.Devices.GetSystemDateAndTime" + assert response == xml_response + end end end