defmodule AugieWeb.ServoLive do use Phoenix.LiveView alias Augie.Firmata alias Augie.Firmata.Commands alias Phoenix.PubSub @moduledoc false def mount(_params, %{"driver" => driver}, socket) do driver_name = String.capitalize(driver) driver = String.to_atom(driver) firmata_connected = Firmata.connected?() if connected?(socket) do PubSub.subscribe(Augie.PubSub, "command.servo_driver_enabled") PubSub.subscribe(Augie.PubSub, "command.servo_channel_enabled") PubSub.subscribe(Augie.PubSub, "command.servo_channel_position") PubSub.subscribe(Augie.PubSub, "serial_telemetry") if firmata_connected do Commands.servo_driver_enabled?(driver) for i <- 0..15 do Commands.servo_channel_enabled?(driver, i) Commands.servo_channel_position?(driver, i) end end end servos = 0..15 |> Enum.map(fn i -> {i, %{ id: i, name: "Servo #{i + 1}", enabled: false, value: 0 }} end) |> Enum.into(%{}) {:ok, assign(socket, driver: driver, driver_name: driver_name, switch_id: "#{driver}", state_known: false, enabled: false, servos: servos, connected: firmata_connected )} end def handle_info({:connected, false}, socket), do: {:noreply, assign(socket, connected: false)} def handle_info({:connected, _}, %{assigns: %{driver: driver}} = socket) do Commands.servo_driver_enabled?(driver) for i <- 0..15 do Commands.servo_channel_enabled?(driver, i) Commands.servo_channel_position?(driver, i) end {:noreply, assign(socket, connected: true)} end def handle_info( {:servo_driver_enabled, {driver, value}}, %{assigns: %{driver: driver}} = socket ) do {:noreply, assign(socket, state_known: true, enabled: value)} end def handle_info({:servo_driver_enabled, _}, socket), do: {:noreply, socket} def handle_info( {:servo_channel_enabled, {driver, channel, value}}, %{assigns: %{servos: servos, driver: driver}} = socket ) do servo = servos |> Map.get(channel) |> Map.put(:enabled, value) servos = servos |> Map.put(channel, servo) {:noreply, assign(socket, servos: servos)} end def handle_info({:servo_channel_enabled, _}, socket), do: {:noreply, socket} def handle_info( {:servo_channel_position, {driver, channel, value}}, %{assigns: %{servos: servos, driver: driver}} = socket ) do servo = servos |> Map.get(channel) |> Map.put(:value, value) servos = servos |> Map.put(channel, servo) {:noreply, assign(socket, servos: servos)} end def handle_info({:servo_channel_position, _}, socket), do: {:noreply, socket} def handle_event("enable-servos", _, %{assigns: %{driver: driver}} = socket) do Commands.servo_driver_enabled(driver, true) {:noreply, socket} end def handle_event("disable-servos", _, %{assigns: %{driver: driver}} = socket) do Commands.servo_driver_enabled(driver, false) {:noreply, socket} end def handle_event( "toggle-servo", %{"servo-id" => servo_no}, %{assigns: %{servos: servos, driver: driver}} = socket ) do servo_no = servo_no |> String.to_integer() servo = servos |> Map.get(servo_no) Commands.servo_channel_enabled(driver, servo_no, !servo.enabled) {:noreply, assign(socket, servos: servos)} end def handle_event( "set-servo", %{"servo-value" => degrees, "servo-id" => servo_no}, %{assigns: %{driver: driver}} = socket ) do degrees = degrees |> String.to_integer() servo_no = servo_no |> String.to_integer() Commands.servo_channel_position(driver, servo_no, degrees) {:noreply, socket} end def handle_event("set-servo", _, socket), do: {:noreply, socket} end