Skip to content

Implement command busy state tracking in the TaskControllerServer#689

Open
gunicsba wants to merge 2 commits into
Open-Agriculture:mainfrom
gunicsba:feat_tc_b6_state_tracking
Open

Implement command busy state tracking in the TaskControllerServer#689
gunicsba wants to merge 2 commits into
Open-Agriculture:mainfrom
gunicsba:feat_tc_b6_state_tracking

Conversation

@gunicsba

Copy link
Copy Markdown
Contributor

Summary

Implements B.6 command busy state tracking in the TaskControllerServer according to ISO 11783-10 B.8.1 specification. This feature informs ISOBUS clients when the server is busy executing device descriptor commands (ObjectPoolTransfer or ObjectPoolActivateDeactivate), preventing command collisions and improving protocol compliance.

We often have to restart the implements and there are still some that refuse to talk with us. I suspect it's because our TC status message prior to this change looked like we're busy with a DDOP upload from NULL_CAN_ADDRESS ECU.

Changes

Core Implementation

  • New Public API: set_b6_command_busy(bool isBusy, std::uint8_t clientAddress = 0, std::uint8_t commandByte = 0)
  • Constructor: Changed currentCommandSourceAddress initialization from NULL_CAN_ADDRESS to 0x00
  • ObjectPoolTransfer: Automatically sets busy state when receiving transfer commands, clears after processing
  • ObjectPoolActivateDeactivate: Automatically sets busy state during activate/deactivate operations, clears after completion
  • Client Timeout: Automatically clears busy state if the timed-out client was executing a B.6 command
  • Status Broadcast: Forces immediate TC Status message when busy state changes

ISO 11783-10 Compliance

Implements TC Status message format per B.8.1:

  • Byte 5 (currentCommandSourceAddress): CAN address of client executing B.6 command (0x00 when idle)
  • Byte 6 (currentCommandByte): B.6 command byte being executed (0x00 when idle)
  • Byte 7: Reserved (0xFF)

Testing

Added three comprehensive unit tests:

  1. B6CommandBusyStateTracking - Direct API testing
  2. B6CommandBusyState_ObjectPoolTransfer - Integration test for transfer commands
  3. B6CommandBusyState_ObjectPoolActivateDeactivate - Integration test for activate/deactivate commands

Files Modified

  • isobus/include/isobus/isobus/isobus_task_controller_server.hpp - Added public API
  • isobus/src/isobus_task_controller_server.cpp - Implementation
  • test/tc_server_tests.cpp - Unit tests

Benefits

✅ Prevents command collisions during DDOP operations
✅ Improves ISOBUS protocol compliance
✅ Better client-server coordination
✅ Automatic cleanup on timeout scenarios
✅ Fully backward compatible (no breaking changes)

Testing

  • All existing TC server tests pass
  • New unit tests verify busy state lifecycle
  • Manual testing with ISOBUS clients recommended

References

  • ISO 11783-10:2015 Section B.6 (Device Descriptor Messages)
  • ISO 11783-10:2015 Section B.8.1 (TC Status Message)

Comment thread isobus/include/isobus/isobus/isobus_task_controller_server.hpp Outdated
numberChannelsSupportedForPositionBasedControlToReport(numberChannelsSupportedForPositionBasedControl),
optionsBitfieldToReport(options.get_bitfield())
optionsBitfieldToReport(options.get_bitfield()),
currentCommandSourceAddress(0x00)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mentioned in another comment, but 0 is a bad default, since G.2 of the ISO doc specifies explicitly that it should be FF, FE, or the address of the VT when no command is executing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ISO_11783-10_2015(en).pdf Annex B 8.2 says otherwise.

Comment thread isobus/src/isobus_task_controller_server.cpp Outdated
@gunicsba

Copy link
Copy Markdown
Contributor Author

@ad3154 I fortunately have some logs of 2 different John Deere tractors. SF3000 and 6000 antennas one of them even had an ISOBUS sprayer attached.

I asked chatgpt to analyse the logs and see what status they send. Here's the result:

Task Controller Status bytes 6–8: comparison with John Deere / Valtra logs

I checked several CAN logs from John Deere / Valtra systems to see what real OEM Task Controllers send for the Task Controller Status Process Data message.

The relevant message is:

PGN: 0x00CB00 / Process Data
DA: 0xFF global
Command: 0xE = Task Controller Status

Observed OEM TC Status frames

From Valtra SmartTouch:

ID = 0x0CCBFFF7
Data = FE FF FF FF 00 00 00 00

From John Deere Task Controllers, identified by Address Claim NAME:

