diff --git a/apps/ex_nvr_web/lib/ex_nvr_web/live/dashboard_live.ex b/apps/ex_nvr_web/lib/ex_nvr_web/live/dashboard_live.ex index 0aaf09ca..e2edcbe5 100644 --- a/apps/ex_nvr_web/lib/ex_nvr_web/live/dashboard_live.ex +++ b/apps/ex_nvr_web/lib/ex_nvr_web/live/dashboard_live.ex @@ -20,84 +20,7 @@ defmodule ExNVRWeb.DashboardLive do def render(assigns) do ~H""" -
-
- <.button - class="dark:bg-gray-700" - phx-click="handle-ptz" - phx-value-action="up" - > - <.icon name="hero-arrow-up" /> - -
-
- <.button - class="dark:bg-gray-700" - phx-click="handle-ptz" - phx-value-action="left" - > - <.icon name="hero-arrow-left" /> - -
-
- <.button - class="dark:bg-gray-700" - phx-click="handle-ptz" - phx-value-action="down" - > - <.icon name="hero-arrow-down" /> - -
-
- <.button - class="dark:bg-gray-700" - phx-click="handle-ptz" - phx-value-action="home" - > - <.icon name="hero-home" /> - -
-
- <.button - class="dark:bg-gray-700" - phx-click="handle-ptz" - phx-value-action="right" - > - <.icon name="hero-arrow-right" /> - -
-
- <.button - class="dark:bg-gray-700" - phx-click="handle-ptz" - phx-value-action="zoom-in" - > - <.icon name="hero-plus" /> - -
-
- <.button - class="dark:bg-gray-700" - phx-click="handle-ptz" - phx-value-action="zoom-out" - > - <.icon name="hero-minus" /> - -
-
- <.button - class="dark:bg-gray-700" - phx-click="handle-ptz" - phx-value-action="presets" - > - <.icon name="hero-bars-3" /> - -
-
-
+
You have no devices, you can create one <.link href={~p"/devices"} class="ml-2 dark:text-blue-600">here @@ -158,7 +81,7 @@ defmodule ExNVRWeb.DashboardLive do
-
+
+
+
+ <.button + class="dark:bg-gray-700" + phx-click="handle-ptz" + phx-value-action="up" + > + <.icon name="hero-arrow-up" /> + +
+
+ <.button + class="dark:bg-gray-700" + phx-click="handle-ptz" + phx-value-action="left" + > + <.icon name="hero-arrow-left" /> + +
+
+ <.button + class="dark:bg-gray-700" + phx-click="handle-ptz" + phx-value-action="down" + > + <.icon name="hero-arrow-down" /> + +
+
+ <.button + class="dark:bg-gray-700" + phx-click="handle-ptz" + phx-value-action="home" + > + <.icon name="hero-home" /> + +
+
+ <.button + class="dark:bg-gray-700" + phx-click="handle-ptz" + phx-value-action="right" + > + <.icon name="hero-arrow-right" /> + +
+
+ <.button + class="dark:bg-gray-700" + phx-click="handle-ptz" + phx-value-action="zoom-in" + > + <.icon name="hero-plus" /> + +
+
+ <.button + class="dark:bg-gray-700" + phx-click="handle-ptz" + phx-value-action="zoom-out" + > + <.icon name="hero-minus" /> + +
+
+ <.button + class="dark:bg-gray-700" + phx-click={JS.toggle(to: "#presets-sidebar")} + > + <.icon name="hero-bars-3" /> + +
+
+ """ end @@ -272,6 +304,7 @@ defmodule ExNVRWeb.DashboardLive do |> assign_runs() |> assign_timezone() |> maybe_push_stream_event(nil) + |> assign_presets() {:ok, assign(socket, start_date: nil, custom_duration: false)} end @@ -290,6 +323,7 @@ defmodule ExNVRWeb.DashboardLive do |> assign_runs() |> assign_timezone() |> maybe_push_stream_event(socket.assigns.start_date) + |> assign_presets() {:noreply, socket} end @@ -352,17 +386,19 @@ defmodule ExNVRWeb.DashboardLive do def handle_event("handle-ptz", %{"action" => action}, socket) do case action do - "presets" -> - socket - |> put_flash(:error, "Presets not implemented yet") - |> then(&{:noreply, &1}) - "home" -> home(socket) - mode -> ptz_action(socket, mode) + _ -> + socket + |> put_flash(:error, "Action not recognized!") + |> then(&{:noreply, &1}) end end + def handle_event("goto-preset", %{"token" => token}, socket) do + goto_preset(socket, token) + end + defp assign_devices(socket) do assign(socket, devices: Devices.list()) end @@ -431,6 +467,32 @@ defmodule ExNVRWeb.DashboardLive do assign(socket, footage_form: to_form(params, as: "footage")) end + defp assign_presets(socket, _device \\ nil) do + opts = get_onvif_access_info() + profile_token = opts[:profile_token] + body = %{"ProfileToken" => profile_token} + + case Onvif.call(opts[:url], :get_presets, body, opts) do + {:ok, %{GetPresetsResponse: presets}} -> + presets = + Keyword.values(presets) + |> Enum.map(fn preset -> + %{ + name: preset[:Name], + token: preset[:token] + } + end) + + socket + |> assign(presets: presets) + + {:error, _SoapResponse} -> + socket + |> put_flash(:error, "Couldn't load presets!") + |> assign(presets: []) + end + end + defp maybe_push_stream_event(socket, datetime) do cond do not connected?(socket) -> @@ -567,15 +629,6 @@ defmodule ExNVRWeb.DashboardLive do end end - defp get_onvif_access_info() do - opts = [ - username: "admin", - password: "Permanex1", - url: "wg6.evercam.io:20974/onvif/ptz_service/", - profile_token: "Profile_1" - ] - end - defp home(socket) do speed = [] opts = get_onvif_access_info() @@ -629,7 +682,7 @@ defmodule ExNVRWeb.DashboardLive do case Onvif.call(opts[:url], :stop, body, opts) do {:ok, _respose} -> socket - |> put_flash(:info, "Action succeeded") + |> put_flash(:info, "Move: #{mode} succeeded!") |> then(&{:noreply, &1}) {:error, _SoapResponse} -> @@ -640,11 +693,46 @@ defmodule ExNVRWeb.DashboardLive do {:error, _SoapResponse} -> socket - |> put_flash(:error, "Couldn't perform the requested action!") + |> put_flash(:error, "Couldn't perform the move: #{mode}!") |> then(&{:noreply, &1}) end end + defp goto_preset(socket, token, speed \\ []) do + opts = get_onvif_access_info() + profile_token = opts[:profile_token] + body = %{"ProfileToken" => profile_token, "PresetToken" => token} + + speed = + case pan_tilt_zoom_vector(speed) do + nil -> %{} + vector -> %{"Speed" => vector} + end + + body = Map.merge(body, speed) + + case Onvif.call(opts[:url], :goto_preset, body, opts) do + {:ok, _response} -> + socket + |> put_flash(:info, "Preset changed!") + |> then(&{:noreply, &1}) + + {:error, _SoapResponse} -> + socket + |> put_flash(:error, "Couldn't change preset!") + |> then(&{:noreply, &1}) + end + end + + defp get_onvif_access_info() do + opts = [ + username: "admin", + password: "Permanex1", + url: "wg6.evercam.io:20974/onvif/ptz_service/", + profile_token: "Profile_1" + ] + end + defp pan_tilt_zoom_vector(vector) do pan_tilt = case {vector[:x], vector[:y]} do