feat: include self-reported tx_power in measurement calls

This commit is contained in:
2026-05-16 14:42:37 +02:00
parent f5e148bb88
commit 0f0f377e98
3 changed files with 32 additions and 20 deletions
+8 -5
View File
@@ -21,9 +21,10 @@ defmodule Localiser.Localisation.Sensor.Server do
{:via, Registry, {Localiser.Registry, {:sensor, sensor_id}}} {:via, Registry, {Localiser.Registry, {:sensor, sensor_id}}}
end end
# Returns %{sensor_id, floor_x, floor_y, distance} for a raw RSSI reading. # Returns %{sensor_id, floor_x, floor_y, distance, rssi, tx_power} for a raw RSSI reading.
def measure(sensor_id, rssi) do # tx_power is the beacon-advertised expected RSSI at 1 m (nil if not available).
GenServer.call(via(sensor_id), {:measure, rssi}) def measure(sensor_id, rssi, tx_power \\ nil) do
GenServer.call(via(sensor_id), {:measure, rssi, tx_power})
end end
# Returns true if the sensor is currently collecting calibration samples. # Returns true if the sensor is currently collecting calibration samples.
@@ -66,14 +67,16 @@ defmodule Localiser.Localisation.Sensor.Server do
end end
@impl true @impl true
def handle_call({:measure, rssi}, _from, state) do def handle_call({:measure, rssi, tx_power}, _from, state) do
distance = rssi_to_distance(rssi, state.rssi_ref, state.path_loss_exp) distance = rssi_to_distance(rssi, state.rssi_ref, state.path_loss_exp)
measurement = %{ measurement = %{
sensor_id: state.sensor_id, sensor_id: state.sensor_id,
floor_x: state.floor_x, floor_x: state.floor_x,
floor_y: state.floor_y, floor_y: state.floor_y,
distance: distance distance: distance,
rssi: rssi,
tx_power: tx_power
} }
{:reply, measurement, state} {:reply, measurement, state}
+14 -5
View File
@@ -51,20 +51,29 @@ defmodule Localiser.MQTT.Router do
end end
defp handle_rssi(sensor_id, payload) do defp handle_rssi(sensor_id, payload) do
with {:ok, %{"tag_id" => tag_id, "rssi" => rssi}} <- case Jason.decode(payload) do
Jason.decode(payload) do {:ok, %{"id" => tag_id, "rssi" => rssi} = decoded} ->
reading = %{ reading = %{
sensor_id: sensor_id, sensor_id: sensor_id,
tag_id: tag_id, tag_id: tag_id,
rssi: rssi, rssi: rssi,
tx_power: Map.get(decoded, "tx_power"),
timestamp: DateTime.utc_now()
}
Localiser.MQTT.Telemetry.count_reading()
Localiser.RSSI.Buffer.push(reading)
{:ok, %{"tag_id" => tag_id, "rssi" => rssi}} ->
reading = %{
sensor_id: sensor_id,
tag_id: tag_id,
rssi: rssi,
tx_power: nil,
timestamp: DateTime.utc_now() timestamp: DateTime.utc_now()
} }
Localiser.MQTT.Telemetry.count_reading() Localiser.MQTT.Telemetry.count_reading()
Localiser.RSSI.Buffer.push(reading) Localiser.RSSI.Buffer.push(reading)
else
{:error, reason} -> {:error, reason} ->
Logger.error("[MQTT.Router] Bad payload from #{sensor_id}: #{inspect(reason)}") Logger.error("[MQTT.Router] Bad payload from #{sensor_id}: #{inspect(reason)}")
Localiser.MQTT.Telemetry.count_error() Localiser.MQTT.Telemetry.count_error()
+3 -3
View File
@@ -6,7 +6,7 @@ defmodule Localiser.RSSI.Buffer do
@flush_interval_ms 500 @flush_interval_ms 500
# reading :: %{sensor_id: String.t(), tag_id: String.t(), rssi: integer()} # reading :: %{sensor_id: String.t(), tag_id: String.t(), rssi: integer(), tx_power: integer() | nil}
def push(reading) do def push(reading) do
GenServer.cast(__MODULE__, {:push, reading}) GenServer.cast(__MODULE__, {:push, reading})
end end
@@ -50,14 +50,14 @@ defmodule Localiser.RSSI.Buffer do
# If the sensor is in calibration mode, feeds the reading to Sensor.Server instead # If the sensor is in calibration mode, feeds the reading to Sensor.Server instead
# and returns [] so the sample is excluded from Tag.Filter measurements. # and returns [] so the sample is excluded from Tag.Filter measurements.
# If the sensor server isn't running, returns []. # If the sensor server isn't running, returns [].
defp resolve_measurement(%{sensor_id: sensor_id, rssi: rssi}) do defp resolve_measurement(%{sensor_id: sensor_id, rssi: rssi, tx_power: tx_power}) do
case Registry.lookup(Localiser.Registry, {:sensor, sensor_id}) do case Registry.lookup(Localiser.Registry, {:sensor, sensor_id}) do
[{_pid, _}] -> [{_pid, _}] ->
if SensorServer.calibrating?(sensor_id) do if SensorServer.calibrating?(sensor_id) do
SensorServer.calibration_reading(sensor_id, rssi) SensorServer.calibration_reading(sensor_id, rssi)
[] []
else else
[SensorServer.measure(sensor_id, rssi)] [SensorServer.measure(sensor_id, rssi, tx_power)]
end end
[] -> [] ->