Skip to content

Read device element children by index, not through the broken DataSpan - #109

Closed
gunicsba wants to merge 1 commit into
developfrom
fix/element-child-ids
Closed

gunicsba wants to merge 1 commit into
developfrom
fix/element-child-ids

Conversation

@gunicsba

Copy link
Copy Markdown
Contributor

Summary

DeviceElementObject::get_child_object_ids() returns a DataSpan<const std::uint16_t>. AgIsoStack's DataSpan multiplies by sizeof(T) in end() and operator[], on top of the pointer arithmetic that already scales by sizeof(T):

T *end() const { return ptr + _size * sizeof(T); }   // utility/include/isobus/utility/data_span.hpp

For std::uint16_t, iterating it reads twice as many IDs as the element has children. The second half comes from past the end of the list, so whatever is in that memory can match an object ID. Checked with AgIsoStack's own deserializer: an element with 22 children yields 44 values, the last 22 of them junk.

All four TC loops that map DDIs to elements iterate this span (find_owning_element_number, the section parent lookup, and both measurement-subscription loops).

Field symptom

Local bench test with a Müller sprayer (11 sections, DDOP has DDI 160 only under element 2):

Subscribed (OnChange) to DDI 160 (Section Control State) for element 2
Subscribed (OnChange) to DDI 160 (Section Control State) for element 17
Subscribed (OnChange) to DDI 160 (Section Control State) for element 18
...
Sending set value to client 135 for DDI Section Control State element 18 with value Auto/on
Client 135 value command for element 2 DDI Section Control State with value Manual/off OK.

Elements 17 and 18 are plain sections that don't list the DDI 160 object. The TC wrote "automatic" to element 18, the sprayer stayed in manual on element 2, and it ignored every setpoint. Whether it happens depends on heap contents: the same sprayer mapped correctly with another build.

Change

One helper, get_child_object_ids(DeviceElementObject &), copies the IDs through get_number_child_objects() / get_child_object_id(i). AgIsoStack's own code uses those (DDOP helpers, TC client, ISOXML export). All four loops now use the helper.

Notes

  • The DataSpan bug itself should be fixed upstream in AgIsoStack. This PR doesn't depend on that fix and stays correct after it.
  • The helper's comment explains why not to go back to the span.

Testing

  • Release build passes on Windows (MSVC).
  • Decoded the Müller DDOP with AgIsoStack's deserializer, in the same 4 chunks as the upload: the indexed accessor returns exactly the listed children, and DDI 160/161/290 map to element 2 only.
  • To be confirmed on the bench: the sprayer reports Section Control State = Auto/on on element 2 and follows setpoints.

🤖 Generated with Claude Code

DeviceElementObject::get_child_object_ids() returns a
DataSpan<const std::uint16_t>, and AgIsoStack's DataSpan scales end() and
operator[] by sizeof(T) on top of the pointer arithmetic. Iterating it reads
twice as many IDs as the element has children; the second half comes from
past the end of the list. Whatever is in that memory can match an object ID.

All four TC loops that map DDIs to elements iterated it. On a Mueller sprayer
(11 sections), DDI 160 Section Control State was subscribed on elements 2, 17
and 18 although only element 2 lists it, and the TC wrote "automatic" to
element 18. The sprayer stayed in manual on element 2 and ignored every
setpoint. Whether it happens depends on heap contents, so the same implement
mapped correctly with another build.

Copy the child IDs through get_number_child_objects()/get_child_object_id(i),
which AgIsoStack's own code uses, in one helper used at all four sites.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@GwnDaan

GwnDaan commented Oct 14, 2026

Copy link
Copy Markdown
Collaborator

@gunicsba Let's fix the issue in agisostack itself instead :)

@gunicsba

Copy link
Copy Markdown
Contributor Author

@GwnDaan You want to fix it or should I ask Claude to do so?

@gunicsba
gunicsba marked this pull request as draft October 14, 2026 07:50
@gunicsba

gunicsba commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor Author

@GwnDaan Fix proposed upstream in Open-Agriculture/AgIsoStack-plus-plus#783: DataSpan now indexes in elements, not bytes. It includes tests, and CI is green. Once it's merged I'll turn this PR into a bump of the AgIsoStack GIT_TAG and drop the workaround.

@gunicsba

Copy link
Copy Markdown
Contributor Author

Closing in favour of the upstream fix, Open-Agriculture/AgIsoStack-plus-plus#783. #110 tracks bumping AgIsoStack once it's merged.

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.

2 participants