Files
localiserd/lib/localiser/localisation/sensor/manager.ex
T
2026-04-16 15:46:00 +02:00

55 lines
1.7 KiB
Elixir

defmodule Localiser.Localisation.Sensor.Manager do
@moduledoc """
GenServer that subscribes to the "sensors" PubSub topic and manages
Sensor.Server lifecycle for a specific floor.
- {:sensor_enrolled, sensor, room} → start Sensor.Server if not already running
- {:sensor_unenrolled, sensor_id} → terminate the Sensor.Server for this floor
"""
use GenServer
alias Localiser.Localisation.Sensor
def start_link(floor) do
GenServer.start_link(__MODULE__, floor.id, name: via(floor.id))
end
def via(floor_id) do
{:via, Registry, {Localiser.Registry, {:sensor_manager, floor_id}}}
end
@impl true
def init(floor_id) do
Phoenix.PubSub.subscribe(Localiser.PubSub, "sensors")
{:ok, %{floor_id: floor_id}}
end
# Sensor placed (or moved) onto this floor's layout.
@impl true
def handle_info({:sensor_enrolled, sensor, %{floor_id: floor_id} = room}, %{floor_id: floor_id} = state) do
case Registry.lookup(Localiser.Registry, {:sensor, sensor.sensor_id}) do
[] -> Sensor.Supervisor.start_sensor_server(floor_id, sensor, room)
_ -> :ok # Sensor.Server is already running and handles position via its own PubSub sub
end
{:noreply, state}
end
# Sensor removed from layout — stop the server for this floor if it's running.
def handle_info({:sensor_unenrolled, sensor_id}, %{floor_id: floor_id} = state) do
case Registry.lookup(Localiser.Registry, {:sensor, sensor_id}) do
[{pid, _}] ->
DynamicSupervisor.terminate_child(Sensor.Supervisor.via(floor_id), pid)
[] ->
:ok
end
{:noreply, state}
end
# Ignore all other PubSub broadcasts (sensor announced, calibration_complete, etc.)
def handle_info(_msg, state), do: {:noreply, state}
end