defmodule DashboardWeb.HostsLive do @moduledoc """ LiveView for real-time systant host monitoring. """ use DashboardWeb, :live_view alias Phoenix.PubSub @pubsub_topic "systant:hosts" @impl true def mount(_params, _session, socket) do if connected?(socket) do # Subscribe to host updates from MQTT PubSub.subscribe(Dashboard.PubSub, @pubsub_topic) end # Start with empty hosts - will be populated by MQTT hosts = %{} socket = socket |> assign(:hosts, hosts) |> assign(:page_title, "Systant Hosts") {:ok, socket} end @impl true def handle_info({:host_update, hostname, host_data}, socket) do require Logger Logger.info("LiveView received host update for #{hostname}: #{inspect(host_data)}") updated_hosts = Map.put(socket.assigns.hosts, hostname, host_data) {:noreply, assign(socket, :hosts, updated_hosts)} end @impl true def render(assigns) do ~H"""

<.icon name="hero-computer-desktop" class="h-4 w-4" /> Systant Host Monitor

Real-time system monitoring across all hosts

Live MQTT-powered dashboard showing statistics from all your systant-enabled hosts.

<%= if Enum.empty?(@hosts) do %>
<.icon name="hero-signal-slash" class="mx-auto h-12 w-12 text-zinc-400" />

No hosts detected

Waiting for systant hosts to publish data via MQTT...

<% else %> <%= for {hostname, host_data} <- @hosts do %> <.host_card hostname={hostname} data={host_data} /> <% end %> <% end %>
""" end attr :hostname, :string, required: true attr :data, :map, required: true defp host_card(assigns) do ~H"""
<.icon name="hero-server" class="h-5 w-5 text-green-600" />

<%= @hostname %>

Last seen: <%= format_datetime(@data["last_seen"]) %>

Online

Raw Data:

          <%= Jason.encode!(@data, pretty: true) %>
        
""" end defp format_datetime(%DateTime{} = datetime) do Calendar.strftime(datetime, "%Y-%m-%d %H:%M:%S UTC") end defp format_datetime(_), do: "Unknown" end