83 lines
2.6 KiB
Elixir
83 lines
2.6 KiB
Elixir
defmodule Localiser.Web.Controllers.FirmwareController do
|
|
use Phoenix.Controller, formats: [:json]
|
|
|
|
alias Localiser.Domain.{Firmware, Sensors}
|
|
|
|
# Admin: upload a new firmware version.
|
|
# Expects multipart/form-data with fields: version (string), firmware (file).
|
|
def upload(conn, %{"version" => version, "firmware" => %Plug.Upload{} = upload}) do
|
|
case Firmware.store(version, upload) do
|
|
{:ok, _version} ->
|
|
json(conn, %{status: "ok", version: version})
|
|
|
|
{:error, reason} ->
|
|
conn
|
|
|> put_status(:internal_server_error)
|
|
|> json(%{error: "Upload failed: #{inspect(reason)}"})
|
|
end
|
|
end
|
|
|
|
def upload(conn, _params) do
|
|
conn
|
|
|> put_status(:bad_request)
|
|
|> json(%{error: "version and firmware file are required"})
|
|
end
|
|
|
|
# Admin: list available firmware versions.
|
|
def index(conn, _params) do
|
|
json(conn, Firmware.list())
|
|
end
|
|
|
|
# Public: serve firmware binary.
|
|
def download(conn, %{"version" => version}) do
|
|
case Firmware.get(version) do
|
|
{:ok, path} ->
|
|
conn
|
|
|> put_resp_content_type("application/octet-stream")
|
|
|> put_resp_header("content-disposition", ~s(attachment; filename="#{version}.bin"))
|
|
|> send_file(200, path)
|
|
|
|
:not_found ->
|
|
conn
|
|
|> put_status(:not_found)
|
|
|> json(%{error: "Firmware version not found"})
|
|
end
|
|
end
|
|
|
|
# Admin: broadcast OTA update to the entire fleet.
|
|
# POST /api/firmware/:version/ota
|
|
def ota_fleet(conn, %{"version" => version}) do
|
|
case Firmware.get(version) do
|
|
{:ok, _path} ->
|
|
url = firmware_url(conn, version)
|
|
Sensors.send_ota_broadcast(url, version)
|
|
json(conn, %{status: "ok", url: url, version: version})
|
|
|
|
:not_found ->
|
|
conn
|
|
|> put_status(:not_found)
|
|
|> json(%{error: "Firmware version not found"})
|
|
end
|
|
end
|
|
|
|
# Admin: upload a new firmware version and push OTA update to fleet immediately.
|
|
# Expects multipart/form-data with fields: version (string), firmware (file).
|
|
def ota_fleet_instant(conn, %{"version" => version, "firmware" => %Plug.Upload{} = upload}) do
|
|
case Firmware.store(version, upload) do
|
|
{:ok, _version} ->
|
|
url = firmware_url(conn, version)
|
|
Sensors.send_ota_broadcast(url, version)
|
|
json(conn, %{status: "ok", version: version})
|
|
|
|
{:error, reason} ->
|
|
conn
|
|
|> put_status(:internal_server_error)
|
|
|> json(%{error: "Upload failed: #{inspect(reason)}"})
|
|
end
|
|
end
|
|
|
|
defp firmware_url(conn, version) do
|
|
"#{conn.scheme}://#{conn.host}:#{conn.port}/api/firmware/#{version}"
|
|
end
|
|
end
|