Skip to content

Commit

Permalink
SetOSD (#77)
Browse files Browse the repository at this point in the history
  • Loading branch information
paoloo authored Aug 5, 2024
1 parent 56b9038 commit 4a83a1c
Show file tree
Hide file tree
Showing 5 changed files with 376 additions and 2 deletions.
18 changes: 16 additions & 2 deletions lib/media/ver10/osd.ex
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,22 @@ defmodule Onvif.Media.Ver10.OSD do
])
|> cast_embed(:font_color, with: &color_changeset/2)
|> cast_embed(:background_color, with: &color_changeset/2)
|> validate_inclusion(:date_format, ["M/d/yyyy", "MM/dd/yyyy", "dd/MM/yyyy", "yyyy/MM/dd", "yyyy-MM-dd", "dddd, MMMM dd, yyyy", "MMMM dd, yyyy", "dd MMMM, yyyy"])
|> validate_inclusion(:time_format, ["h:mm:ss tt", "hh:mm:ss tt", "H:mm:ss", "HH:mm:ss"])
|> validate_inclusion(:date_format, [
"M/d/yyyy",
"MM/dd/yyyy",
"dd/MM/yyyy",
"yyyy/MM/dd",
"yyyy-MM-dd",
"dddd, MMMM dd, yyyy",
"MMMM dd, yyyy",
"dd MMMM, yyyy"
])
|> validate_inclusion(:time_format, [
"h:mm:ss tt",
"hh:mm:ss tt",
"H:mm:ss",
"HH:mm:ss"
])
end

def color_changeset(module, attrs) do
Expand Down
162 changes: 162 additions & 0 deletions lib/media/ver10/set_osd.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
defmodule Onvif.Media.Ver10.SetOSD 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/SetOSD"

@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:SetOSD", [
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:SetOSDResponse/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
61 changes: 61 additions & 0 deletions test/media/ver10/fixtures/set_osd_response_error.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<env:Envelope
xmlns:env="http://www.w3.org/2003/05/soap-envelope"
xmlns:soapenc="http://www.w3.org/2003/05/soap-encoding"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tt="http://www.onvif.org/ver10/schema"
xmlns:tds="http://www.onvif.org/ver10/device/wsdl"
xmlns:trt="http://www.onvif.org/ver10/media/wsdl"
xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl"
xmlns:tev="http://www.onvif.org/ver10/events/wsdl"
xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl"
xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl"
xmlns:tst="http://www.onvif.org/ver10/storage/wsdl"
xmlns:ter="http://www.onvif.org/ver10/error"
xmlns:dn="http://www.onvif.org/ver10/network/wsdl"
xmlns:tns1="http://www.onvif.org/ver10/topics"
xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl"
xmlns:wsoap12="http://schemas.xmlsoap.org/wsdl/soap12"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery"
xmlns:wsadis="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2"
xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:wstop="http://docs.oasis-open.org/wsn/t-1"
xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
xmlns:wsntw="http://docs.oasis-open.org/wsn/bw-2"
xmlns:wsrf-rw="http://docs.oasis-open.org/wsrf/rw-2"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2"
xmlns:trc="http://www.onvif.org/ver10/recording/wsdl"
xmlns:tse="http://www.onvif.org/ver10/search/wsdl"
xmlns:trp="http://www.onvif.org/ver10/replay/wsdl"
xmlns:tnshik="http://www.hikvision.com/2011/event/topics"
xmlns:hikwsd="http://www.onvifext.com/onvif/ext/ver10/wsdl"
xmlns:hikxsd="http://www.onvifext.com/onvif/ext/ver10/schema"
xmlns:tas="http://www.onvif.org/ver10/advancedsecurity/wsdl"
xmlns:tr2="http://www.onvif.org/ver20/media/wsdl"
xmlns:axt="http://www.onvif.org/ver20/analytics">
<env:Body>
<env:Fault>
<env:Code>
<env:Value>env:Sender</env:Value>
<env:Subcode>
<env:Value>ter:InvalidArgVal</env:Value>
<env:Subcode>
<env:Value>ter:InvalidParameter</env:Value>
</env:Subcode>
</env:Subcode>
</env:Code>
<env:Reason>
<env:Text xml:lang="en">the parameter value is illegal</env:Text>
</env:Reason>
<env:Node>http://www.w3.org/2003/05/soap-envelope/node/ultimateReceiver</env:Node>
<env:Role>http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver</env:Role>
<env:Detail>
<env:Text>token is null</env:Text>
</env:Detail>
</env:Fault>
</env:Body>
</env:Envelope>
44 changes: 44 additions & 0 deletions test/media/ver10/fixtures/set_osd_response_success.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope
xmlns:env="http://www.w3.org/2003/05/soap-envelope"
xmlns:soapenc="http://www.w3.org/2003/05/soap-encoding"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tt="http://www.onvif.org/ver10/schema"
xmlns:tds="http://www.onvif.org/ver10/device/wsdl"
xmlns:trt="http://www.onvif.org/ver10/media/wsdl"
xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl"
xmlns:tev="http://www.onvif.org/ver10/events/wsdl"
xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl"
xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl"
xmlns:tst="http://www.onvif.org/ver10/storage/wsdl"
xmlns:ter="http://www.onvif.org/ver10/error"
xmlns:dn="http://www.onvif.org/ver10/network/wsdl"
xmlns:tns1="http://www.onvif.org/ver10/topics"
xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl"
xmlns:wsoap12="http://schemas.xmlsoap.org/wsdl/soap12"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery"
xmlns:wsadis="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2"
xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:wstop="http://docs.oasis-open.org/wsn/t-1"
xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
xmlns:wsntw="http://docs.oasis-open.org/wsn/bw-2"
xmlns:wsrf-rw="http://docs.oasis-open.org/wsrf/rw-2"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2"
xmlns:trc="http://www.onvif.org/ver10/recording/wsdl"
xmlns:tse="http://www.onvif.org/ver10/search/wsdl"
xmlns:trp="http://www.onvif.org/ver10/replay/wsdl"
xmlns:tnshik="http://www.hikvision.com/2011/event/topics"
xmlns:hikwsd="http://www.onvifext.com/onvif/ext/ver10/wsdl"
xmlns:hikxsd="http://www.onvifext.com/onvif/ext/ver10/schema"
xmlns:tas="http://www.onvif.org/ver10/advancedsecurity/wsdl"
xmlns:tr2="http://www.onvif.org/ver20/media/wsdl"
xmlns:axt="http://www.onvif.org/ver20/analytics">
<env:Body>
<trt:SetOSDResponse/>
</env:Body>
</env:Envelope>
93 changes: 93 additions & 0 deletions test/media/ver10/set_osd_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
defmodule Onvif.Media.Ver10.SetOSDTest do
alias Onvif.Media.Ver10.OSD
use ExUnit.Case, async: true

@moduletag capture_log: true

describe "SetOSDs/2" do
test "should update the OSD" do
xml_response = File.read!("test/media/ver10/fixtures/set_osd_response_success.xml")

device = Onvif.Factory.device()

Mimic.expect(Tesla, :request, fn _client, _opts ->
{:ok, %{status: 200, body: xml_response}}
end)

{:ok, osd} =
Onvif.Media.Ver10.SetOSD.request(device, [
%OSD{
image: nil,
position: %OSD.Position{
pos: %{x: "-1.000000", y: "0.866667"},
type: :custom
},
text_string: %OSD.TextString{
background_color: nil,
date_format: "MM/dd/yyyy",
font_color: %OSD.TextString.FontColor{
color: %{
colorspace: "http://www.onvif.org/ver10/colorspace/YCbCr",
x: "0.000000",
y: "0.000000",
z: "0.000000"
},
transparent: nil
},
font_size: 30,
is_persistent_text: nil,
plain_text: nil,
time_format: "HH:mm:ss",
type: :date_and_time
},
token: "OsdToken_101",
type: :text,
video_source_configuration_token: "VideoSourceToken"
}
])

assert osd == ""
end

test "shoud return an error" do
xml_response = File.read!("test/media/ver10/fixtures/set_osd_response_error.xml")

device = Onvif.Factory.device()

Mimic.expect(Tesla, :request, fn _client, _opts ->
{:ok, %{status: 500, body: xml_response}}
end)

{:error, error} =
Onvif.Media.Ver10.SetOSD.request(device, [
%OSD{
position: %OSD.Position{
pos: %{x: "-1.000000", y: "0.866667"},
type: :custom
},
text_string: %OSD.TextString{
date_format: "MM/dd/yyyy",
font_color: %OSD.TextString.FontColor{
color: %{
colorspace: "http://www.onvif.org/ver10/colorspace/YCbCr",
x: "0.000000",
y: "0.000000",
z: "0.000000"
},
transparent: nil
},
font_size: 30,
time_format: "HH:mm:ss",
type: :date_and_time
},
token: nil,
type: :text,
video_source_configuration_token: "VideoSourceToken"
}
])

assert error.reason == "Received 500 from Elixir.Onvif.Media.Ver10.SetOSD"
assert String.contains?(error.response, "token is null")
end
end
end

0 comments on commit 4a83a1c

Please sign in to comment.