Skip to content

Config section write: set_config_section (SYSTEM_CONFIG_SET_MESSAGE) - #10

Merged
widgetii merged 2 commits into
masterfrom
config-set-primitive
Sep 22, 2026
Merged

widgetii merged 2 commits into
masterfrom
config-set-primitive

Conversation

@widgetii

Copy link
Copy Markdown
Member

What

Adds AnjoyCommClient.set_config_section(code, body, confirm=True) — the primitive for the vendor's per-feature batch-config operations, captured live from AjDevTools driving an MTF45-4G_AF.

Protocol (captured + verified live)

AjDevTools' per-feature batch buttons write one config section at a time:

  • TX SYSTEM_CONFIG_SET_MESSAGE with the section's numeric Msg_code and the section element as the body.
  • RX the same type+code with an empty body = success ack.
  • A partial section is accepted (the device merges it into the stored config).
  • The write is applied asynchronously — the ack returns at once but the change reaches /mnt/nand/config.xml (and get_config) a moment later.

Captured "Batch Set Title": code 525 = MediaConfig/Video/Overlay (OSD title + timestamp; title is hex-ASCII, 43616d657261 = "Camera"). Verified live by setting the OSD title to "Test" then back to "Camera".

Reads stay on the full-config download (get_config) — the device's per-section GET returned an empty body to every request form tried, so it is not used (also what the vendor tool does).

Changes

  • anjoy/comm.py: set_config_section (confirm-gated, GB2312-validated, echo-ack).
  • anjoy/const.py: CFG_OVERLAY = "525" and the section-code namespace (further codes added as captured).
  • tests/fake_server.py: SYSTEM_CONFIG_SET_MESSAGE branch (records config_sets).
  • tests/test_comm.py: frame/ack, confirm gate, non-GB2312 reject, round-trip (71 tests pass).
  • docs/devices.md: config-section-write block.

This is the foundation for the typed batch setters (title/time/encode/motion/AI/maintenance/platform) that follow.

AjDevTools' per-feature batch buttons write one config section at a time:
SYSTEM_CONFIG_SET_MESSAGE carries the section's numeric Msg_code and the
section element as the body; the device acks with the same type+code and an
empty body. A partial section is accepted (the device merges it), and the
write is applied asynchronously (it reaches /mnt/nand/config.xml a moment
after the ack).

Captured "Batch Set Title" against a live MTF45-4G_AF: code 525 =
MediaConfig/Video/Overlay (OSD title + timestamp; title is hex-ASCII).
Verified live by setting the OSD title to "Test" then back to "Camera".

Reads stay on the full-config download (get_config) — the device's
per-section GET returned an empty body to every request form tried, so it is
not used (which is also what the vendor tool does).

- anjoy/comm.py: set_config_section(code, body, confirm=True)
- anjoy/const.py: CFG_OVERLAY = "525" + the section-code namespace
- tests/fake_server.py: SYSTEM_CONFIG_SET branch (records config_sets)
- tests/test_comm.py: frame/ack, confirm gate, GB2312 reject, round-trip
- docs/devices.md: config section write block
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Add confirmed per-section camera configuration writes

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Adds confirmed, GB2312-safe writes for individual camera configuration sections.
• Defines the verified overlay section code and documents asynchronous merge semantics.
• Extends protocol simulation and tests for framing, acknowledgements, safety, and round trips.
Diagram

sequenceDiagram
    actor Caller
    participant Client as Comm Client
    participant Camera as Camera Server
    participant Store as Config Store
    Caller->>Client: Set section
    Client->>Client: Confirm and validate
    Client->>Camera: SET type and code
    Camera-->>Client: Empty-body ack
    Camera-->>Store: Merge asynchronously
    Client-->>Caller: Return ack
Loading
High-Level Assessment

A generic section-write primitive is the best foundation because it mirrors the captured vendor protocol while allowing typed feature setters to be layered on later. Implementing overlay-specific setters immediately would reduce reuse, while relying on per-section GET is unsuitable because hardware testing returned empty responses; retaining full-config downloads for reads is therefore appropriate.

