feat: implement multidistance rssi->distance model parameter estimation
This commit is contained in:
@@ -108,21 +108,39 @@ defmodule Localiser.Web.Controllers.SensorController do
|
||||
unauthorized: {"Unauthorized", "application/json", Schemas.Error}
|
||||
]
|
||||
|
||||
operation :calibration_start,
|
||||
summary: "Begin RSSI calibration",
|
||||
operation :calibration_begin,
|
||||
summary: "Enter calibration mode (between-stages)",
|
||||
parameters: [id: [in: :path, type: :integer, required: true]],
|
||||
request_body: {"Calibration params", "application/json", Schemas.CalibrationStartParams, required: true},
|
||||
responses: [
|
||||
ok: {"Calibration started", "application/json", Schemas.CalibrationStatus},
|
||||
bad_request: {"Missing reference_distance", "application/json", Schemas.Error},
|
||||
ok: {"Calibration mode entered", "application/json", Schemas.CalibrationBeginResponse},
|
||||
unauthorized: {"Unauthorized", "application/json", Schemas.Error}
|
||||
]
|
||||
|
||||
operation :calibration_stop,
|
||||
summary: "Abort active calibration",
|
||||
operation :calibration_stage_start,
|
||||
summary: "Start collecting samples for a specific distance",
|
||||
parameters: [id: [in: :path, type: :integer, required: true]],
|
||||
request_body: {"Stage params", "application/json", Schemas.CalibrationStageParams, required: true},
|
||||
responses: [
|
||||
ok: {"Stage started", "application/json", Schemas.CalibrationStageResponse},
|
||||
bad_request: {"Missing or invalid distance", "application/json", Schemas.Error},
|
||||
unprocessable_entity: {"Stage already active", "application/json", Schemas.Error},
|
||||
unauthorized: {"Unauthorized", "application/json", Schemas.Error}
|
||||
]
|
||||
|
||||
operation :calibration_finish,
|
||||
summary: "Run regression over completed stages and save calibration",
|
||||
parameters: [id: [in: :path, type: :integer, required: true]],
|
||||
responses: [
|
||||
ok: {"Calibration aborted", "application/json", Schemas.CalibrationStatus},
|
||||
ok: {"Calibration saved", "application/json", Schemas.CalibrationFinishResponse},
|
||||
unprocessable_entity: {"Insufficient stages or stage active", "application/json", Schemas.Error},
|
||||
unauthorized: {"Unauthorized", "application/json", Schemas.Error}
|
||||
]
|
||||
|
||||
operation :calibration_cancel,
|
||||
summary: "Abort calibration, discard all stages",
|
||||
parameters: [id: [in: :path, type: :integer, required: true]],
|
||||
responses: [
|
||||
ok: {"Calibration cancelled", "application/json", Schemas.CalibrationStatus},
|
||||
unauthorized: {"Unauthorized", "application/json", Schemas.Error}
|
||||
]
|
||||
|
||||
@@ -252,24 +270,77 @@ defmodule Localiser.Web.Controllers.SensorController do
|
||||
json(conn, %{status: "ok"})
|
||||
end
|
||||
|
||||
def calibration_start(conn, %{"id" => id, "reference_distance" => ref_dist}) do
|
||||
def calibration_begin(conn, %{"id" => id}) do
|
||||
sensor = Sensors.get_sensor!(id)
|
||||
:ok = SensorServer.begin_calibration(sensor.sensor_id, ref_dist)
|
||||
json(conn, %{status: "calibrating"})
|
||||
:ok = SensorServer.begin_calibration_mode(sensor.sensor_id)
|
||||
json(conn, %{status: "calibration_mode", samples_needed: calibration_samples_needed()})
|
||||
end
|
||||
|
||||
def calibration_start(conn, _params) do
|
||||
def calibration_stage_start(conn, %{"id" => id, "distance" => distance})
|
||||
when is_number(distance) and distance > 0 do
|
||||
sensor = Sensors.get_sensor!(id)
|
||||
|
||||
case SensorServer.start_stage(sensor.sensor_id, distance * 1.0) do
|
||||
{:ok, samples_needed} ->
|
||||
json(conn, %{status: "stage_active", distance: distance, samples_needed: samples_needed})
|
||||
|
||||
{:error, :already_active} ->
|
||||
conn
|
||||
|> put_status(:unprocessable_entity)
|
||||
|> json(%{error: "a stage is already active"})
|
||||
|
||||
{:error, :not_in_calibration_mode} ->
|
||||
conn
|
||||
|> put_status(:unprocessable_entity)
|
||||
|> json(%{error: "sensor is not in calibration mode"})
|
||||
end
|
||||
end
|
||||
|
||||
def calibration_stage_start(conn, _params) do
|
||||
conn
|
||||
|> put_status(:bad_request)
|
||||
|> json(%{error: "reference_distance is required"})
|
||||
|> json(%{error: "distance is required and must be a positive number"})
|
||||
end
|
||||
|
||||
def calibration_stop(conn, %{"id" => id}) do
|
||||
def calibration_finish(conn, %{"id" => id}) do
|
||||
sensor = Sensors.get_sensor!(id)
|
||||
|
||||
case SensorServer.finish_calibration(sensor.sensor_id) do
|
||||
{:ok, %{rssi_ref: rssi_ref, path_loss_exp: path_loss_exp}} ->
|
||||
json(conn, %{status: "idle", rssi_ref: rssi_ref, path_loss_exp: path_loss_exp})
|
||||
|
||||
{:error, :insufficient_stages} ->
|
||||
conn
|
||||
|> put_status(:unprocessable_entity)
|
||||
|> json(%{error: "at least 2 completed stages required"})
|
||||
|
||||
{:error, :stage_active} ->
|
||||
conn
|
||||
|> put_status(:unprocessable_entity)
|
||||
|> json(%{error: "cannot finish while a stage is active"})
|
||||
|
||||
{:error, :not_in_calibration_mode} ->
|
||||
conn
|
||||
|> put_status(:unprocessable_entity)
|
||||
|> json(%{error: "sensor is not in calibration mode"})
|
||||
|
||||
{:error, reason} ->
|
||||
conn
|
||||
|> put_status(:unprocessable_entity)
|
||||
|> json(%{error: inspect(reason)})
|
||||
end
|
||||
end
|
||||
|
||||
def calibration_cancel(conn, %{"id" => id}) do
|
||||
sensor = Sensors.get_sensor!(id)
|
||||
:ok = SensorServer.abort_calibration(sensor.sensor_id)
|
||||
json(conn, %{status: "idle"})
|
||||
end
|
||||
|
||||
defp calibration_samples_needed do
|
||||
Application.get_env(:localiser, :calibration_samples, 30)
|
||||
end
|
||||
|
||||
defp render_sensor(sensor) do
|
||||
%{
|
||||
id: sensor.id,
|
||||
|
||||
Reference in New Issue
Block a user