Skip to content

Commit

Permalink
CreateOSD (#80)
Browse files Browse the repository at this point in the history
* #10627 add create_osd and tests

* #10627 fix test

* #10627 handle error in 200 for dahua

* #10627 fix typo in GetOSD

* #10627 mix format
  • Loading branch information
paoloo authored Aug 6, 2024
1 parent 4a939dc commit 24af35f
Show file tree
Hide file tree
Showing 8 changed files with 419 additions and 42 deletions.
162 changes: 162 additions & 0 deletions lib/media/ver10/create_osd.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
defmodule Onvif.Media.Ver10.CreateOSD do
import SweetXml
import XmlBuilder

alias Onvif.Media.Ver10.OSD.TextString.FontColor
alias Onvif.Media.Ver10.OSD.TextString.BackgroundColor
alias Onvif.Media.Ver10.OSD.Image
alias Onvif.Device
alias Onvif.Media.Ver10.OSD

@spec soap_action :: String.t()
def soap_action, do: "http://www.onvif.org/ver10/media/wsdl/CreateOSD"

@spec request(Device.t(), list) :: {:ok, any} | {:error, map()}
def request(device, args),
do: Onvif.Media.Ver10.Media.request(device, args, __MODULE__)

def request_body(%OSD{} = osd) do
element(:"s:Body", [
element(:"trt:CreateOSD", [
element(:"trt:OSD", %{token: osd.token}, [
element(:"tt:VideoSourceConfigurationToken", osd.video_source_configuration_token),
element(
:"tt:Type",
Keyword.fetch!(Ecto.Enum.mappings(osd.__struct__, :type), osd.type)
),
element(:"tt:Position", [
element(
:"tt:Type",
Keyword.fetch!(
Ecto.Enum.mappings(osd.position.__struct__, :type),
osd.position.type
)
),
element(:"tt:Pos", %{x: osd.position.pos.x, y: osd.position.pos.y})
]),
gen_element_type(osd.type, osd)
])
])
])
end

defp gen_element_type(:text, osd) do
element(
:"tt:TextString",
[
element_is_persistent_text(osd.text_string.is_persistent_text),
element(
:"tt:Type",
Keyword.fetch!(
Ecto.Enum.mappings(osd.text_string.__struct__, :type),
osd.text_string.type
)
),
element_font_size(osd.text_string.font_size),
font_color_element(osd.text_string.font_color),
background_color_element(osd.text_string.background_color)
] ++ gen_text_type(osd.text_string.type, osd)
)
end

defp gen_element_type(:image, osd) do
image_element(osd.image)
end

defp gen_text_type(:plain, osd) do
[element_plain_text(osd.text_string.plain_text)]
end

defp gen_text_type(:date, osd) do
[element_date_format(osd.text_string.date_format)]
end

defp gen_text_type(:time, osd) do
[element_time_format(osd.text_string.time_format)]
end

defp gen_text_type(:date_and_time, osd) do
[
element_date_format(osd.text_string.date_format),
element_time_format(osd.text_string.time_format)
]
end

defp element_is_persistent_text(nil), do: []

defp element_is_persistent_text(is_persistent_text) do
element(:"tt:IsPersistentText", is_persistent_text)
end

defp element_date_format(nil), do: []

defp element_date_format(date_format) do
element(:"tt:DateFormat", date_format)
end

defp element_time_format(nil), do: []

defp element_time_format(time_format) do
element(:"tt:TimeFormat", time_format)
end

defp element_font_size(nil), do: []

defp element_font_size(font_size) do
element(:"tt:FontSize", font_size)
end

defp element_plain_text(nil), do: []

defp element_plain_text(plain_text) do
element(:"tt:PlainText", plain_text)
end

defp font_color_element(nil), do: []

defp font_color_element(%FontColor{} = font_color) do
element(:"tt:FontColor", [
element(:"tt:Color", %{
X: font_color.color.x,
Y: font_color.color.y,
Z: font_color.color.z,
Colorspace: font_color.color.colorspace
})
])
end

defp background_color_element(nil), do: []

defp background_color_element(%BackgroundColor{} = background_color) do
element(:BackgroundColor, [
element(:"tt:Color", %{
X: background_color.color.x,
Y: background_color.color.y,
Z: background_color.color.z,
Colorspace: background_color.color.colorspace
})
])
end

defp image_element(nil), do: []

defp image_element(%Image{} = image) do
element(:"tt:Image", [
element(:"tt:ImagePath", image.image_path)
])
end

def response(xml_response_body) do
res =
xml_response_body
|> parse(namespace_conformant: true, quiet: true)
|> xpath(
~x"//s:Envelope/s:Body/trt:CreateOSDResponse/trt:OSDToken/text()"s
|> add_namespace("s", "http://www.w3.org/2003/05/soap-envelope")
|> add_namespace("trt", "http://www.onvif.org/ver10/media/wsdl")
|> add_namespace("tt", "http://www.onvif.org/ver10/schema")
)

{:ok, res}
end
end
2 changes: 1 addition & 1 deletion lib/media/ver10/get_osd.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ defmodule Onvif.Media.Ver10.GetOSD do
def request_body(token) do
element(:"s:Body", [
element(:"trt:GetOSD", [
element(:"tt:OSDToken", token)
element(:"trt:OSDToken", token)
])
])
end
Expand Down
17 changes: 16 additions & 1 deletion lib/media/ver10/media.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ defmodule Onvif.Media.Ver10.Media do
https://www.onvif.org/ver10/media/wsdl/media.wsdl
"""
import SweetXml
require Logger

alias Onvif.Device
Expand Down Expand Up @@ -31,7 +32,21 @@ defmodule Onvif.Media.Ver10.Media do
defp generate_content(operation, args), do: apply(operation, :request_body, args)

defp parse_response({:ok, %{status: 200, body: body}}, operation) do
operation.response(body)
body
|> parse(namespace_conformant: true, quiet: true)
|> xpath(~x"//s:Envelope/s:Body/s:Fault"eo)
|> case do
nil ->
operation.response(body)

_ ->
{:error,
%{
status: 200,
reason: "Received a SOAP Fault from #{operation}",
response: body
}}
end
end

defp parse_response({:ok, %{status: status_code, body: body}}, operation)
Expand Down
Loading

0 comments on commit 24af35f

Please sign in to comment.