manufacturer = 33
function = 130 // Task Controller

Observed TC Status payloads:

FE FF FF FF 00 00 00 00
FE FF FF FF 01 00 00 00

So JD / Valtra appear to use:

Byte 1 = FE // element number high nibble not available + TC Status command 0xE
Byte 2 = FF // element number low byte not available
Byte 3 = FF // DDI low byte not available
Byte 4 = FF // DDI high byte not available
Byte 5 = TC/DL status
Byte 6 = 00
Byte 7 = 00
Byte 8 = 00

when the TC is not currently reporting an active B.6 / DDOP command.

Comparison with current AOG / AgIsoStack behaviour

In our logs we saw two TC Status-like frames from the same TC source address:

0x0CCBFFF7 FE FF FF FF 01 FE 00 FF
0x18CBFFF7 FE FF FF FF 01 00 00 FF

The first four bytes match the OEM pattern:

FE FF FF FF

But bytes 5–8 differ.

The suspicious one is:

FE FF FF FF 01 FE 00 FF

Here:

Byte 5 = 01 // task totals active
Byte 6 = FE // looks like "not available" / null address
Byte 7 = 00
Byte 8 = FF

This does not match the JD / Valtra logs I checked.

About byte 6 and "0x00 could be a valid CAN source address"

I agree that "0x00" should not be used as a "no client" sentinel if byte 6 is currently valid, because "0x00" can be a valid CAN source address.

However, the OEM logs suggest a different interpretation:

If the TC is not busy with a B.6 / DDOP command:
Byte 5 busy/B.6-active bit is not set
Byte 6 = 00
Byte 7 = 00
Byte 8 = 00

In that state, byte 6 and byte 7 are not meaningful because the status byte does not mark them as active/valid.

Only when the TC status indicates that it is busy executing a B.6 / DDOP command should byte 6 and byte 7 carry meaningful values:

If the TC is busy with a B.6 / DDOP command:
Byte 5 busy/B.6-active bit set
Byte 6 = actual client source address
Byte 7 = actual B.6 command
Byte 8 = 00

So the concern about "0x00" being a valid source address is valid for the busy/active case, but JD / Valtra still appear to use "00 00 00" for bytes 6–8 when no B.6 command is active.

Suggested payloads

Idle / no active task totals:

FE FF FF FF 00 00 00 00

Compatibility mode / task totals active:

FE FF FF FF 01 00 00 00

Busy with a B.6 / DDOP command:

FE FF FF FF 00

Recommendation

I think we should stop sending:

FE FF FF FF 01 FE 00 FF

and instead align with the OEM behaviour:

FE FF FF FF 00 00 00 00

or, if we intentionally want to advertise task totals active:

FE FF FF FF 01 00 00 00

The main point is that byte 6 should not be "0xFE" unless the status byte says the B.6 command fields are valid, and byte 8 should likely be "0x00", matching the JD / Valtra examples.

@gunicsba gunicsba requested a review from ad3154 May 31, 2026 12:44
@gunicsba gunicsba changed the title Implement B.6 command busy state tracking in the TaskControllerServer Implement command busy state tracking in the TaskControllerServer May 31, 2026
@gunicsba

gunicsba commented Jun 6, 2026

Copy link
Copy Markdown
Contributor Author

Although I'm yet to hear back from users who had problems but all my tests are positive. No matter when I start the TC the implements connect to it well. In fact sometimes they connect before they are loaded to the VT.

@gunicsba gunicsba force-pushed the feat_tc_b6_state_tracking branch from 46f13f6 to 28b4573 Compare June 7, 2026 17:09
Implement command busy state tracking in TC Status message (Bytes 5-7):
- Add set_command_busy() API to track when server is executing commands
- Track currentCommandSourceAddress and currentCommandByte
- Set busy state during ObjectPoolTransfer and ObjectPoolActivateDeactivate
- Clear busy state after command processing or on client timeout
- Use flag-based status update scheduling (statusUpdatePending)
- Enforce 200ms minimum interval between status messages (ISO compliant)
- Fix MessageEncoding test expectations for Bytes 5-7

This implementation is ISO 11783-10 compliant for TC Status message
Bytes 5-7 (currentCommandSourceAddress, currentCommandByte).
@gunicsba gunicsba force-pushed the feat_tc_b6_state_tracking branch from 28b4573 to dfb1e5f Compare June 7, 2026 18:46
@gunicsba

Copy link
Copy Markdown
Contributor Author

@ad3154 could you please review this?
I tried to clean up the code as much as we can

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