Fix dashboard MQTT connection and remove simulation code

- Replace SimpleMqtt simulation with real MqttSubscriber
- Fix String.split bug when handling MQTT topic parsing
- Use hostname-based client ID to avoid MQTT client conflicts
- Add process management tools (hivemind, just) to development environment

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
ryan 2025-08-03 19:39:59 -07:00
parent 400270ae52
commit c8e8e1dc24
4 changed files with 46 additions and 61 deletions

View File

@ -13,8 +13,8 @@ defmodule Dashboard.Application do
{Phoenix.PubSub, name: Dashboard.PubSub},
# Start the Finch HTTP client for sending emails
{Finch, name: Dashboard.Finch},
# Start simple MQTT subscriber
Dashboard.SimpleMqtt,
# Start real MQTT subscriber
Dashboard.MqttSubscriber,
# Start to serve requests, typically the last entry
DashboardWeb.Endpoint
]

View File

@ -19,17 +19,27 @@ defmodule Dashboard.MqttSubscriber do
@impl true
def init(_opts) do
# Start MQTT connection in a supervised way
{:ok, _pid} = Tortoise.Supervisor.start_child(
:dashboard_mqtt,
client_id: :dashboard_mqtt,
# Start MQTT connection directly with hostname-based client ID to avoid conflicts
{:ok, hostname} = :inet.gethostname()
client_id = "systant-dashboard-#{hostname}"
connection_opts = [
client_id: client_id,
server: {Tortoise.Transport.Tcp, host: "mqtt.home", port: 1883},
handler: {__MODULE__, []},
subscriptions: [{"systant/+/stats", 0}]
)
]
Logger.info("Dashboard MQTT subscriber started")
{:ok, %{hosts: %{}}}
case Tortoise.Connection.start_link(connection_opts) do
{:ok, _pid} ->
Logger.info("Dashboard MQTT subscriber connected successfully")
{:ok, %{hosts: %{}}}
{:error, {:already_started, _pid}} ->
Logger.info("Dashboard MQTT connection already exists, reusing")
{:ok, %{hosts: %{}}}
{:error, reason} ->
Logger.error("Failed to connect to MQTT broker: #{inspect(reason)}")
{:stop, reason}
end
end
@impl true
@ -43,11 +53,19 @@ defmodule Dashboard.MqttSubscriber do
end
# Tortoise handler callbacks
def connection(_status, _state), do: []
def subscription(_status, _topic, _state), do: []
def connection(status, state) do
Logger.info("MQTT connection status: #{status}")
{:ok, state}
end
def subscription(status, topic, state) do
Logger.info("MQTT subscription status for #{topic}: #{status}")
{:ok, state}
end
def handle_message(topic, payload, _state) do
case String.split(topic, "/") do
topic_parts = if is_binary(topic), do: String.split(topic, "/"), else: topic
case topic_parts do
["systant", hostname, "stats"] ->
case Jason.decode(payload) do
{:ok, data} ->
@ -74,5 +92,6 @@ defmodule Dashboard.MqttSubscriber do
{:noreply, %{state | hosts: updated_hosts}}
end
@impl true
def terminate(_reason, _state), do: []
end

View File

@ -1,42 +0,0 @@
defmodule Dashboard.SimpleMqtt do
@moduledoc """
Simple GenServer that polls for MQTT data instead of complex subscriptions.
"""
use GenServer
require Logger
alias Phoenix.PubSub
def start_link(_opts) do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end
@impl true
def init(_) do
# Start a timer that simulates receiving MQTT data
# In a real implementation, you'd use a proper MQTT client here
Logger.info("Starting simple MQTT poller")
# For now, just generate fake data that matches what systant publishes
:timer.send_interval(5000, self(), :simulate_mqtt)
{:ok, %{}}
end
@impl true
def handle_info(:simulate_mqtt, state) do
# Simulate receiving an MQTT message from orion
hostname = "orion"
host_data = %{
"message" => "Hello from systant",
"hostname" => hostname,
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601(),
"last_seen" => DateTime.utc_now()
}
Logger.info("Simulating MQTT message from #{hostname}")
PubSub.broadcast(Dashboard.PubSub, "systant:hosts", {:host_update, hostname, host_data})
{:noreply, state}
end
end

View File

@ -27,13 +27,20 @@
elixir
erlang
# File watching for Phoenix live reload
inotifyTools
# Process management and task running
hivemind
just
# AI/Development tools
claude-code
aider-chat
# Node.js for Phoenix assets
nodejs_20
npm
nodePackages.npm
# Database for development
postgresql
@ -69,7 +76,8 @@
};
};
}
) // {
)
// {
nixosModules.default = import ./nix/nixos-module.nix;
};
}