Skip to content

China-market G20S (a96): method-selective -10002 rrcheck access denied despite working local MQTT/HTTPS #182

Open

Description

@JiQingWu68

What happened?

I am investigating local control of a China-market Roborock G20S (roborock.vacuum.a96, hardware model A9650RR) using local_roborock_server.

The robot successfully connects to the existing local HTTPS and MQTT services. Its device identity has been correlated between the access point, LAN neighbor table, MQTT connection and configured device inventory.

However, device RPC behavior differs significantly by method.

Some initialization and identity methods return structured results, while ordinary status-related methods return -10002 rrcheck access denied, often followed by a separate unknown_method response with the same request ID.

The problem is reproducible across the saved observations. I have not established successful cleaning control on this device.

The device is being operated outside mainland China.

Environment

  • Vacuum: Roborock G20S, China-market model A9650RR
  • Device identifier: roborock.vacuum.a96
  • Main robot firmware: Unknown; the available DSP version is not treated as the main firmware version
  • Local server: local_roborock_server 1.0.2
  • Client SDK studied: python-roborock 4.20.0
  • Host: Ubuntu WSL2 with Docker
  • Local connectivity: HTTPS and MQTT confirmed
  • Control authorization: Not established

Reproducible observations

We reconstructed 52 previously recorded RPC requests across five connection epochs, preserving request IDs, response direction, session association and response-envelope distinctions.

Method Parameters Observed response
app_get_init_status [] Structured result
get_serial_number [] Structured result
get_status [] -10002 followed by separate unknown_method
get_prop ["get_status"] -10002 followed by separate unknown_method

Across the full historical dataset:

  • 31 requests received structured responses.
  • 21 requests received two distinct failure responses using the same request ID.
  • The two failure responses have different envelope structures and sequence numbers.
  • Successful initialization responses do not establish general control authorization.

In one controlled observation, app_get_init_status([]) returned a structured result, while a subsequent get_status([]) request on the same device connection returned:

  1. An error-only response containing -10002 rrcheck access denied.
  2. A separate response containing result: "unknown_method" using the same RPC ID.

Both responses were observed in the saved device-direction MQTT traffic. This is not merely a client-side parsing or timeout issue.

No cleaning, docking, firmware modification or pairing-reset commands were performed as part of these diagnostics.

Investigations already completed

We compared the saved RPC frames, Python SDK implementation, server transport path, decoded Android application and product plugin bytecode.

Findings:

  • The ordinary application status path uses get_prop(["get_status"]).
  • The initialization path uses app_get_init_status([]).
  • Both ultimately use the ordinary device-method dispatch path in the analyzed application build.
  • The application's observed retry whitelist does not include these status methods.
  • We found no evidence that adding need_retry or switching to the Spec API would resolve this issue.
  • An SDK duplicate-response consumption issue was reproduced offline, but it cannot explain the device-direction -10002 response.
  • Forty-four offline regression tests passed; no live robot RPCs were sent during this analysis.

Question about /f/c and PR #124

I noticed the /f/c authorization-check handling added in PR #124 and included in newer releases.

My installed server version does not contain that handler.

However, the available HTTP logs contain no attributable natural /f/c request from this a96 device. The logs also have limited visibility into other destinations and TLS failures.

I therefore do not assume that the S7-derived /f/c behavior applies to a96, or that PR #124 would safely resolve this issue.

Questions for maintainers

  1. Has anyone confirmed successful get_status or get_prop(["get_status"]) responses on a China-market roborock.vacuum.a96 using a local server? If so, could you share the relevant firmware version and request contract, without credentials?

  2. Is the -10002 / unknown_method combination known to indicate an rrcheck authorization condition, a missing device-session context, or incompatible method handling? Is there any a96-specific evidence distinguishing these possibilities?

  3. Is /f/c known to be used by a96 firmware? Has the handler introduced in PR feat(fw): answer /f/c rrcheck with a locally-forged access grant (#120) #124 actually been tested with this model?

  4. Is there a safe, read-only diagnostic for determining the device's actual main firmware version or the reason for an rrcheck rejection? I would prefer not to guess additional security fields, grant responses or unlock commands.

  5. Does the project currently consider a96 supported for actual local control, rather than connectivity alone? If it is unsupported, are there known implementation gaps or a recommended compatibility reference?

Related issues

These reports may involve different firmware behavior. In my case, initial successful device-control operation has never been confirmed.

Privacy and testing scope

I have intentionally excluded my device ID, serial number, MAC address, LAN IP, local keys, tokens, account identifiers, raw signed requests and unredacted logs.

I can provide additional sanitized request/response structure or offline test results if they would help identify the a96-specific compatibility requirement.

I am looking for evidence of the actual device contract before attempting further changes to the live robot.

Thank you for any guidance.

Steps to reproduce

  1. Start the existing local_roborock_server deployment with the previously configured device identity and local key.

  2. Wait for the China-market G20S (roborock.vacuum.a96) to establish its natural MQTT/HTTPS connections. Confirm the target device against the configured inventory and active connection.

  3. In the historical controlled test, send app_get_init_status with params: [] once. Observe a normal structured response.

  4. On the same device connection, send get_status with params: [] once.

  5. Observe two distinct device-direction responses with the same RPC ID:

    • error.code: -10002, error.message: "rrcheck access denied"
    • result: "unknown_method"
  6. Inspect the saved MQTT response envelopes. The two responses have different sequence numbers and field structures.

This sequence has already been performed and documented. I am not requesting additional live commands or repeated diagnostic attempts without evidence of a model-specific contract.

Vacuum model

Roborock G20S (China), A9650RR, roborock.vacuum.a96

Server / image version

local_roborock_server 1.0.2 (Ubuntu WSL2 / Docker; exact image tag not verified)

Relevant logs

Sanitized summary of previously captured device-direction MQTT responses:

Successful initialization:
  Method: app_get_init_status
  Params: []
  Response: structured result received

Rejected status request:
  Method: get_status
  Params: []
  Response 1:
    error.code: -10002
    error.message: rrcheck access denied
  Response 2 (same RPC ID):
    result: unknown_method

The rejection and unknown_method responses were recorded as distinct MQTT response envelopes, with different sequence numbers and field sets.

Historical analysis:
  Total requests: 52
  Structured-response cases: 31
  Dual-rejection cases: 21
  Connection epochs: 5

This is a sanitized structural summary, not a verbatim raw log. Device IDs, request IDs, IP/MAC addresses, keys, account credentials and raw payloads have been omitted.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions