feat: wait for enrolled sensors to announce, factory reset them on deletion

This commit is contained in:
2026-05-15 15:07:04 +02:00
parent 4c66642cd4
commit b434896e71
8 changed files with 99 additions and 5 deletions
+36 -3
View File
@@ -55,6 +55,8 @@ defmodule Localiser.Domain.Sensors do
end
def delete_sensor(%Sensor{} = sensor) do
topic = "localiser/sensor/#{sensor.sensor_id}/cmd"
Localiser.MQTT.Connection.publish(topic, Jason.encode!(%{command: "factory_reset"}))
Repo.delete(sensor)
end
@@ -89,14 +91,45 @@ defmodule Localiser.Domain.Sensors do
# Sensor lifecycle / enrollment helpers
@enrollment_timeout_ms Application.compile_env(:localiser, :enrollment_timeout_ms, 10_000)
# Called by the phone app to indicate a sensor is about to come online.
# Creates an unconfirmed sensor record and starts a timeout Task.
def expect_sensor(sensor_id) do
result =
%Sensor{}
|> Sensor.changeset(%{sensor_id: sensor_id, confirmed: false})
|> Repo.insert(
on_conflict: [set: [confirmed: false, updated_at: DateTime.utc_now()]],
conflict_target: :sensor_id,
returning: true
)
case result do
{:ok, sensor} ->
Phoenix.PubSub.broadcast(Localiser.PubSub, "sensors", {:sensor_expected, sensor})
Task.start(fn ->
Process.sleep(@enrollment_timeout_ms)
fresh = Repo.get_by(Sensor, sensor_id: sensor_id)
if fresh && !fresh.confirmed do
Phoenix.PubSub.broadcast(Localiser.PubSub, "sensors", {:sensor_enrollment_timeout, sensor_id})
end
end)
{:ok, sensor}
error ->
error
end
end
# Called when an ESP board self-announces on MQTT. Inserts a new unplaced sensor
# record, or bumps updated_at if the sensor_id already exists.
# record, or marks it confirmed if the sensor_id already exists.
def upsert_announced(sensor_id) do
result =
%Sensor{}
|> Sensor.changeset(%{sensor_id: sensor_id})
|> Sensor.changeset(%{sensor_id: sensor_id, confirmed: true})
|> Repo.insert(
on_conflict: [set: [updated_at: DateTime.utc_now()]],
on_conflict: [set: [confirmed: true, updated_at: DateTime.utc_now()]],
conflict_target: :sensor_id,
returning: true
)