feat: return 200 for motor control actions
This commit is contained in:
parent
bb8a69e2d0
commit
c9005baf9a
15
README.md
15
README.md
@ -232,6 +232,21 @@ curl -X POST "http://${SERVER_IP}:8000/v1/motor/stop"
|
|||||||
curl "http://${SERVER_IP}:8000/v1/motor/status"
|
curl "http://${SERVER_IP}:8000/v1/motor/status"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`open`、`close`、`stop` 成功时均返回 HTTP `200 OK`,响应 JSON 包含
|
||||||
|
`"code": 200`、执行动作和当前电机状态。例如:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"accepted": true,
|
||||||
|
"action": "stop",
|
||||||
|
"state": "stopped"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
实际响应还包含电机 ID、控制量、广播状态等字段。硬件未启用或状态冲突仍返回
|
||||||
|
HTTP `409`,CAN/USB 通讯失败仍返回 HTTP `503`。
|
||||||
|
|
||||||
`MOTOR_HARDWARE_ENABLED=true` 时,启动过程会自动 Enable。HTTP 只保留
|
`MOTOR_HARDWARE_ENABLED=true` 时,启动过程会自动 Enable。HTTP 只保留
|
||||||
`open`、`close`、`stop` 和 `status`,不提供 `enable`/`disable`。
|
`open`、`close`、`stop` 和 `status`,不提供 `enable`/`disable`。
|
||||||
|
|
||||||
|
|||||||
@ -74,6 +74,7 @@ def create_app(
|
|||||||
|
|
||||||
def response_for(result: MotorStatus, action: str) -> dict[str, Any]:
|
def response_for(result: MotorStatus, action: str) -> dict[str, Any]:
|
||||||
return {
|
return {
|
||||||
|
"code": status.HTTP_200_OK,
|
||||||
"accepted": True,
|
"accepted": True,
|
||||||
"action": action,
|
"action": action,
|
||||||
"transmission": "CAN frame transmitted; physical motor motion is not verified",
|
"transmission": "CAN frame transmitted; physical motor motion is not verified",
|
||||||
@ -128,7 +129,7 @@ def create_app(
|
|||||||
|
|
||||||
@app.post(
|
@app.post(
|
||||||
"/v1/motor/open",
|
"/v1/motor/open",
|
||||||
status_code=status.HTTP_202_ACCEPTED,
|
status_code=status.HTTP_200_OK,
|
||||||
dependencies=[Depends(authorize)],
|
dependencies=[Depends(authorize)],
|
||||||
)
|
)
|
||||||
async def open_motor(request: Request) -> dict[str, Any]:
|
async def open_motor(request: Request) -> dict[str, Any]:
|
||||||
@ -137,7 +138,7 @@ def create_app(
|
|||||||
|
|
||||||
@app.post(
|
@app.post(
|
||||||
"/v1/motor/close",
|
"/v1/motor/close",
|
||||||
status_code=status.HTTP_202_ACCEPTED,
|
status_code=status.HTTP_200_OK,
|
||||||
dependencies=[Depends(authorize)],
|
dependencies=[Depends(authorize)],
|
||||||
)
|
)
|
||||||
async def close_motor(request: Request) -> dict[str, Any]:
|
async def close_motor(request: Request) -> dict[str, Any]:
|
||||||
@ -146,7 +147,7 @@ def create_app(
|
|||||||
|
|
||||||
@app.post(
|
@app.post(
|
||||||
"/v1/motor/stop",
|
"/v1/motor/stop",
|
||||||
status_code=status.HTTP_202_ACCEPTED,
|
status_code=status.HTTP_200_OK,
|
||||||
dependencies=[Depends(authorize)],
|
dependencies=[Depends(authorize)],
|
||||||
)
|
)
|
||||||
async def stop(request: Request) -> dict[str, Any]:
|
async def stop(request: Request) -> dict[str, Any]:
|
||||||
|
|||||||
@ -100,7 +100,8 @@ def test_http_open_and_close_can_switch_directions() -> None:
|
|||||||
reopened = await client.post("/v1/motor/open")
|
reopened = await client.post("/v1/motor/open")
|
||||||
stopped = await client.post("/v1/motor/stop")
|
stopped = await client.post("/v1/motor/stop")
|
||||||
|
|
||||||
assert opening.status_code == 202
|
assert opening.status_code == 200
|
||||||
|
assert opening.json()["code"] == 200
|
||||||
assert opening.json()["action"] == "open"
|
assert opening.json()["action"] == "open"
|
||||||
assert opening.json()["state"] == "opening"
|
assert opening.json()["state"] == "opening"
|
||||||
assert opening.json()["control_raw"] == 400
|
assert opening.json()["control_raw"] == 400
|
||||||
@ -110,18 +111,21 @@ def test_http_open_and_close_can_switch_directions() -> None:
|
|||||||
assert opening.json()["broadcast_frequency_hz"] == 10
|
assert opening.json()["broadcast_frequency_hz"] == 10
|
||||||
assert still_opening.json()["state"] == "opening"
|
assert still_opening.json()["state"] == "opening"
|
||||||
assert still_opening.json()["streaming"] is True
|
assert still_opening.json()["streaming"] is True
|
||||||
assert closing.status_code == 202
|
assert closing.status_code == 200
|
||||||
|
assert closing.json()["code"] == 200
|
||||||
assert closing.json()["action"] == "close"
|
assert closing.json()["action"] == "close"
|
||||||
assert closing.json()["state"] == "closing"
|
assert closing.json()["state"] == "closing"
|
||||||
assert closing.json()["control_raw"] == -400
|
assert closing.json()["control_raw"] == -400
|
||||||
assert closing.json()["control_raw_by_motor"] == {"1": -400, "2": 400}
|
assert closing.json()["control_raw_by_motor"] == {"1": -400, "2": 400}
|
||||||
assert "not verified" in closing.json()["transmission"]
|
assert "not verified" in closing.json()["transmission"]
|
||||||
assert reopened.status_code == 202
|
assert reopened.status_code == 200
|
||||||
|
assert reopened.json()["code"] == 200
|
||||||
assert reopened.json()["action"] == "open"
|
assert reopened.json()["action"] == "open"
|
||||||
assert reopened.json()["state"] == "opening"
|
assert reopened.json()["state"] == "opening"
|
||||||
assert reopened.json()["control_raw"] == 400
|
assert reopened.json()["control_raw"] == 400
|
||||||
assert reopened.json()["control_raw_by_motor"] == {"1": 400, "2": -400}
|
assert reopened.json()["control_raw_by_motor"] == {"1": 400, "2": -400}
|
||||||
assert stopped.status_code == 202
|
assert stopped.status_code == 200
|
||||||
|
assert stopped.json()["code"] == 200
|
||||||
assert stopped.json()["state"] == "stopped"
|
assert stopped.json()["state"] == "stopped"
|
||||||
|
|
||||||
asyncio.run(scenario())
|
asyncio.run(scenario())
|
||||||
@ -139,9 +143,11 @@ def test_automatic_enable_and_motion_do_not_require_feedback_replies() -> None:
|
|||||||
opening = await client.post("/v1/motor/open")
|
opening = await client.post("/v1/motor/open")
|
||||||
stopped = await client.post("/v1/motor/stop")
|
stopped = await client.post("/v1/motor/stop")
|
||||||
|
|
||||||
assert opening.status_code == 202
|
assert opening.status_code == 200
|
||||||
|
assert opening.json()["code"] == 200
|
||||||
assert opening.json()["streaming"] is True
|
assert opening.json()["streaming"] is True
|
||||||
assert stopped.status_code == 202
|
assert stopped.status_code == 200
|
||||||
|
assert stopped.json()["code"] == 200
|
||||||
assert stopped.json()["streaming"] is False
|
assert stopped.json()["streaming"] is False
|
||||||
|
|
||||||
asyncio.run(scenario())
|
asyncio.run(scenario())
|
||||||
@ -165,7 +171,8 @@ def test_one_http_stop_sends_two_explicit_stop_rounds() -> None:
|
|||||||
(frame.arbitration_id, frame.data.hex()) for frame in transport.frames[start:]
|
(frame.arbitration_id, frame.data.hex()) for frame in transport.frames[start:]
|
||||||
]
|
]
|
||||||
timeouts_s = transport.tx_queue_timeouts_s[start:]
|
timeouts_s = transport.tx_queue_timeouts_s[start:]
|
||||||
assert stopped.status_code == 202
|
assert stopped.status_code == 200
|
||||||
|
assert stopped.json()["code"] == 200
|
||||||
assert stopped.json()["state"] == "stopped"
|
assert stopped.json()["state"] == "stopped"
|
||||||
assert frames == [
|
assert frames == [
|
||||||
(CONTROL_FRAME_ID, "0000000000000000"),
|
(CONTROL_FRAME_ID, "0000000000000000"),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user