Skip to content

Make get_status_now fail when the firmware refuses 0x40 #7

Description

@X-F-R

Context

Arm.get_status_now() (src/litearm/arm.py:1301) sends GET_STATUS 0x40 and waits for a conclusion. Its completion predicate is _done (src/litearm/arm.py:1321):

def _done(a) -> bool:
    return bool(a._queues.get(err_key)) or a.status_seq != seq0

The two halves are independent sources. a._queues.get(err_key) is the reply to our 0x40. a.status_seq counts the firmware's passive 100 Hz status stream, which keeps arriving no matter what we asked for.

Expected

When the firmware refuses 0x40, the call raises. err_key exists for exactly that case, and the comment on _done says so: "本命令被拒也算有结论".

Actual

Whichever half becomes true first ends the wait, and the code then decides from the error queue alone (src/litearm/arm.py:1330):

self._pump_until(timeout, _done, "get_status_now")
errq = a._queues.get(err_key)
if errq:
    raise _err_from(p, "get_status_now: ")
st = a.state
if st is None:
    raise MotionTimeoutError(...)
return self._msg(st, P.RSP_STATUS)

A passive status frame that lands before our ERR{0x40,...} satisfies a.status_seq != seq0, so _pump_until returns with the error queue still empty. a.state is not None, because the passive stream has been filling it all along. The call returns that state as a success and the refusal disappears. The caller cannot tell its command was rejected.

Reproduce

I found this while porting the client to C++ and measured it there; the C++ port inherits these semantics deliberately, so _done and the block above are the same shape.

Measured against a fake transport, varying only how many status frames are delivered during the call:

  • zero status frames delivered: 150/150 raised correctly;
  • exactly one status frame delivered: 26 to 35 out of 150 returned a successful result instead.

I have not re-run this against the Python implementation itself. The experiment is a C++ harness and is not in any repository, so treat the numbers as an indication of the window's size rather than a figure reproducible from main.

The existing offline tests do not cover it: they drive a fake whose status stream they control, so a status frame never lands inside that window by accident.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions