14#include "isobus/utility/system_timing.hpp"
15#include "isobus/utility/to_string.hpp"
21#if !defined CAN_STACK_DISABLE_THREADS && !defined ARDUINO
28 languageCommandInterface(clientSource, partner),
29 partnerControlFunction(partner),
30 myControlFunction(clientSource),
31 primaryVirtualTerminal(primaryVT)
63#if !defined CAN_STACK_DISABLE_THREADS && !defined ARDUINO
116 std::uint8_t maxNumberBoomsSupported,
117 std::uint8_t maxNumberSectionsSupported,
118 std::uint8_t maxNumberChannelsSupportedForPositionBasedControl,
119 bool reportToTCSupportsDocumentation,
120 bool reportToTCSupportsTCGEOWithoutPositionBasedControl,
121 bool reportToTCSupportsTCGEOWithPositionBasedControl,
122 bool reportToTCSupportsPeerControlAssignment,
123 bool reportToTCSupportsImplementSectionControl)
127 assert(
nullptr != DDOP);
137 maxNumberSectionsSupported,
138 maxNumberChannelsSupportedForPositionBasedControl,
139 reportToTCSupportsDocumentation,
140 reportToTCSupportsTCGEOWithoutPositionBasedControl,
141 reportToTCSupportsTCGEOWithPositionBasedControl,
142 reportToTCSupportsPeerControlAssignment,
143 reportToTCSupportsImplementSectionControl);
148 LOG_ERROR(
"[TC]: Cannot reconfigure TC client while it is running!");
153 std::uint32_t DDOPSize,
154 std::uint8_t maxNumberBoomsSupported,
155 std::uint8_t maxNumberSectionsSupported,
156 std::uint8_t maxNumberChannelsSupportedForPositionBasedControl,
157 bool reportToTCSupportsDocumentation,
158 bool reportToTCSupportsTCGEOWithoutPositionBasedControl,
159 bool reportToTCSupportsTCGEOWithPositionBasedControl,
160 bool reportToTCSupportsPeerControlAssignment,
161 bool reportToTCSupportsImplementSectionControl)
165 assert(
nullptr != binaryDDOP);
166 assert(0 != DDOPSize);
175 maxNumberSectionsSupported,
176 maxNumberChannelsSupportedForPositionBasedControl,
177 reportToTCSupportsDocumentation,
178 reportToTCSupportsTCGEOWithoutPositionBasedControl,
179 reportToTCSupportsTCGEOWithPositionBasedControl,
180 reportToTCSupportsPeerControlAssignment,
181 reportToTCSupportsImplementSectionControl);
186 LOG_ERROR(
"[TC]: Cannot reconfigure TC client while it is running!");
191 std::uint8_t maxNumberBoomsSupported,
192 std::uint8_t maxNumberSectionsSupported,
193 std::uint8_t maxNumberChannelsSupportedForPositionBasedControl,
194 bool reportToTCSupportsDocumentation,
195 bool reportToTCSupportsTCGEOWithoutPositionBasedControl,
196 bool reportToTCSupportsTCGEOWithPositionBasedControl,
197 bool reportToTCSupportsPeerControlAssignment,
198 bool reportToTCSupportsImplementSectionControl)
202 assert(
nullptr != binaryDDOP);
211 maxNumberSectionsSupported,
212 maxNumberChannelsSupportedForPositionBasedControl,
213 reportToTCSupportsDocumentation,
214 reportToTCSupportsTCGEOWithoutPositionBasedControl,
215 reportToTCSupportsTCGEOWithPositionBasedControl,
216 reportToTCSupportsPeerControlAssignment,
217 reportToTCSupportsImplementSectionControl);
222 LOG_ERROR(
"[TC]: Cannot reconfigure TC client while it is running!");
248#if !defined CAN_STACK_DISABLE_THREADS && !defined ARDUINO
331 assert(
nullptr != binaryDDOP);
332 assert(!binaryDDOP->empty());
344 LOG_INFO(
"[TC]: Requested to change the DDOP. Object pool will be deactivated for a little while.");
356 assert(
nullptr != binaryDDOP);
357 assert(0 != DDOPSize);
369 LOG_INFO(
"[TC]: Requested to change the DDOP. Object pool will be deactivated for a little while.");
381 assert(
nullptr != DDOP);
394 LOG_INFO(
"[TC]: Requested to change the DDOP. Object pool will be deactivated for a little while.");
419 LOG_DEBUG(
"[TC]: Startup delay complete, waiting for TC server status message.");
433 LOG_ERROR(
"[TC]: Timeout sending working set master message. Resetting client connection.");
450 LOG_ERROR(
"[TC]: Timeout sending first status message. Resetting client connection.");
464 LOG_ERROR(
"[TC]: Timeout sending version request message. Resetting client connection.");
474 LOG_ERROR(
"[TC]: Timeout waiting for version request response. Resetting client connection.");
484 LOG_WARNING(
"[TC]: Timeout waiting for version request from TC. This is not required, so proceeding anways.");
500 LOG_ERROR(
"[TC]: Timeout sending version request response. Resetting client connection.");
515 LOG_ERROR(
"[TC]: Timeout trying to send request for language command message. Resetting client connection.");
530 LOG_WARNING(
"[TC]: Timeout waiting for language response. Moving on to processing the DDOP anyways.");
536 LOG_WARNING(
"[TC]: No response to our request for the language command data, which is unusual.");
540 LOG_WARNING(
"[TC]: Falling back to VT for language data.");
547 LOG_WARNING(
"[TC]: Since no VT was specified, falling back to a global request for language data.");
562 if (serverVersion < clientDDOP->get_task_controller_compatibility_level())
565 LOG_INFO(
"[TC]: DDOP will be generated using the server's version instead of the specified version. New version: " +
575 LOG_DEBUG(
"[TC]: DDOP Generated, size: " + isobus::to_string(
static_cast<int>(
generatedBinaryDDOP.size())));
579 LOG_ERROR(
"[TC]: You didn't properly update your new DDOP's structure label. ISO11783-10 states that an update to an object pool must include an updated structure label.");
587 LOG_ERROR(
"[TC]: Cannot proceed with connection to TC due to invalid DDOP. Check log for [DDOP] events. TC client will now terminate.");
593 LOG_DEBUG(
"[TC]: Using previously generated DDOP binary");
602 LOG_DEBUG(
"[TC]: Beginning a search of pre-serialized DDOP for device structure and localization labels.");
608 LOG_ERROR(
"[TC]: Failed to parse the DDOP. Ensure you provided a valid device object. TC client will now terminate.");
614 LOG_DEBUG(
"[TC]: Reusing previously located device labels.");
629 LOG_ERROR(
"[TC]: Timeout trying to send request for TC structure label. Resetting client connection.");
639 LOG_ERROR(
"[TC]: Timeout waiting for TC structure label. Resetting client connection.");
653 LOG_ERROR(
"[TC]: Timeout trying to send request for TC localization label. Resetting client connection.");
663 LOG_ERROR(
"[TC]: Timeout waiting for TC localization label. Resetting client connection.");
677 LOG_ERROR(
"[TC]: Timeout trying to send delete object pool message. Resetting client connection.");
687 LOG_ERROR(
"[TC]: Timeout waiting for delete object pool response. Resetting client connection.");
701 LOG_ERROR(
"[TC]: Timeout trying to send request to transfer object pool. Resetting client connection.");
711 LOG_ERROR(
"[TC]: Timeout waiting for request transfer object pool response. Resetting client connection.");
719 bool transmitSuccessful =
false;
720 std::uint32_t dataLength = 0;
746 assert(0 != dataLength);
756 if (transmitSuccessful)
762 LOG_ERROR(
"[TC]: Timeout trying to begin the object pool upload. Resetting client connection.");
779 LOG_ERROR(
"[TC]: Timeout waiting for object pool transfer response. Resetting client connection.");
793 LOG_ERROR(
"[TC]: Timeout trying to activate object pool. Resetting client connection.");
803 LOG_ERROR(
"[TC]: Timeout waiting for activate object pool response. Resetting client connection.");
813 LOG_ERROR(
"[TC]: Server Status Message Timeout. The TC may be offline.");
832 LOG_ERROR(
"[TC]: Timeout sending object pool deactivate. Client terminated.");
845 LOG_WARNING(
"[TC]: Timeout waiting for deactivate object pool response. This is unusual, but we're just going to reconnect anyways.");
851 LOG_ERROR(
"[TC]: Timeout waiting for deactivate object pool response. Client terminated.");
876 return ((obj.
ddi == this->ddi) && (obj.
elementNumber == this->elementNumber));
881 return (obj.
callback == this->callback) && (obj.
parent == this->parent);
886 return (obj.
callback == this->callback) && (obj.
parent == this->parent);
933 std::uint32_t currentByteIndex = 0;
934 const std::string DEVICE_TABLE_ID =
"DVC";
935 constexpr std::uint8_t DESIGNATOR_BYTE_OFFSET = 5;
936 constexpr std::uint8_t CLIENT_NAME_LENGTH = 8;
944 auto deviceObject =
clientDDOP->get_object_by_id(0);
945 assert(
nullptr != deviceObject);
948 ddopStructureLabel = std::static_pointer_cast<task_controller_object::DeviceObject>(deviceObject)->get_structure_label();
955 ddopLocalizationLabel = std::static_pointer_cast<task_controller_object::DeviceObject>(deviceObject)->get_localization_label();
962 auto getDDOPSize = [
this]() {
973 auto getDDOPByteAt = [
this](std::size_t index) {
984 while (currentByteIndex < (getDDOPSize() - DEVICE_TABLE_ID.size()))
986 if ((DEVICE_TABLE_ID[0] == getDDOPByteAt(currentByteIndex)) &&
987 (DEVICE_TABLE_ID[1] == getDDOPByteAt(currentByteIndex + 1)) &&
988 (DEVICE_TABLE_ID[2] == getDDOPByteAt(currentByteIndex + 2)))
994 assert((currentByteIndex + DESIGNATOR_BYTE_OFFSET) < getDDOPSize());
995 currentByteIndex += DESIGNATOR_BYTE_OFFSET;
997 const std::uint32_t DESIGNATOR_LENGTH = getDDOPByteAt(currentByteIndex);
998 assert(currentByteIndex + DESIGNATOR_LENGTH < getDDOPSize());
999 currentByteIndex += DESIGNATOR_LENGTH + 1;
1001 const std::uint32_t SOFTWARE_VERSION_LENGTH = getDDOPByteAt(currentByteIndex);
1002 assert(currentByteIndex + SOFTWARE_VERSION_LENGTH + CLIENT_NAME_LENGTH < getDDOPSize());
1003 currentByteIndex += SOFTWARE_VERSION_LENGTH + CLIENT_NAME_LENGTH + 1;
1005 const std::uint32_t SERIAL_NUMBER_LENGTH = getDDOPByteAt(currentByteIndex);
1006 assert(currentByteIndex + SERIAL_NUMBER_LENGTH < getDDOPSize());
1007 currentByteIndex += SERIAL_NUMBER_LENGTH + 1;
1035 bool transmitSuccessful =
true;
1043 std::int32_t newValue = 0;
1044 if (currentCallback.callback(currentRequest.elementNumber, currentRequest.ddi, newValue, currentCallback.parent))
1046 transmitSuccessful =
send_value_command(currentRequest.elementNumber, currentRequest.ddi, newValue);
1058 if (currentCallback.callback(currentRequest.elementNumber, currentRequest.ddi, currentRequest.processDataValue, currentCallback.parent))
1066 if (currentRequest.ackRequested)
1068 transmitSuccessful =
send_pdack(currentRequest.elementNumber, currentRequest.ddi);
1075 bool transmitSuccessful =
false;
1079 if (SystemTiming::time_expired_ms(
static_cast<std::uint32_t
>(measurementTimeCommand.lastValue),
static_cast<std::uint32_t
>(measurementTimeCommand.processDataValue)))
1082 transmitSuccessful =
false;
1085 std::int32_t newValue = 0;
1086 if (currentCallback.callback(measurementTimeCommand.elementNumber, measurementTimeCommand.ddi, newValue, currentCallback.parent))
1088 transmitSuccessful =
send_value_command(measurementTimeCommand.elementNumber, measurementTimeCommand.ddi, newValue);
1093 if (transmitSuccessful)
1095 measurementTimeCommand.lastValue =
static_cast<std::int32_t
>(SystemTiming::get_timestamp_ms());
1102 std::int32_t newValue = 0;
1105 if (currentCallback.callback(measurementMaxCommand.elementNumber, measurementMaxCommand.ddi, newValue, currentCallback.parent))
1111 if (!measurementMaxCommand.thresholdPassed)
1113 if ((newValue > measurementMaxCommand.processDataValue) &&
1114 (
send_value_command(measurementMaxCommand.elementNumber, measurementMaxCommand.ddi, newValue)))
1116 measurementMaxCommand.thresholdPassed =
true;
1121 if (newValue < measurementMaxCommand.processDataValue)
1123 measurementMaxCommand.thresholdPassed =
false;
1130 std::int32_t newValue = 0;
1133 if (currentCallback.callback(measurementMinCommand.elementNumber, measurementMinCommand.ddi, newValue, currentCallback.parent))
1139 if (!measurementMinCommand.thresholdPassed)
1141 if ((newValue < measurementMinCommand.processDataValue) &&
1142 (
send_value_command(measurementMinCommand.elementNumber, measurementMinCommand.ddi, newValue)))
1144 measurementMinCommand.thresholdPassed =
true;
1149 if (newValue > measurementMinCommand.processDataValue)
1151 measurementMinCommand.thresholdPassed =
false;
1158 std::int32_t newValue = 0;
1161 if (currentCallback.callback(measurementChangeCommand.elementNumber, measurementChangeCommand.ddi, newValue, currentCallback.parent))
1167 std::int64_t lowerLimit = (
static_cast<int64_t
>(measurementChangeCommand.lastValue) - measurementChangeCommand.processDataValue);
1173 if ((newValue != measurementChangeCommand.lastValue) &&
1174 ((newValue >= (measurementChangeCommand.lastValue + measurementChangeCommand.processDataValue)) ||
1175 (newValue <= lowerLimit)))
1177 if (
send_value_command(measurementChangeCommand.elementNumber, measurementChangeCommand.ddi, newValue))
1179 measurementChangeCommand.lastValue = newValue;
1187 if ((
nullptr != parentPointer) &&
1193 const auto &messageData = message.
get_data();
1197 case static_cast<std::uint32_t
>(CANLibParameterGroupNumber::Acknowledge):
1201 std::uint32_t targetParameterGroupNumber = message.
get_uint24_at(5);
1202 if (
static_cast<std::uint32_t
>(CANLibParameterGroupNumber::ProcessData) == targetParameterGroupNumber)
1204 LOG_ERROR(
"[TC]: The TC Server is NACK-ing our messages. Disconnecting.");
1211 case static_cast<std::uint32_t
>(CANLibParameterGroupNumber::ProcessData):
1227 LOG_WARNING(
"[TC]: Server requested version information at a strange time.");
1234 parentTC->serverVersion = messageData[1];
1235 parentTC->maxServerBootTime_s = messageData[2];
1236 parentTC->serverOptionsByte1 = messageData[3];
1237 parentTC->serverOptionsByte2 = messageData[4];
1238 parentTC->serverNumberOfBoomsForSectionControl = messageData[5];
1239 parentTC->serverNumberOfSectionsForSectionControl = messageData[6];
1240 parentTC->serverNumberOfChannelsForPositionBasedControl = messageData[7];
1244 LOG_WARNING(
"[TC]: Server version is newer than client's maximum supported version.");
1246 LOG_DEBUG(
"[TC]: TC Server supports version %u with %u booms, %u sections, and %u position based control channels.",
1261 LOG_WARNING(
"[TC]: Unsupported process data technical data message received. Message will be dropped.");
1276 if ((0xFF == messageData[1]) &&
1277 (0xFF == messageData[2]) &&
1278 (0xFF == messageData[3]) &&
1279 (0xFF == messageData[4]) &&
1280 (0xFF == messageData[5]) &&
1281 (0xFF == messageData[6]) &&
1282 (0xFF == messageData[7]) &&
1290 std::string tcStructure;
1292 for (std::size_t i = 1; i < messageData.size(); i++)
1294 tcStructure.push_back(messageData[i]);
1297 if (tcStructure.size() > 40)
1299 LOG_WARNING(
"[TC]: Structure Label from TC exceeds the max length allowed by ISO11783-10");
1302 if (parentTC->ddopStructureLabel == tcStructure)
1305 LOG_DEBUG(
"[TC]: Task controller structure labels match");
1311 LOG_INFO(
"[TC]: Task controller structure labels do not match. DDOP will be deleted and reuploaded.");
1318 LOG_WARNING(
"[TC]: Structure label message received, but ignored due to current state machine state.");
1330 if ((0xFF == messageData[1]) &&
1331 (0xFF == messageData[2]) &&
1332 (0xFF == messageData[3]) &&
1333 (0xFF == messageData[4]) &&
1334 (0xFF == messageData[5]) &&
1335 (0xFF == messageData[6]) &&
1336 (0xFF == messageData[7]) &&
1344 assert(7 == parentTC->ddopLocalizationLabel.size());
1345 bool labelsMatch =
true;
1349 if (messageData[i + 1] != parentTC->ddopLocalizationLabel[i])
1351 labelsMatch =
false;
1359 LOG_DEBUG(
"[TC]: Task controller localization labels match");
1365 LOG_INFO(
"[TC]: Task controller localization labels do not match. DDOP will be deleted and reuploaded.");
1372 LOG_WARNING(
"[TC]: Localization label message received, but ignored due to current state machine state.");
1381 if (0 == messageData[1])
1384 LOG_DEBUG(
"[TC]: Server indicates there may be enough memory available.");
1389 LOG_ERROR(
"[TC]: Server states that there is not enough memory available for our DDOP. Client will terminate.");
1390 parentTC->terminate();
1395 LOG_WARNING(
"[TC]: Request Object-pool Transfer Response message received, but ignored due to current state machine state.");
1404 if (0 == messageData[1])
1406 LOG_INFO(
"[TC]: DDOP Activated without error.");
1411 LOG_ERROR(
"[TC]: DDOP was not activated.");
1412 if (0x01 & messageData[1])
1414 LOG_ERROR(
"[TC]: There are errors in the DDOP. Faulting parent ID: " +
1415 isobus::to_string(
static_cast<int>(
static_cast<std::uint16_t
>(messageData[2]) |
1416 static_cast<std::uint16_t
>(messageData[3] << 8))) +
1417 " Faulting object: " +
1418 isobus::to_string(
static_cast<int>(
static_cast<std::uint16_t
>(messageData[4]) |
1419 static_cast<std::uint16_t
>(messageData[5] << 8))));
1420 if (0x01 & messageData[6])
1422 LOG_ERROR(
"[TC]: Method or attribute not supported by the TC");
1424 if (0x02 & messageData[6])
1426 LOG_ERROR(
"[TC]: Unknown object reference (missing object)");
1428 if (0x04 & messageData[6])
1430 LOG_ERROR(
"[TC]: Unknown error (Any other error)");
1432 if (0x08 & messageData[6])
1434 LOG_ERROR(
"[TC]: Device descriptor object pool was deleted from volatile memory");
1436 if (0xF0 & messageData[6])
1438 LOG_WARNING(
"[TC]: The TC sent illegal errors in the reserved bits of the response.");
1441 if (0x02 & messageData[1])
1443 LOG_ERROR(
"[TC]: Task Controller ran out of memory during activation.");
1445 if (0x04 & messageData[1])
1447 LOG_ERROR(
"[TC]: Task Controller indicates an unknown error occurred.");
1449 if (0x08 & messageData[1])
1451 LOG_ERROR(
"[TC]: A different DDOP with the same structure label already exists in the TC.");
1453 if (0xF0 & messageData[1])
1455 LOG_WARNING(
"[TC]: The TC sent illegal errors in the reserved bits of the response.");
1458 LOG_ERROR(
"[TC]: Client terminated.");
1459 parentTC->terminate();
1464 if (0 == messageData[1])
1466 LOG_INFO(
"[TC]: Object pool deactivated OK.");
1468 if (parentTC->shouldReuploadAfterDDOPDeletion)
1475 LOG_ERROR(
"[TC]: Object pool deactivation error.");
1480 LOG_WARNING(
"[TC]: Object pool activate/deactivate response received at a strange time. Message dropped.");
1500 if (0 == messageData[1])
1502 LOG_DEBUG(
"[TC]: DDOP upload completed with no errors.");
1507 if (0x01 == messageData[1])
1509 LOG_ERROR(
"[TC]: DDOP upload completed but TC ran out of memory during transfer.");
1513 LOG_ERROR(
"[TC]: DDOP upload completed but TC had some unknown error.");
1515 LOG_ERROR(
"[TC]: Client terminated.");
1516 parentTC->terminate();
1521 LOG_WARNING(
"[TC]: Recieved unexpected object pool transfer response");
1528 LOG_WARNING(
"[TC]: Unsupported device descriptor command message received. Message will be dropped.");
1542 parentTC->tcStatusBitfield = messageData[4];
1543 parentTC->sourceAddressOfCommandBeingExecuted = messageData[5];
1544 parentTC->commandBeingExecuted = messageData[6];
1545 parentTC->serverStatusMessageTimestamp_ms = SystemTiming::get_timestamp_ms();
1556 LOG_WARNING(
"[TC]: Server sent the client task message, which is not meant to be sent by servers.");
1566 requestData.
elementNumber = (
static_cast<std::uint16_t
>(messageData[0] >> 4) | (
static_cast<std::uint16_t
>(messageData[1]) << 4));
1567 requestData.
ddi =
static_cast<std::uint16_t
>(messageData[2]) |
1568 (
static_cast<std::uint16_t
>(messageData[3]) << 8);
1569 requestData.
processDataValue = (
static_cast<std::int32_t
>(messageData[4]) |
1570 (
static_cast<std::int32_t
>(messageData[5]) << 8) |
1571 (
static_cast<std::int32_t
>(messageData[6]) << 16) |
1572 (
static_cast<std::int32_t
>(messageData[7]) << 24));
1573 parentTC->queuedValueRequests.push_back(requestData);
1583 requestData.
elementNumber = (
static_cast<std::uint16_t
>(messageData[0] >> 4) | (
static_cast<std::uint16_t
>(messageData[1]) << 4));
1584 requestData.
ddi =
static_cast<std::uint16_t
>(messageData[2]) |
1585 (
static_cast<std::uint16_t
>(messageData[3]) << 8);
1586 requestData.
processDataValue = (
static_cast<std::int32_t
>(messageData[4]) |
1587 (
static_cast<std::int32_t
>(messageData[5]) << 8) |
1588 (
static_cast<std::int32_t
>(messageData[6]) << 16) |
1589 (
static_cast<std::int32_t
>(messageData[7]) << 24));
1590 parentTC->queuedValueCommands.push_back(requestData);
1600 requestData.
elementNumber = (
static_cast<std::uint16_t
>(messageData[0] >> 4) | (
static_cast<std::uint16_t
>(messageData[1]) << 4));
1601 requestData.
ddi =
static_cast<std::uint16_t
>(messageData[2]) |
1602 (
static_cast<std::uint16_t
>(messageData[3]) << 8);
1603 requestData.
processDataValue = (
static_cast<std::int32_t
>(messageData[4]) |
1604 (
static_cast<std::int32_t
>(messageData[5]) << 8) |
1605 (
static_cast<std::int32_t
>(messageData[6]) << 16) |
1606 (
static_cast<std::int32_t
>(messageData[7]) << 24));
1607 parentTC->queuedValueCommands.push_back(requestData);
1616 commandData.
elementNumber = (
static_cast<std::uint16_t
>(messageData[0] >> 4) | (
static_cast<std::uint16_t
>(messageData[1]) << 4));
1617 commandData.
ddi =
static_cast<std::uint16_t
>(messageData[2]) |
1618 (
static_cast<std::uint16_t
>(messageData[3]) << 8);
1619 commandData.
processDataValue = (
static_cast<std::int32_t
>(messageData[4]) |
1620 (
static_cast<std::int32_t
>(messageData[5]) << 8) |
1621 (
static_cast<std::int32_t
>(messageData[6]) << 16) |
1622 (
static_cast<std::int32_t
>(messageData[7]) << 24));
1623 commandData.
lastValue =
static_cast<std::int32_t
>(SystemTiming::get_timestamp_ms());
1625 auto previousCommand = std::find(parentTC->measurementTimeIntervalCommands.begin(), parentTC->measurementTimeIntervalCommands.end(), commandData);
1626 if (parentTC->measurementTimeIntervalCommands.end() == previousCommand)
1628 parentTC->measurementTimeIntervalCommands.push_back(commandData);
1629 LOG_DEBUG(
"[TC]: TC Requests element: " +
1630 isobus::to_string(
static_cast<int>(commandData.
elementNumber)) +
1632 isobus::to_string(
static_cast<int>(commandData.
ddi)) +
1641 LOG_DEBUG(
"[TC]: TC Altered time interval request for element: " +
1642 isobus::to_string(
static_cast<int>(commandData.
elementNumber)) +
1644 isobus::to_string(
static_cast<int>(commandData.
ddi)) +
1657 commandData.
elementNumber = (
static_cast<std::uint16_t
>(messageData[0] >> 4) | (
static_cast<std::uint16_t
>(messageData[1]) << 4));
1658 commandData.
ddi =
static_cast<std::uint16_t
>(messageData[2]) |
1659 (
static_cast<std::uint16_t
>(messageData[3]) << 8);
1660 commandData.
processDataValue = (
static_cast<std::int32_t
>(messageData[4]) |
1661 (
static_cast<std::int32_t
>(messageData[5]) << 8) |
1662 (
static_cast<std::int32_t
>(messageData[6]) << 16) |
1663 (
static_cast<std::int32_t
>(messageData[7]) << 24));
1665 auto previousCommand = std::find(parentTC->measurementMaximumThresholdCommands.begin(), parentTC->measurementMaximumThresholdCommands.end(), commandData);
1666 if (parentTC->measurementMaximumThresholdCommands.end() == previousCommand)
1668 parentTC->measurementMaximumThresholdCommands.push_back(commandData);
1669 LOG_DEBUG(
"[TC]: TC Requests element: " +
1670 isobus::to_string(
static_cast<int>(commandData.
elementNumber)) +
1672 isobus::to_string(
static_cast<int>(commandData.
ddi)) +
1673 " when it is above the raw value: " +
1680 previousCommand->thresholdPassed =
false;
1690 commandData.
elementNumber = (
static_cast<std::uint16_t
>(messageData[0] >> 4) | (
static_cast<std::uint16_t
>(messageData[1]) << 4));
1691 commandData.
ddi =
static_cast<std::uint16_t
>(messageData[2]) |
1692 (
static_cast<std::uint16_t
>(messageData[3]) << 8);
1693 commandData.
processDataValue = (
static_cast<std::int32_t
>(messageData[4]) |
1694 (
static_cast<std::int32_t
>(messageData[5]) << 8) |
1695 (
static_cast<std::int32_t
>(messageData[6]) << 16) |
1696 (
static_cast<std::int32_t
>(messageData[7]) << 24));
1698 auto previousCommand = std::find(parentTC->measurementMinimumThresholdCommands.begin(), parentTC->measurementMinimumThresholdCommands.end(), commandData);
1699 if (parentTC->measurementMinimumThresholdCommands.end() == previousCommand)
1701 parentTC->measurementMinimumThresholdCommands.push_back(commandData);
1702 LOG_DEBUG(
"[TC]: TC Requests Element " +
1703 isobus::to_string(
static_cast<int>(commandData.
elementNumber)) +
1705 isobus::to_string(
static_cast<int>(commandData.
ddi)) +
1706 " when it is below the raw value: " +
1713 previousCommand->thresholdPassed =
false;
1723 commandData.
elementNumber = (
static_cast<std::uint16_t
>(messageData[0] >> 4) | (
static_cast<std::uint16_t
>(messageData[1]) << 4));
1724 commandData.
ddi =
static_cast<std::uint16_t
>(messageData[2]) |
1725 (
static_cast<std::uint16_t
>(messageData[3]) << 8);
1726 commandData.
processDataValue = (
static_cast<std::int32_t
>(messageData[4]) |
1727 (
static_cast<std::int32_t
>(messageData[5]) << 8) |
1728 (
static_cast<std::int32_t
>(messageData[6]) << 16) |
1729 (
static_cast<std::int32_t
>(messageData[7]) << 24));
1731 auto previousCommand = std::find(parentTC->measurementOnChangeThresholdCommands.begin(), parentTC->measurementOnChangeThresholdCommands.end(), commandData);
1732 if (parentTC->measurementOnChangeThresholdCommands.end() == previousCommand)
1734 parentTC->measurementOnChangeThresholdCommands.push_back(commandData);
1735 LOG_DEBUG(
"[TC]: TC Requests element " +
1736 isobus::to_string(
static_cast<int>(commandData.
elementNumber)) +
1738 isobus::to_string(
static_cast<int>(commandData.
ddi)) +
1739 " on change by at least: " +
1746 previousCommand->thresholdPassed =
false;
1753 if (0 != messageData[4])
1755 LOG_WARNING(
"[TC]: TC sent us a PDNACK");
1762 LOG_WARNING(
"[TC]: Unhandled process data message!");
1778 std::uint32_t bytesOffset,
1779 std::uint32_t numberOfBytesNeeded,
1780 std::uint8_t *chunkBuffer,
1781 void *parentPointer)
1784 bool retVal =
false;
1788 assert(
nullptr != parentTCClient);
1789 assert(
nullptr != chunkBuffer);
1790 assert(0 != numberOfBytesNeeded);
1792 if (((bytesOffset + numberOfBytesNeeded) <= parentTCClient->generatedBinaryDDOP.size() + 1) ||
1793 ((bytesOffset + numberOfBytesNeeded) <= parentTCClient->userSuppliedBinaryDDOPSize_bytes + 1))
1796 if (0 == bytesOffset)
1803 memcpy(&chunkBuffer[1], &parentTCClient->userSuppliedBinaryDDOP[bytesOffset], numberOfBytesNeeded - 1);
1807 memcpy(&chunkBuffer[1], &parentTCClient->generatedBinaryDDOP[bytesOffset], numberOfBytesNeeded - 1);
1815 memcpy(chunkBuffer, &parentTCClient->userSuppliedBinaryDDOP[bytesOffset - 1], numberOfBytesNeeded);
1820 memcpy(chunkBuffer, &parentTCClient->generatedBinaryDDOP[bytesOffset - 1], numberOfBytesNeeded);
1826 LOG_ERROR(
"[TC]: DDOP internal data callback received out of range request.");
1833 std::shared_ptr<InternalControlFunction>,
1834 std::shared_ptr<ControlFunction> destinationControlFunction,
1836 void *parentPointer)
1838 if ((
nullptr != parentPointer) &&
1839 (
static_cast<std::uint32_t
>(CANLibParameterGroupNumber::ProcessData) == parameterGroupNumber) &&
1840 (
nullptr != destinationControlFunction))
1852 LOG_ERROR(
"[TC]: DDOP upload did not complete. Resetting.");
1867 const std::array<std::uint8_t, CAN_DATA_LENGTH> buffer = { multiplexor,
1911 static_cast<std::uint8_t
>(elementNumber & 0x0F) << 4),
1912 static_cast<std::uint8_t
>(elementNumber >> 4),
1913 static_cast<std::uint8_t
>(ddi & 0xFF),
1914 static_cast<std::uint8_t
>(ddi >> 8),
1943 static_cast<std::uint8_t
>(binaryPoolSize & 0xFF),
1944 static_cast<std::uint8_t
>((binaryPoolSize >> 8) & 0xFF),
1945 static_cast<std::uint8_t
>((binaryPoolSize >> 16) & 0xFF),
1946 static_cast<std::uint8_t
>((binaryPoolSize >> 24) & 0xFF),
2007 const std::array<std::uint8_t, CAN_DATA_LENGTH> buffer = {
static_cast<std::uint8_t
>(
static_cast<std::uint8_t
>(
ProcessDataCommands::Value) |
2008 (
static_cast<std::uint8_t
>(elementNumber & 0x0F) << 4)),
2009 static_cast<std::uint8_t
>(elementNumber >> 4),
2010 static_cast<std::uint8_t
>(ddi & 0xFF),
2011 static_cast<std::uint8_t
>(ddi >> 8),
2012 static_cast<std::uint8_t
>(value),
2013 static_cast<std::uint8_t
>(value >> 8),
2014 static_cast<std::uint8_t
>(value >> 16),
2015 static_cast<std::uint8_t
>(value >> 24) };
2030 const std::array<std::uint8_t, CAN_DATA_LENGTH> buffer = {
numberOfWorkingSetMembers, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
2040 std::uint8_t maxNumberSectionsSupported,
2041 std::uint8_t maxNumberChannelsSupportedForPositionBasedControl,
2042 bool reportToTCSupportsDocumentation,
2043 bool reportToTCSupportsTCGEOWithoutPositionBasedControl,
2044 bool reportToTCSupportsTCGEOWithPositionBasedControl,
2045 bool reportToTCSupportsPeerControlAssignment,
2046 bool reportToTCSupportsImplementSectionControl)
2085 LOG_WARNING(
"[TC]: The TC is < version 4 but no VT was provided. Language data will be requested globally, which might not be ideal.");
2090 LOG_DEBUG(
"[TC]: Using VT as the partner for language data, because the TC's version is less than 4.");
2097#if !defined CAN_STACK_DISABLE_THREADS && !defined ARDUINO
2105 std::this_thread::sleep_for(std::chrono::milliseconds(50));
2142 Version retVal = Version::Unknown;
2158 requestData.
ddi = DDI;
Defines some PGNs that are used in the library or are very common.
The main class that manages the ISOBUS stack including: callbacks, Name to Address management,...
A class that acts as a logging sink. The intent is that someone could make their own derived class of...
@ PriorityLowest7
The lowest priority.
std::uint32_t get_parameter_group_number() const
Returns the PGN encoded in the identifier.
A class that represents a generic CAN message of arbitrary length.
const std::vector< std::uint8_t > & get_data() const
Gets a reference to the data in the CAN message.
std::uint32_t get_data_length() const
Returns the length of the data in the CAN message.
std::uint32_t get_uint24_at(const std::uint32_t index, const ByteFormat format=ByteFormat::LittleEndian) const
Get a right-aligned 24-bit integer from the buffer (returned as a uint32_t) at a specific index....
std::shared_ptr< ControlFunction > get_source_control_function() const
Gets the source control function that the message is from.
std::uint8_t get_uint8_at(const std::uint32_t index) const
Get a 8-bit unsigned byte from the buffer at a specific index. A 8-bit unsigned byte can hold a value...
CANIdentifier get_identifier() const
Returns the identifier of the message.
void add_global_parameter_group_number_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent)
This is how you register a callback for any PGN destined for the global address (0xFF)
static CANNetworkManager CANNetwork
Static singleton of the one network manager. Use this to access stack functionality.
void remove_global_parameter_group_number_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent)
This is how you remove a callback for any PGN destined for the global address (0xFF)
bool send_can_message(std::uint32_t parameterGroupNumber, const std::uint8_t *dataBuffer, std::uint32_t dataLength, std::shared_ptr< InternalControlFunction > sourceControlFunction, std::shared_ptr< ControlFunction > destinationControlFunction=nullptr, CANIdentifier::CANPriority priority=CANIdentifier::CANPriority::PriorityDefault6, TransmitCompleteCallback txCompleteCallback=nullptr, void *parentPointer=nullptr, DataChunkCallback frameChunkCallback=nullptr)
This is the main way to send a CAN message of any length.
std::string get_language_code() const
Returns the commanded language code parsed from the last language command.
bool send_request_language_command() const
Sends a PGN request for the language command PGN to the interface's partner, or the global address de...
std::shared_ptr< PartneredControlFunction > get_partner() const
Returns the current partner being used by the interface.
void set_partner(std::shared_ptr< PartneredControlFunction > filteredControlFunction)
Changes the partner being used by the interface to a new partner.
bool get_initialized() const
Returns if initialize has been called yet.
std::uint32_t get_language_command_timestamp() const
Returns a timestamp (in ms) corresponding to when the interface last received a language command.
void initialize()
Initializes the interface.
A class to manage a client connection to a ISOBUS field computer's task controller or data logger.
bool send_working_set_master() const
Sends the working set master message.
std::uint8_t serverNumberOfBoomsForSectionControl
When reported by the TC, this is the maximum number of section control booms that are supported.
bool request_task_controller_identification() const
Sends a broadcast request to TCs to identify themseleves.
std::string ddopStructureLabel
Stores a pre-parsed structure label, helps to avoid processing the whole DDOP during a CAN message ca...
std::shared_ptr< PartneredControlFunction > partnerControlFunction
The partner control function this client will send to.
TaskControllerClient(std::shared_ptr< PartneredControlFunction > partner, std::shared_ptr< InternalControlFunction > clientSource, std::shared_ptr< PartneredControlFunction > primaryVT)
The constructor for a TaskControllerClient.
void select_language_command_partner()
Sets the behavior of the language command interface based on the TC's reported version information.
std::shared_ptr< PartneredControlFunction > primaryVirtualTerminal
A pointer to the primary VT's control function. Used for TCs < version 4 and language command compati...
bool send_pdack(std::uint16_t elementNumber, std::uint16_t ddi) const
Sends a Process Data ACK.
std::uint8_t numberOfWorkingSetMembers
The number of working set members that will be reported in the working set master message.
bool get_supports_tcgeo_without_position_based_control() const
Returns if the client has been configured to report that it supports TC-GEO without position based co...
bool send_request_version_response() const
Sends the response to a request for version from the TC.
std::list< ProcessDataCallbackInfo > queuedValueRequests
A list of queued value requests that will be processed on the next update.
bool get_supports_documentation() const
Returns if the client has been configured to report that it supports documentation to the TC.
bool get_supports_tcgeo_with_position_based_control() const
Returns if the client has been configured to report that it supports TC-GEO with position based contr...
std::uint8_t serverOptionsByte1
The options specified in ISO 11783-10 that this TC, DL, or client meets (The definition of this byte ...
std::uint8_t maxServerBootTime_s
Maximum number of seconds from a power cycle to transmission of first �Task Controller Status message...
bool send_status() const
Sends the status message to the TC.
std::list< ProcessDataCallbackInfo > queuedValueCommands
A list of queued value commands that will be processed on the next update.
bool get_is_task_active() const
Returns if a task is active as indicated by the TC.
void remove_request_value_callback(RequestValueCommandCallback callback, void *parentPointer)
Removes the specified callback from the list of value request callbacks.
void set_common_config_items(std::uint8_t maxNumberBoomsSupported, std::uint8_t maxNumberSectionsSupported, std::uint8_t maxNumberChannelsSupportedForPositionBasedControl, bool reportToTCSupportsDocumentation, bool reportToTCSupportsTCGEOWithoutPositionBasedControl, bool reportToTCSupportsTCGEOWithPositionBasedControl, bool reportToTCSupportsPeerControlAssignment, bool reportToTCSupportsImplementSectionControl)
Sets the common items found in all versions of configure
bool send_value_command(std::uint16_t elementNumber, std::uint16_t ddi, std::int32_t value) const
Sends the value command message for a specific DDI/Element number combo.
std::uint32_t statusMessageTimestamp_ms
Timestamp corresponding to the last time we sent a status message to the TC.
std::uint8_t const * userSuppliedBinaryDDOP
Stores a client-provided DDOP if one was provided.
static void process_tx_callback(std::uint32_t parameterGroupNumber, std::uint32_t dataLength, std::shared_ptr< InternalControlFunction > sourceControlFunction, std::shared_ptr< ControlFunction > destinationControlFunction, bool successful, void *parentPointer)
The callback passed to the network manager's send function to know when a Tx is completed.
bool(*)(std::uint16_t elementNumber, std::uint16_t DDI, std::int32_t &processVariableValue, void *parentPointer) RequestValueCommandCallback
A callback for handling a value request command from the TC.
bool send_request_structure_label() const
Sends a request to the TC for its structure label.
void update()
The cyclic update function for this interface.
std::list< ProcessDataCallbackInfo > measurementTimeIntervalCommands
A list of measurement commands that will be processed on a time interval.
Mutex clientMutex
A general mutex to protect data in the worker thread against data accessed by the app or the network ...
bool get_is_initialized() const
Returns if the client has been initialized.
static bool process_internal_object_pool_upload_callback(std::uint32_t callbackIndex, std::uint32_t bytesOffset, std::uint32_t numberOfBytesNeeded, std::uint8_t *chunkBuffer, void *parentPointer)
The data callback passed to the network manger's send function for the transport layer messages.
bool enableStatusMessage
Enables sending the status message to the TC cyclically.
std::uint8_t tcStatusBitfield
The last received TC/DL status from the status message.
void add_value_command_callback(ValueCommandCallback callback, void *parentPointer)
Adds a callback that will be called when the TC commands a new value for one of your variables.
bool send_object_pool_activate() const
Sends the activate object pool message.
bool send_generic_process_data(std::uint8_t multiplexor) const
Sends a process data message with 1 mux byte and all 0xFFs as payload.
std::shared_ptr< PartneredControlFunction > get_partner_control_function() const
Returns the control function of the TC server with which this TC client communicates.
void on_value_changed_trigger(std::uint16_t elementNumber, std::uint16_t DDI)
Tells the TC client that a value was changed or the TC client needs to command a value to the TC serv...
bool supportsDocumentation
Determines if the client reports documentation support to the TC.
std::uint32_t serverStatusMessageTimestamp_ms
Timestamp corresponding to the last time we received a status message from the TC.
void process_queued_commands()
Processes queued TC requests and commands. Calls the user's callbacks if needed.
std::uint8_t get_connected_tc_number_sections_supported() const
Returns the number of sections that the connected TC supports for section control.
bool(*)(std::uint16_t elementNumber, std::uint16_t DDI, std::int32_t processVariableValue, void *parentPointer) ValueCommandCallback
A callback for handling a set value command from the TC.
LanguageCommandInterface languageCommandInterface
Used to determine the language and unit systems in use by the TC server.
std::uint8_t get_connected_tc_number_booms_supported() const
Returns the number of booms that the connected TC supports for section control.
void add_request_value_callback(RequestValueCommandCallback callback, void *parentPointer)
This adds a callback that will be called when the TC requests the value of one of your variables.
StateMachineState
Enumerates the different internal state machine states.
@ WaitForRequestVersionFromServer
Waiting to see if the TC will request our version (optional)
@ WaitForDeleteObjectPoolResponse
Waiting for a response to our request to delete our object pool off the TC.
@ RequestVersion
Requests the TC version and related data from the TC.
@ WaitForStructureLabelResponse
Client is waiting for the TC to respond to our request for its structure label.
@ SendRequestVersionResponse
Sending our response to the TC's request for out version information.
@ Connected
TC is connected.
@ WaitForServerStatusMessage
Client is waiting to identify the TC via reception of a valid status message.
@ SendStatusMessage
Enables sending the status message.
@ RequestLocalizationLabel
Client is requesting the DDOP localization label the TC has for us (if any)
@ WaitForDDOPTransfer
The DDOP transfer in ongoing. Client is waiting for a callback from the transport layer.
@ SendWorkingSetMaster
Client initating communication with TC by sending the working set master message.
@ RequestLanguage
Client is requesting the language command PGN from the TC.
@ SendDeleteObjectPool
Client is sending a request to the TC to delete its current copy of our object pool.
@ DeactivateObjectPool
Client is shutting down and is therefore sending the deactivate object pool message.
@ WaitForObjectPoolActivateResponse
Client is waiting for a response to its request to activate the object pool.
@ SendRequestTransferObjectPool
Client is requesting to transfer the DDOP to the TC.
@ WaitForRequestTransferObjectPoolResponse
Waiting for a response to our request to transfer the DDOP to the TC.
@ SendObjectPoolActivate
Client is sending the activate object pool message.
@ RequestStructureLabel
Client is requesting the DDOP structure label that the TC has (if any)
@ WaitForObjectPoolDeactivateResponse
Client is waiting for a response to the deactivate object pool message.
@ WaitForObjectPoolTransferResponse
DDOP has transferred. Waiting for a response to our object pool transfer.
@ BeginTransferDDOP
Client is initiating the DDOP transfer.
@ WaitForLocalizationLabelResponse
Waiting for a response to our request for the localization label from the TC.
@ WaitForStartUpDelay
Client is waiting for the mandatory 6s startup delay.
@ WaitForLanguageResponse
Waiting for a response to our request for the language command PGN.
@ ProcessDDOP
Client is processing the DDOP into a binary DDOP and validating object IDs in the pool.
@ Disconnected
Not communicating with the TC.
@ WaitForRequestVersionResponse
Waiting for the TC to respond to a request for its version.
std::uint32_t stateMachineTimestamp_ms
Timestamp that tracks when the state machine last changed states (in milliseconds)
void initialize(bool spawnThread)
This function starts the state machine. Call this once you have created your DDOP,...
void configure(std::shared_ptr< DeviceDescriptorObjectPool > DDOP, std::uint8_t maxNumberBoomsSupported, std::uint8_t maxNumberSectionsSupported, std::uint8_t maxNumberChannelsSupportedForPositionBasedControl, bool reportToTCSupportsDocumentation, bool reportToTCSupportsTCGEOWithoutPositionBasedControl, bool reportToTCSupportsTCGEOWithPositionBasedControl, bool reportToTCSupportsPeerControlAssignment, bool reportToTCSupportsImplementSectionControl)
A convenient way to set all client options at once instead of calling the individual setters.
std::string previousStructureLabel
Stores the last structure label we used, helps to warn the user if they aren't updating the label pro...
ProcessDataCommands
Enumerates the different Process Data commands from ISO11783-10 Table B.1.
@ StatusMessage
Message is a Task Controller Status message.
@ MeasurementMaximumWithinThreshold
The client has to send the value of this data element to the TC or DL when the value is lower than th...
@ ProcessDataAcknowledge
Message is a Process Data Acknowledge (PDACK).
@ MeasurementMinimumWithinThreshold
The client has to send the value of this data element to the TC or DL when the value is higher than t...
@ DeviceDescriptor
Subcommand for the transfer and management of device descriptors.
@ Value
This command is used both to answer a request value command and to set the value of a process data en...
@ TechnicalCapabilities
Used for determining the technical capabilities of a TC, DL, or client.
@ MeasurementChangeThreshold
The client has to send the value of this data element to the TC or DL when the value change is higher...
@ RequestValue
The value of the data entity specified by the data dictionary identifier is requested.
@ MeasurementTimeInterval
The process data value is the time interval for sending the data element specified by the data dictio...
@ SetValueAndAcknowledge
This command is used to set the value of a process data entity and request a reception acknowledgemen...
@ ClientTask
Sent by the client.
std::vector< std::uint8_t > generatedBinaryDDOP
Stores the DDOP in binary form after it has been generated.
static void process_rx_message(const CANMessage &message, void *parentPointer)
Processes a CAN message destined for any TC client.
bool get_connected_tc_option_supported(ServerOptions option) const
Returns if the connected TC supports a certain option.
std::list< ProcessDataCallbackInfo > measurementMinimumThresholdCommands
A list of measurement commands that will be processed when the value drops below a threshold.
std::uint8_t get_number_booms_supported() const
Returns the previously configured number of booms supported by the client.
std::uint8_t serverVersion
The detected version of the TC Server.
std::uint8_t get_connected_tc_max_boot_time() const
Returns the maximum boot time in seconds reported by the connected TC.
std::shared_ptr< DeviceDescriptorObjectPool > clientDDOP
Stores the DDOP for upload to the TC (if needed)
void remove_value_command_callback(ValueCommandCallback callback, void *parentPointer)
Removes the specified callback from the list of value command callbacks.
std::list< ProcessDataCallbackInfo > measurementOnChangeThresholdCommands
A list of measurement commands that will be processed when the value changes by the specified amount.
Version
Enumerates the different task controller versions.
@ SecondPublishedEdition
The version of the second edition published as the final draft International Standard(E2....
bool send_delete_object_pool() const
Sends the delete object pool command to the TC.
DDOPUploadType ddopUploadMode
Determines if DDOPs get generated or raw uploaded.
std::uint32_t languageCommandWaitingTimestamp_ms
Timestamp used to determine when to give up on waiting for a language command response.
std::uint8_t get_connected_tc_number_channels_supported() const
Returns the number of channels that the connected TC supports for position control.
bool send_object_pool_deactivate() const
Sends the deactivate object pool message.
StateMachineState get_state() const
Returns the current state machine state.
bool supportsTCGEOWithoutPositionBasedControl
Determines if the client reports TC-GEO without position control capability to the TC.
std::uint8_t get_number_sections_supported() const
Returns the previously configured number of section supported by the client.
TechnicalDataMessageCommands
Enumerates the subcommands within the technical data message group.
@ ParameterRequestVersion
The Request Version message allows the TC, DL, and the client to determine the ISO 11783-10 version o...
@ ParameterVersion
The Version message is sent in response to the request version message and contains the ISO 11783-10 ...
@ IdentifyTaskController
Upon receipt of this message, the TC shall display, for a period of 3 s, the TC Number.
bool send_request_object_pool_transfer() const
Sends a request to the TC indicating we wish to transfer an object pool.
std::vector< ValueCommandCallbackInfo > valueCommandsCallbacks
A list of callbacks that will be called when the TC sets a process data value.
std::uint8_t serverNumberOfSectionsForSectionControl
When reported by the TC, this is the maximum number of sections that are supported (or 0xFF for versi...
std::shared_ptr< std::vector< std::uint8_t > > userSuppliedVectorDDOP
Stores a client-provided DDOP if one was provided.
void process_queued_threshold_commands()
Processes measurement threshold/interval commands.
static constexpr std::uint32_t SIX_SECOND_TIMEOUT_MS
The startup delay time defined in the standard.
static constexpr std::uint16_t TWO_SECOND_TIMEOUT_MS
Used for sending the status message to the TC.
bool initialized
Tracks the initialization state of the interface instance.
std::uint8_t numberBoomsSupported
Stores the number of booms this client supports for section control.
bool shouldReuploadAfterDDOPDeletion
Used to determine how the state machine should progress when updating a DDOP.
void terminate()
Terminates the client and joins the worker thread if applicable.
std::vector< RequestValueCommandCallbackInfo > requestValueCallbacks
A list of callbacks that will be called when the TC requests a process data value.
std::uint8_t get_number_channels_supported_for_position_based_control() const
Returns the previously configured number of channels supported for position based control.
bool shouldTerminate
This variable tells the worker thread to exit.
bool supportsImplementSectionControl
Determines if the client reports implement section control capability to the TC.
void restart()
Calling this function will reset the task controller client's connection with the TC server,...
StateMachineState currentState
Tracks the internal state machine's current state.
std::uint8_t serverNumberOfChannelsForPositionBasedControl
When reported by the TC, this is the maximum number of individual control channels that is supported.
ServerOptions
Enumerates the bits stored in our version data that we send to the TC when handshaking.
std::shared_ptr< InternalControlFunction > get_internal_control_function() const
Returns the internal control function being used by the interface to send messages.
bool get_supports_implement_section_control() const
Returns if the client has been configured to report that it supports implement section control to the...
std::list< ProcessDataCallbackInfo > measurementMaximumThresholdCommands
A list of measurement commands that will be processed when the value above a threshold.
void process_labels_from_ddop()
Searches the DDOP for a device object and stores that object's structure and localization labels.
bool send_request_localization_label() const
Sends a request to the TC for its localization label.
std::uint8_t numberSectionsSupported
Stores the number of sections this client supports for section control.
DeviceDescriptorCommands
Enumerates the subcommands within the device descriptor command message group.
@ ObjectPoolTransferResponse
Response to an object pool transfer.
@ LocalizationLabel
Sent by the TC or DL to inform the client about the availability of the requested localization versio...
@ ObjectPoolTransfer
Enables the client to transfer (part of) the device descriptor object pool to the TC.
@ RequestLocalizationLabel
Allows the client to determine the availability of the requested device descriptor localization.
@ RequestObjectPoolTransfer
The Request Object-pool Transfer message allows the client to determine whether it is allowed to tran...
@ RequestObjectPoolTransferResponse
Sent in response to Request Object-pool Transfer message.
@ ObjectPoolActivateDeactivateResponse
sent by a client to complete its connection procedure to a TC or DL or to disconnect from a TC or DL.
@ ObjectPoolDelete
This is a message to delete the device descriptor object pool for the client that sends this message.
@ StructureLabel
The Structure Label message is sent by the TC or DL to inform the client about the availability of th...
@ RequestStructureLabel
Allows the client to determine the availability of the requested device descriptor structure.
@ ObjectPoolDeleteResponse
TC response to a Object-pool Delete message.
@ ObjectPoolActivateDeactivate
sent by a client to complete its connection procedure to a TC or DL or to disconnect from a TC or DL.
std::shared_ptr< InternalControlFunction > myControlFunction
The internal control function the client uses to send from.
Version get_connected_tc_version() const
Returns the version of the connected task controller.
void clear_queues()
Clears all queued TC commands and responses.
bool get_was_ddop_supplied() const
Checks if a DDOP was provided via one of the configure functions.
bool get_supports_peer_control_assignment() const
Returns if the client has been configured to report that it supports peer control assignment to the T...
std::uint32_t userSuppliedBinaryDDOPSize_bytes
The number of bytes in the user provided binary DDOP (if one was provided)
std::thread * workerThread
The worker thread that updates this interface.
bool get_is_connected() const
Check whether the client is connected to the TC server.
@ ProgramaticallyGenerated
Using the AgIsoStack++ DeviceDescriptorObjectPool class.
@ UserProvidedBinaryPointer
Using a raw pointer to a binary DDOP.
@ UserProvidedVector
Uses a vector of bytes that comprise a binary DDOP.
std::array< std::uint8_t, 7 > ddopLocalizationLabel
Stores a pre-parsed localization label, helps to avoid processing the whole DDOP during a CAN message...
std::uint8_t numberChannelsSupportedForPositionBasedControl
Stores the number of channels this client supports for position based control.
~TaskControllerClient()
Destructor for the client.
bool reupload_device_descriptor_object_pool(std::shared_ptr< std::vector< std::uint8_t > > binaryDDOP)
If the TC client is connected to a TC, calling this function will cause the TC client interface to de...
bool supportsPeerControlAssignment
Determines if the client reports peer control assignment capability to the TC.
void set_state(StateMachineState newState)
Changes the internal state machine state and updates the associated timestamp.
bool supportsTCGEOWithPositionBasedControl
Determines if the client reports TC-GEO with position control capability to the TC.
bool send_version_request() const
Sends the version request message to the TC.
void worker_thread_function()
The worker thread will execute this function when it runs, if applicable.
static constexpr std::size_t MAX_STRUCTURE_AND_LOCALIZATION_LABEL_LENGTH
Defines the max length of the device structure label and device localization label (in bytes)
A class to manage a client connection to a ISOBUS field computer's task controller.
@ Device
The root object. Each device shall have one single Device.
This namespace encompasses all of the ISO11783 stack's functionality to reduce global namespace pollu...
constexpr std::uint8_t CAN_DATA_LENGTH
The length of a classical CAN frame.
AcknowledgementType
The types of acknowledgement that can be sent in the Ack PGN.
@ Negative
"NACK" Indicates the request was not completed or we do not support the PGN
Stores data related to requests and commands from the TC.
std::uint16_t elementNumber
The element number for the command.
bool ackRequested
Stores if the TC used the mux that also requires a PDACK.
bool operator==(const ProcessDataCallbackInfo &obj) const
Allows easy comparison of callback data.
std::int32_t lastValue
Used for measurement commands to store timestamp or previous values.
std::uint16_t ddi
The DDI for the command.
std::int32_t processDataValue
The value of the value set command.
Stores a TC value command callback along with its parent pointer.
RequestValueCommandCallback callback
The callback itself.
void * parent
The parent pointer, generic context value.
bool operator==(const RequestValueCommandCallbackInfo &obj) const
Allows easy comparison of callback data.
Stores a TC value command callback along with its parent pointer.
ValueCommandCallback callback
The callback itself.
void * parent
The parent pointer, generic context value.
bool operator==(const ValueCommandCallbackInfo &obj) const
Allows easy comparison of callback data.