55 lines
1.7 KiB
Elixir
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
|