Files changed (5) +127 / -0

Enhancement (2) +45 / -0
comm.pyAdd guarded config-section write primitive +33/-0

Add guarded config-section write primitive

• Adds 'set_config_section' to send partial section XML using 'SYSTEM_CONFIG_SET_MESSAGE' and wait for the matching type-and-code acknowledgement. Writes require explicit confirmation and reject bodies that cannot be encoded losslessly as GB2312.

anjoy/comm.py

const.pyDefine the verified overlay section code +12/-0

Define the verified overlay section code

• Introduces the 'CFG_*' section-code namespace and maps 'CFG_OVERLAY' to captured code '525'. Comments document partial merging, asynchronous persistence, and full-config reads.

anjoy/const.py

Tests (2) +53 / -0
fake_server.pySimulate config-set acknowledgements +12/-0

Simulate config-set acknowledgements

• Extends the fake camera server to recognize section-write messages, record their codes and bodies, and return matching empty-body acknowledgements.

tests/fake_server.py

test_comm.pyCover config-section write behavior +41/-0

Cover config-section write behavior

• Adds tests for outgoing framing and acknowledgement handling, the explicit confirmation gate, GB2312 rejection, and an end-to-end fake-server round trip.

tests/test_comm.py

Documentation (1) +29 / -0
devices.mdDocument config-section write protocol +29/-0

Document config-section write protocol

• Documents the captured request and acknowledgement behavior, asynchronous application, and confirmed overlay code. Includes a representative overlay payload and hardware verification details.

docs/devices.md

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Rejected writes can appear successful ✓ Resolved 🐞 Bug ≡ Correctness
Description
set_config_section delegates its acknowledgement check to _recv_until, which matches only
Msg_type and Msg_code and never enforces the documented empty MESSAGE_BODY. When the camera
returns the same type and code with a status or error payload, the method returns normally, so
callers can proceed as though the configuration change was accepted.
Code

anjoy/comm.py[402]

+        return self._recv_until("SYSTEM_CONFIG_SET_MESSAGE", code)
Evidence
The new method defines a successful acknowledgement as the same type and code with an empty body,
but _recv_until returns solely on header matches. The fake server covers only the empty-body
success response, leaving the non-empty matching-response path accepted by the production
implementation.

anjoy/comm.py[377-385]
anjoy/comm.py[281-294]
tests/fake_server.py[223-233]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`set_config_section` treats every response with the expected message type and code as success, although this protocol defines success specifically as an empty response body.
## Fix Focus Areas
- anjoy/comm.py[371-402]
- anjoy/comm.py[281-294]
- tests/test_comm.py[388-426]
## Recommended Fix
After `_recv_until` returns, parse the response envelope and verify that `MESSAGE_BODY` is empty, with no text or child elements. Raise `AnjoyError` for a non-empty body, and add a test proving that a matching type and code carrying a payload is rejected rather than returned as a successful acknowledgement.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can route each action level your way: inline, summary, both, or drop

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread anjoy/comm.py Outdated
Qodo review: success is defined as the same type+code with an EMPTY
MESSAGE_BODY, but the ack check delegated to _recv_until (which matches only
type+code). A device that replied with the matching type+code carrying an
error/status payload would be treated as success.

Parse the ack's MESSAGE_BODY after _recv_until; raise AnjoyError (surfacing the
payload) when it is non-empty. Add _message_body() helper + a test that a
matching-type/code frame with a payload is rejected.
@widgetii

Copy link
Copy Markdown
Member Author

Addressed the review finding in 92af268: set_config_section now parses the ack's MESSAGE_BODY after _recv_until and raises AnjoyError (surfacing the payload) when it is non-empty — success is strictly the same type+code with an empty body. Added a test that a matching-type/code frame carrying a payload is rejected.

@widgetii
widgetii merged commit be91ae7 into master Sep 22, 2026
6 checks passed
@widgetii
widgetii deleted the config-set-primitive branch September 22, 2026 16:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant