generated from Grigo/AndroidTemplate
Initial commit: LoraTester Android + server
This commit is contained in:
@@ -66,6 +66,29 @@ class TrackPointsBody(BaseModel):
|
||||
points: list[TrackPoint] = Field(default_factory=list)
|
||||
|
||||
|
||||
class CommandBody(BaseModel):
|
||||
from_device_id: str
|
||||
to_device_id: str
|
||||
kind: str
|
||||
payload: Optional[dict[str, Any]] = None
|
||||
|
||||
|
||||
class PairedTrackStartBody(BaseModel):
|
||||
device_ids: Optional[list[str]] = None
|
||||
initiator: Optional[str] = None
|
||||
device_id: Optional[str] = None
|
||||
|
||||
|
||||
class PairedTrackAckBody(BaseModel):
|
||||
session_id: int
|
||||
device_id: str
|
||||
track_id: int
|
||||
|
||||
|
||||
class PairedTrackCancelBody(BaseModel):
|
||||
session_id: Optional[int] = None
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def index():
|
||||
return FileResponse(
|
||||
@@ -194,6 +217,87 @@ def get_chat(since: float = 0, limit: int = Query(200, ge=1, le=500)):
|
||||
return storage.get_chat(since, limit)
|
||||
|
||||
|
||||
@app.post("/api/commands")
|
||||
def post_command(body: CommandBody):
|
||||
try:
|
||||
return storage.enqueue_command(
|
||||
body.from_device_id,
|
||||
body.to_device_id,
|
||||
body.kind,
|
||||
body.payload,
|
||||
)
|
||||
except ValueError as e:
|
||||
raise HTTPException(400, detail=str(e)) from e
|
||||
|
||||
|
||||
@app.get("/api/commands/pending")
|
||||
def commands_pending(
|
||||
device_id: str = Query(...),
|
||||
limit: int = Query(20, ge=1, le=50),
|
||||
x_lora_client: Optional[str] = Header(None, alias=ANDROID_CLIENT_HEADER),
|
||||
):
|
||||
_require_android(x_lora_client)
|
||||
try:
|
||||
return storage.poll_pending_commands(device_id, limit)
|
||||
except ValueError as e:
|
||||
raise HTTPException(400, detail=str(e)) from e
|
||||
|
||||
|
||||
@app.get("/api/commands")
|
||||
def commands_list(
|
||||
to_device_id: Optional[str] = None,
|
||||
limit: int = Query(50, ge=1, le=200),
|
||||
):
|
||||
return storage.list_commands(to_device_id, limit)
|
||||
|
||||
|
||||
@app.post("/api/paired-tracks/start")
|
||||
def paired_tracks_start(
|
||||
body: PairedTrackStartBody,
|
||||
x_lora_client: Optional[str] = Header(None, alias=ANDROID_CLIENT_HEADER),
|
||||
):
|
||||
if body.initiator:
|
||||
initiator = body.initiator
|
||||
elif body.device_id:
|
||||
initiator = body.device_id
|
||||
elif (x_lora_client or "").strip().lower() == ANDROID_CLIENT_VALUE:
|
||||
raise HTTPException(400, detail="initiator or device_id required")
|
||||
else:
|
||||
initiator = storage.WEB_SENDER_ID
|
||||
try:
|
||||
return storage.start_paired_track(body.device_ids, str(initiator))
|
||||
except ValueError as e:
|
||||
raise HTTPException(400, detail=str(e)) from e
|
||||
|
||||
|
||||
@app.get("/api/paired-tracks/active")
|
||||
def paired_tracks_active():
|
||||
session = storage.get_active_paired_track()
|
||||
return {"active": session is not None, "session": session}
|
||||
|
||||
|
||||
@app.post("/api/paired-tracks/ack")
|
||||
def paired_tracks_ack(
|
||||
body: PairedTrackAckBody,
|
||||
x_lora_client: Optional[str] = Header(None, alias=ANDROID_CLIENT_HEADER),
|
||||
):
|
||||
_require_android(x_lora_client)
|
||||
try:
|
||||
return storage.ack_paired_track(
|
||||
body.session_id, body.device_id, body.track_id
|
||||
)
|
||||
except ValueError as e:
|
||||
raise HTTPException(400, detail=str(e)) from e
|
||||
|
||||
|
||||
@app.post("/api/paired-tracks/cancel")
|
||||
def paired_tracks_cancel(body: PairedTrackCancelBody):
|
||||
try:
|
||||
return storage.cancel_paired_track(body.session_id)
|
||||
except ValueError as e:
|
||||
raise HTTPException(400, detail=str(e)) from e
|
||||
|
||||
|
||||
@app.get("/api/health")
|
||||
def health():
|
||||
status = storage.db_status()
|
||||
|
||||
Reference in New Issue
Block a user