Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ dependencies = [
audio = [
"sounddevice>=0.4.6",
]
codegen = [
"grpcio-tools==1.76.0",
]

[project.scripts]
robonix-client = "robonix_client.cli:main"
Expand All @@ -37,6 +40,7 @@ robonix_client = [
"static/*.js",
"static/fonts/*",
"proto/*.py",
"proto/*.proto",
"audio_device_server/*.py",
"audio_device_server/requirements.txt",
]
16 changes: 16 additions & 0 deletions scripts/generate_sentinel_proto.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PROTO_DIR="$ROOT_DIR/src/robonix_client/proto"
PYTHON="${PYTHON:-python}"

if [[ "$($PYTHON -m grpc_tools.protoc --version)" != "libprotoc 31.1" ]]; then
echo "Sentinel bindings require protoc 31.1 (grpcio-tools 1.76.0)." >&2
exit 1
fi

"$PYTHON" -m grpc_tools.protoc \
--proto_path="$PROTO_DIR" \
--python_out="$PROTO_DIR" \
"$PROTO_DIR/sentinel.proto"
27 changes: 27 additions & 0 deletions src/robonix_client/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
account_replace_voiceprint,
account_unbind_voiceprint,
account_update_profile,
sentinel_list_rules,
sentinel_replace_rules,
)

STATIC_DIR = Path(__file__).with_name("static")
Expand Down Expand Up @@ -164,6 +166,10 @@ class AdminTargetRequest(AccountRequest):
targetUserId: str


class SentinelRulesRequest(AccountRequest):
rules: list[dict[str, Any]]


def _payload_steer(payload: dict[str, Any]) -> bool:
return bool(payload.get("steer") or payload.get("interactionMode") == "steer")

Expand Down Expand Up @@ -226,6 +232,7 @@ async def stop_client_audio() -> None:
@app.get("/settings")
@app.get("/profile")
@app.get("/admin")
@app.get("/sentinel")
async def index() -> FileResponse:
return FileResponse(STATIC_DIR / "index.html")

Expand Down Expand Up @@ -460,6 +467,26 @@ async def admin_reset_voiceprint(req: AdminTargetRequest) -> dict[str, Any]:
return {"ok": False, "error": _rpc_error(exc)}


@app.post("/api/sentinel/rules")
async def sentinel_rules(req: AccountRequest) -> dict[str, Any]:
try:
rules = await sentinel_list_rules(ClientSettings.from_payload(req.settings))
return {"ok": True, "rules": rules}
except Exception as exc:
return {"ok": False, "error": _rpc_error(exc)}


@app.put("/api/sentinel/rules")
async def sentinel_rules_replace(req: SentinelRulesRequest) -> dict[str, Any]:
try:
rules = await sentinel_replace_rules(
ClientSettings.from_payload(req.settings), req.rules
)
return {"ok": True, "rules": rules}
except Exception as exc:
return {"ok": False, "error": _rpc_error(exc)}


@app.get("/api/system")
async def system(atlas: str = Query(DEFAULT_ATLAS)) -> dict[str, Any]:
try:
Expand Down
22 changes: 22 additions & 0 deletions src/robonix_client/proto/sentinel.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// @generated by robonix-codegen --lang proto
// source: ROS IDL package 'sentinel'
syntax = "proto3";

package robonix.sentinel;

message ListRules_Request {
string session_token = 1;
}

message ListRules_Response {
string rules_json = 1;
}

message ReplaceRules_Request {
string session_token = 1;
string rules_json = 2;
}

message ReplaceRules_Response {
string rules_json = 1;
}
42 changes: 42 additions & 0 deletions src/robonix_client/proto/sentinel_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading