16#include "isobus/utility/system_timing.hpp"
23 std::uint8_t numberBoomsSupported,
24 std::uint8_t numberSectionsSupported,
25 std::uint8_t numberChannelsSupportedForPositionBasedControl,
28 languageCommandInterface(internalControlFunction, true),
29 serverControlFunction(internalControlFunction),
30 reportedVersion(versionToReport),
31 numberBoomsSupportedToReport(numberBoomsSupported),
32 numberSectionsSupportedToReport(numberSectionsSupported),
33 numberChannelsSupportedForPositionBasedControlToReport(numberChannelsSupportedForPositionBasedControl),
34 optionsBitfieldToReport(options.get_bitfield())
45 std::array<std::uint8_t, CAN_DATA_LENGTH> payload = { 0 };
48 payload[0] |= (elementNumber & 0x0F) << 4;
49 payload[1] =
static_cast<std::uint8_t
>(elementNumber >> 4);
50 payload[2] =
static_cast<std::uint8_t
>(dataDescriptionIndex);
51 payload[3] =
static_cast<std::uint8_t
>(dataDescriptionIndex >> 8);
91 bool TaskControllerServer::send_set_value(std::shared_ptr<ControlFunction> clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t processDataValue)
const
100 currentStatusByte &= ~static_cast<std::uint8_t>(ServerStatusBit::TaskTotalsActive);
101 currentStatusByte |= (
static_cast<std::uint8_t
>(isTaskActive) &
static_cast<std::uint8_t
>(ServerStatusBit::TaskTotalsActive));
108 return (0 != (
currentStatusByte &
static_cast<std::uint8_t
>(ServerStatusBit::TaskTotalsActive)));
143#if !defined CAN_STACK_DISABLE_THREADS && !defined ARDUINO
162 [](std::shared_ptr<ActiveClient> clientInfo) {
163 constexpr std::uint32_t CLIENT_TASK_TIMEOUT_MS = 6000;
164 if (SystemTiming::time_expired_ms(clientInfo->lastStatusMessageTimestamp_ms, CLIENT_TASK_TIMEOUT_MS))
166 LOG_WARNING(
"[TC Server]: Client 0x%02X has timed out. Removing from active client list.", clientInfo->clientControlFunction->get_address());
171 activeClients.end());
174 TaskControllerServer::ActiveClient::ActiveClient(std::shared_ptr<ControlFunction> clientControlFunction) :
175 clientControlFunction(clientControlFunction),
176 lastStatusMessageTimestamp_ms(SystemTiming::get_timestamp_ms())
182 if (
nullptr != parentPointer)
185#if !defined CAN_STACK_DISABLE_THREADS && !defined ARDUINO
186 const std::lock_guard<std::mutex> lock(server->messagesMutex);
187 server->rxMessageQueue.push_back(message);
188 server->updateWakeupCondition.notify_all();
190 server->rxMessageQueue.push_back(message);
197#if !defined CAN_STACK_DISABLE_THREADS && !defined ARDUINO
203 auto &rxData = rxMessage.get_data();
205 switch (rxMessage.get_identifier().get_parameter_group_number())
207 case static_cast<std::uint32_t
>(CANLibParameterGroupNumber::ProcessData):
217 case TechnicalDataCommandParameters::RequestVersion:
232 LOG_DEBUG(
"[TC Server]: Client reports that its version is %u", rxData[1]);
239 LOG_INFO(
"[TC Server]: Received identify task controller command from 0x%02X. We are TC number %u", rxMessage.get_source_control_function()->get_address(),
serverControlFunction->get_NAME().get_function_instance());
256 LOG_WARNING(
"[TC Server]: Unknown technical capabilities command received: 0x%02X", rxData[0]);
266 (
nullptr != rxMessage.get_source_control_function()) &&
267 (
nullptr != rxMessage.get_destination_control_function()))
271 case DeviceDescriptorCommandParameters::RequestStructureLabel:
275 std::vector<std::uint8_t> structureLabel;
276 std::vector<std::uint8_t> extendedStructureLabel;
280 structureLabel.push_back(rxData[i + 1]);
286 for (std::size_t i = 0; i < (rxMessage.get_data_length() -
CAN_DATA_LENGTH); i++)
294 LOG_INFO(
"[TC Server]:Client 0x%02X structure label(s) matched.", rxMessage.get_source_control_function()->get_address());
295 send_structure_label(rxMessage.get_source_control_function(), structureLabel, extendedStructureLabel);
300 LOG_INFO(
"[TC Server]:Client 0x%02X structure label(s) did not match. Sending 0xFFs as the structure label.", rxMessage.get_source_control_function()->get_address());
315 const std::array<std::uint8_t, 7> localizationLabel = { rxData.at(1), rxData.at(2), rxData.at(3), rxData.at(4), rxData.at(5), rxData.at(6), rxData.at(7) };
318 LOG_INFO(
"[TC Server]:Client 0x%02X localization label matched.", rxMessage.get_source_control_function()->get_address());
324 LOG_INFO(
"[TC Server]: No object pool found for client 0x%02X localization label. Sending FFs as the localization label.", rxMessage.get_source_control_function()->get_address());
339 std::uint32_t requestedSize = rxMessage.get_uint32_at(1);
344 LOG_INFO(
"[TC Server]: Client 0x%02X requests object pool transfer of %u bytes", rxMessage.get_source_control_function()->get_address(), requestedSize);
346 get_active_client(rxMessage.get_source_control_function())->clientDDOPsize_bytes = requestedSize;
351 LOG_ERROR(
"[TC Server]: Client 0x%02X requests object pool transfer of %u bytes but there is not enough memory available.", rxMessage.get_source_control_function()->get_address(), requestedSize);
366 std::vector<std::uint8_t> objectPool = rxData;
367 objectPool.erase(objectPool.begin());
369 if (0 ==
get_active_client(rxMessage.get_source_control_function())->clientDDOPsize_bytes)
371 LOG_WARNING(
"[TC Server]: Client 0x%02X sent object pool transfer without first requesting a transfer!", rxMessage.get_source_control_function()->get_address());
376 LOG_INFO(
"[TC Server]: Stored DDOP segment for client 0x%02X", rxMessage.get_source_control_function()->get_address());
381 LOG_ERROR(
"[TC Server]: Failed to store DDOP segment for client 0x%02X. Reporting to the client as \"Any other error\"", rxMessage.get_source_control_function()->get_address());
396 constexpr std::uint8_t ACTIVATE = 0xFF;
397 constexpr std::uint8_t DEACTIVATE = 0x00;
400 std::uint16_t faultingParentObject = 0;
401 std::uint16_t faultingObject = 0;
403 if (ACTIVATE == rxData[1])
405 LOG_INFO(
"[TC Server]: Client 0x%02X requests activation of object pool", rxMessage.get_source_control_function()->get_address());
408 if (
activate_object_pool(rxMessage.get_source_control_function(), activationError, errorCode, faultingParentObject, faultingObject))
410 LOG_INFO(
"[TC Server]: Object pool activated for client 0x%02X", rxMessage.get_source_control_function()->get_address());
411 client->isDDOPActive =
true;
416 LOG_ERROR(
"[TC Server]: Failed to activate object pool for client 0x%02X. Error code: %u, Faulty object: %u, Parent of faulty object: %u", rxMessage.get_source_control_function()->get_address(),
static_cast<std::uint8_t
>(activationError), faultingObject, faultingParentObject);
420 else if (DEACTIVATE == rxData[1])
422 LOG_INFO(
"[TC Server]: Client 0x%02X requests deactivation of object pool", rxMessage.get_source_control_function()->get_address());
426 LOG_INFO(
"[TC Server]: Object pool deactivated for client 0x%02X", rxMessage.get_source_control_function()->get_address());
427 get_active_client(rxMessage.get_source_control_function())->isDDOPActive =
false;
432 LOG_ERROR(
"[TC Server]: Failed to deactivate object pool for client 0x%02X", rxMessage.get_source_control_function()->get_address());
438 LOG_ERROR(
"[TC Server]: Client 0x%02X requests activation/deactivation of object pool with invalid value: 0x%02X", rxMessage.get_source_control_function()->get_address(), rxData[1]);
456 LOG_INFO(
"[TC Server]: Deleted object pool for client 0x%02X", rxMessage.get_source_control_function()->get_address());
457 send_delete_object_pool_response(rxMessage.get_source_control_function(),
true,
static_cast<std::uint8_t
>(ObjectPoolDeletionErrors::ErrorDetailsNotAvailable));
461 LOG_ERROR(
"[TC Server]: Failed to delete object pool for client 0x%02X. Error code: %u", rxMessage.get_source_control_function()->get_address(),
static_cast<std::uint8_t
>(errorCode));
478 std::uint16_t objectID = rxMessage.get_uint16_at(1);
479 std::vector<std::uint8_t> newDesignatorUTF8Bytes;
481 for (std::size_t i = 0; i < rxData.size() - 3; i++)
483 newDesignatorUTF8Bytes.push_back(rxData[3 + i]);
486 if (
change_designator(rxMessage.get_source_control_function(), objectID, newDesignatorUTF8Bytes))
488 LOG_INFO(
"[TC Server]: Changed designator for client 0x%02X. Object ID: %u", rxMessage.get_source_control_function()->get_address(), objectID);
493 LOG_ERROR(
"[TC Server]: Failed to change designator for client 0x%02X. Object ID: %u", rxMessage.get_source_control_function()->get_address(), objectID);
499 LOG_ERROR(
"[TC Server]: Client 0x%02X requests change to change a designator but the object pool is not active.", rxMessage.get_source_control_function()->get_address());
525 LOG_WARNING(
"[TC Server]: Device descriptor message received with invalid DLC. DLC must be at least 8.");
530 LOG_WARNING(
"[TC Server]: Unknown device descriptor command received: 0x%02X", rxData[0]);
542 std::uint16_t DDI = rxMessage.get_uint16_at(2);
543 std::uint16_t elementNumber =
static_cast<std::uint16_t
>(rxData[0] >> 4) | (
static_cast<std::uint16_t
>(rxData[1]) << 4);
544 std::int32_t processVariableValue = rxMessage.get_int32_at(4);
545 std::uint8_t errorCodes = 0;
547 if (
on_value_command(rxMessage.get_source_control_function(), DDI, elementNumber, processVariableValue, errorCodes))
549 LOG_DEBUG(
"[TC Server]: Client 0x%02X value command for element %u DDI %u and value %d OK.", rxMessage.get_source_control_function()->get_address(), elementNumber, DDI, processVariableValue);
558 LOG_ERROR(
"[TC Server]: Client 0x%02X value command for element %u DDI %u and value %d failed.", rxMessage.get_source_control_function()->get_address(), elementNumber, DDI, processVariableValue);
562 LOG_ERROR(
"[TC Server]: Your derived TC server class must set errorCodes to a non-zero value if a value command fails.");
563 errorCodes =
static_cast<std::uint8_t
>(ProcessDataAcknowledgeErrorCodes::DDINotSupportedByElement);
571 LOG_ERROR(
"[TC Server]: Client 0x%02X sent a value command but the object pool is not active.", rxMessage.get_source_control_function()->get_address());
585 std::uint16_t DDI = rxMessage.get_uint16_at(2);
586 std::uint16_t elementNumber =
static_cast<std::uint16_t
>(rxData[0] >> 4) | (
static_cast<std::uint16_t
>(rxData[1]) << 4);
594 LOG_ERROR(
"[TC Server]: Client 0x%02X sent an acknowledge command but the object pool is not active.", rxMessage.get_source_control_function()->get_address());
613 std::uint16_t DDI =
static_cast<std::uint16_t
>(rxData[2]) | (
static_cast<std::uint16_t
>(rxData[3]) << 8);
614 std::uint16_t elementNumber =
static_cast<std::uint16_t
>(rxData[0] >> 4) | (
static_cast<std::uint16_t
>(rxData[1]) << 4);
615 LOG_ERROR(
"[TC Server]: Client 0x%02X is sending measurement commands?", rxMessage.get_source_control_function()->get_address());
616 send_process_data_acknowledge(rxMessage.get_source_control_function(), DDI, elementNumber,
static_cast<std::uint8_t
>(ProcessDataAcknowledgeErrorCodes::ProcessDataCommandNotSupported),
static_cast<ProcessDataCommands>(rxData[0] & 0x0F));
620 LOG_ERROR(
"[TC Server]: Client 0x%02X is sending measurement commands with invalid lengths, which is very unusual.", rxMessage.get_source_control_function()->get_address());
638 if ((
nullptr != activeClient) &&
639 (activeClient->clientControlFunction == rxMessage.get_source_control_function()))
641 std::uint32_t status = rxData[4];
642 status |=
static_cast<std::uint32_t
>(rxData[5]) << 8;
643 status |=
static_cast<std::uint32_t
>(rxData[6]) << 16;
644 status |=
static_cast<std::uint32_t
>(rxData[7]) << 24;
645 activeClient->lastStatusMessageTimestamp_ms = SystemTiming::get_timestamp_ms();
646 activeClient->statusBitfield = status;
652 LOG_WARNING(
"[TC Server]: client task message received with invalid DLC. DLC must be 8.");
659 LOG_WARNING(
"[TC Server]: Peer Control is currently not supported");
666 LOG_WARNING(
"[TC Server]: Reserved command received: 0x%02X", rxData[0]);
672 LOG_WARNING(
"[TC Server]: Unknown ProcessData command received: 0x%02X", rxData[0]);
679 case static_cast<std::uint32_t
>(CANLibParameterGroupNumber::WorkingSetMaster):
683 std::uint8_t numberOfWorkingSetMembers = rxData[0];
685 if (1 == numberOfWorkingSetMembers)
689 activeClients.push_back(std::make_shared<ActiveClient>(rxMessage.get_source_control_function()));
694 LOG_ERROR(
"[TC Server]: Working set master message received with unsupported number of working set members: %u", numberOfWorkingSetMembers);
699 LOG_ERROR(
"[TC Server]: Working set master message received with invalid DLC. DLC should be 8.");
715 std::array<std::uint8_t, CAN_DATA_LENGTH> payload = { multiplexer, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
718 switch (multiplexer & 0x0F)
748 if (
nullptr != clientControlFunction)
750 std::array<std::uint8_t, CAN_DATA_LENGTH> payload = { 0 };
751 payload[0] = (commandValue & 0x0F);
752 payload[0] |= (elementNumber & 0x0F) << 4;
753 payload[1] =
static_cast<std::uint8_t
>(elementNumber >> 4);
754 payload[2] =
static_cast<std::uint8_t
>(dataDescriptionIndex);
755 payload[3] =
static_cast<std::uint8_t
>(dataDescriptionIndex >> 8);
756 payload[4] =
static_cast<std::uint8_t
>(processDataValue);
757 payload[5] =
static_cast<std::uint8_t
>(processDataValue >> 8);
758 payload[6] =
static_cast<std::uint8_t
>(processDataValue >> 16);
759 payload[7] =
static_cast<std::uint8_t
>(processDataValue >> 24);
771 std::array<std::uint8_t, CAN_DATA_LENGTH> payload = {
790 std::array<std::uint8_t, CAN_DATA_LENGTH> payload = {
809 if ((
nullptr != activeClient) &&
810 (
nullptr != activeClient->clientControlFunction) &&
811 (
nullptr != clientControlFunction) &&
812 (activeClient->clientControlFunction->get_NAME() == clientControlFunction->get_NAME()) &&
813 (activeClient->clientControlFunction->get_can_port() == clientControlFunction->get_can_port()))
825 if (
nullptr != clientControlFunction)
827 const std::array<std::uint8_t, CAN_DATA_LENGTH> payload = {
832 clientControlFunction->get_address(),
833 static_cast<std::uint8_t
>(
static_cast<std::uint32_t
>(CANLibParameterGroupNumber::ProcessData) & 0xFF),
834 static_cast<std::uint8_t
>((
static_cast<std::uint32_t
>(CANLibParameterGroupNumber::ProcessData) >> 8) & 0xFF),
835 static_cast<std::uint8_t
>((
static_cast<std::uint32_t
>(CANLibParameterGroupNumber::ProcessData) >> 16) & 0xFF)
838 LOG_WARNING(
"[TC Server]: NACKing process data command from 0x%02X because they are not known to us. Clients must send the working set master message first.", clientControlFunction->get_address());
843 clientControlFunction);
852 if (
nullptr != clientControlFunction)
856 structureLabel.push_back(0xFF);
859 std::vector<std::uint8_t> payload;
862 for (
const auto &labelByte : structureLabel)
864 payload.push_back(labelByte);
866 for (
const auto &extendedLabelByte : extendedStructureLabel)
868 payload.push_back(extendedLabelByte);
881 if (
nullptr != clientControlFunction)
883 const std::array<std::uint8_t, CAN_DATA_LENGTH> payload = {
885 localizationLabel[0],
886 localizationLabel[1],
887 localizationLabel[2],
888 localizationLabel[3],
889 localizationLabel[4],
890 localizationLabel[5],
905 if (
nullptr != clientControlFunction)
907 const std::array<std::uint8_t, CAN_DATA_LENGTH> payload = {
909 static_cast<std::uint8_t
>(
false == isEnoughMemory),
929 if (
nullptr != clientControlFunction)
931 const std::array<std::uint8_t, CAN_DATA_LENGTH> payload = {
934 static_cast<std::uint8_t
>(sizeBytes),
935 static_cast<std::uint8_t
>(sizeBytes >> 8),
936 static_cast<std::uint8_t
>(sizeBytes >> 16),
937 static_cast<std::uint8_t
>(sizeBytes >> 24),
950 std::uint8_t activationErrorBitfield,
951 std::uint8_t objectPoolErrorBitfield,
952 std::uint16_t parentOfFaultingObject,
953 std::uint16_t faultingObject)
const
957 if (
nullptr != clientControlFunction)
959 const std::array<std::uint8_t, CAN_DATA_LENGTH> payload = {
961 activationErrorBitfield,
962 static_cast<std::uint8_t
>(parentOfFaultingObject),
963 static_cast<std::uint8_t
>(parentOfFaultingObject >> 8),
964 static_cast<std::uint8_t
>(faultingObject),
965 static_cast<std::uint8_t
>(faultingObject >> 8),
966 objectPoolErrorBitfield,
980 if (
nullptr != clientControlFunction)
982 const std::array<std::uint8_t, CAN_DATA_LENGTH> payload = {
984 static_cast<std::uint8_t
>(!deletionResult),
1001 bool retVal =
false;
1003 if (
nullptr != clientControlFunction)
1005 const std::array<std::uint8_t, CAN_DATA_LENGTH> payload = {
1007 static_cast<std::uint8_t
>(objectID),
1008 static_cast<std::uint8_t
>(objectID >> 8),
1024 bool retVal =
false;
1026 if (
nullptr != clientControlFunction)
1028 const std::array<std::uint8_t, CAN_DATA_LENGTH> payload = {
1030 static_cast<std::uint8_t
>(elementNumber >> 4),
1031 static_cast<std::uint8_t
>(dataDescriptionIndex),
1032 static_cast<std::uint8_t
>(dataDescriptionIndex >> 8),
1034 static_cast<std::uint8_t
>(0xF0 |
static_cast<std::uint8_t
>(processDataCommand)),
1047 const std::uint8_t *dataBuffer,
1048 std::uint32_t dataLength,
1051 bool retVal =
false;
1053 if ((
nullptr != dataBuffer) && (dataLength > 0))
1059 clientControlFunction,
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...
CANPriority
Defines all the CAN frame priorities that can be encoded in a frame ID.
@ Priority3
Priority highest - 3 (Control messages priority)
@ Priority4
Priority highest - 4.
@ Priority5
Priority highest - 5.
A class that represents a generic CAN message of arbitrary length.
static const std::uint32_t ABSOLUTE_MAX_MESSAGE_LENGTH
ISO11783-3 defines this: The maximum number of packets that can be sent in a single connection with e...
static CANNetworkManager CANNetwork
Static singleton of the one network manager. Use this to access stack functionality.
void add_any_control_function_parameter_group_number_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent)
Registers a callback for ANY control function sending the associated PGN.
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.
void remove_any_control_function_parameter_group_number_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parent)
This is how you remove a callback added with add_any_control_function_parameter_group_number_callback...
An interface for requesting and parsing the ISO11783 language command PGN, 0xFE0F.
void initialize()
Initializes the interface.
A helper class to assign TC server options. You can use this by doing something like this: TaskContro...
An ISO11783-10 task controller (or data logger) server. A task controller collects task data from con...
bool get_task_totals_active() const
Returns whether a task is currently active or not.
bool send_minimum_threshold_measurement_command(std::shared_ptr< ControlFunction > clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t minimum) const
Sends a minimum threshold measurement command. The process data value for this command is the minimum...
std::uint32_t lastStatusMessageTimestamp_ms
The timestamp of the last status message sent on the bus.
virtual bool on_value_command(std::shared_ptr< ControlFunction > clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::int32_t processDataValue, std::uint8_t &errorCodes)=0
This function will be called by the server when a client sends a value command to the TC....
TaskControllerVersion
Enumerates the different versions of the task controller standard.
virtual ~TaskControllerServer()
Destructor for a TC server.
virtual void identify_task_controller(std::uint8_t taskControllerNumber)=0
This function will be called if someone requests that the TC identify itself. If this gets called,...
std::condition_variable updateWakeupCondition
A condition variable you can optionally use to update the interface when messages are received.
const TaskControllerVersion reportedVersion
The version of the TC that will be reported to the clients.
std::shared_ptr< ActiveClient > get_active_client(std::shared_ptr< ControlFunction > clientControlFunction) const
Checks to see if we are communicating with a control function that is already in our list of active c...
TechnicalDataCommandParameters
Enumerates the subcommands for determining the technical capabilities of a TC, DL,...
@ ParameterVersion
The Request Version message allows the TC, DL, and the client to determine the ISO 11783-10 version o...
@ IdentifyTaskController
The Version message is sent in response to the request version message and contains the ISO 11783-10 ...
bool send_object_pool_transfer_response(std::shared_ptr< ControlFunction > clientControlFunction, std::uint8_t errorBitfield, std::uint32_t sizeBytes) const
Sends a response to an object pool transfer.
void terminate()
Shuts down the TC server, unregisters PGN callbacks.
bool send_request_object_pool_transfer_response(std::shared_ptr< ControlFunction > clientControlFunction, bool isEnoughMemory) const
Sends a response to a request object pool transfer command.
bool send_set_value(std::shared_ptr< ControlFunction > clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t processDataValue) const
Sends a set value command without requesting an acknowledgement. This command is used to set the valu...
bool send_distance_interval_measurement_command(std::shared_ptr< ControlFunction > clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t distanceInterval) const
Sends a distance interval measurement command. The process data value for this command is the distanc...
void process_rx_messages()
Processes messages received from task controller clients.
bool send_change_threshold_measurement_command(std::shared_ptr< ControlFunction > clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t threshold) const
Sends a change threshold measurement command. The process data value for this command is the change t...
void initialize()
Initializes the task controller server.
virtual bool change_designator(std::shared_ptr< ControlFunction > clientControlFunction, std::uint16_t objectIDToAlter, const std::vector< std::uint8_t > &designator)=0
This function will be called by the server when the client wants to change the designator of an objec...
ProcessDataCommands
Enumerates the different process data commands that can be sent to the client.
@ MeasurementMaximumWithinThreshold
The client has to send the value of this data element to the TC or DL when the value is lower than th...
@ 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
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...
@ PeerControlAssignment
This message is used to establish a connection between a setpoint value source and a setpoint value u...
@ 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
Used when 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...
@ MeasurementDistanceInterval
The process data value is the distance interval for sending the data element specified by the data di...
@ SetValueAndAcknowledge
This command is used to set the value of a process data entity and request a reception acknowledgemen...
@ ClientTask
Sent by the client as a status message every 2s.
@ Acknowledge
Message is a Process Data Acknowledge (PDACK).
@ Status
Message is a Task Controller Status message.
std::mutex messagesMutex
A mutex used to protect the rxMessageQueue.
std::uint8_t currentCommandSourceAddress
The current command source address to send in the status message.
std::deque< CANMessage > rxMessageQueue
A queue of messages received from the clients which will be processed when update is called.
bool send_status_message() const
Sends a status message broadcast.
virtual bool get_is_enough_memory_available(std::uint32_t numberBytesRequired)=0
This function will be called by the server when the client wants to transfer its DDOP to the server a...
static void store_rx_message(const CANMessage &message, void *parentPointer)
Stores messages received from task controller clients for processing later.
void update()
This must be called periodically for the interface to operate correctly.
ObjectPoolErrorCodes
Enumerates the different error codes that can be returned when processing a DDOP.
const std::uint8_t numberChannelsSupportedForPositionBasedControlToReport
The number of channels that will be reported as supported by the TC.
virtual bool get_is_stored_device_descriptor_object_pool_by_localization_label(std::shared_ptr< ControlFunction > clientControlFunction, const std::array< std::uint8_t, 7 > &localizationLabel)=0
This function will be called by the server when the server needs to know if it has previously saved t...
LanguageCommandInterface & get_language_command_interface()
Returns the language command interface used to communicate with the client which language/units are i...
virtual bool get_is_stored_device_descriptor_object_pool_by_structure_label(std::shared_ptr< ControlFunction > clientControlFunction, const std::vector< std::uint8_t > &structureLabel, const std::vector< std::uint8_t > &extendedStructureLabel)=0
This function will be called by the server when the server needs to know if it has previously saved t...
const std::uint8_t numberSectionsSupportedToReport
The number of sections that will be reported as supported by the TC.
void set_task_totals_active(bool isTaskActive)
Use this to set the reported task state in the status message. Basically, this should be set to true ...
bool send_localization_label(std::shared_ptr< ControlFunction > clientControlFunction, const std::array< std::uint8_t, 7 > &localizationLabel) const
Sends a response to a request localization label command.
bool send_maximum_threshold_measurement_command(std::shared_ptr< ControlFunction > clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t maximum) const
Sends a maximum threshold measurement command. The process data value for this command is the maximum...
const std::uint8_t numberBoomsSupportedToReport
The number of booms that will be reported as supported by the TC.
bool send_generic_process_data_default_payload(std::uint8_t multiplexer, std::shared_ptr< ControlFunction > destination) const
This sends a process data message with all FFs in the payload except for the command byte....
bool send_change_designator_response(std::shared_ptr< ControlFunction > clientControlFunction, std::uint16_t objectID, std::uint8_t errorCode) const
Sends a response to a change designator command.
virtual bool store_device_descriptor_object_pool(std::shared_ptr< ControlFunction > clientControlFunction, const std::vector< std::uint8_t > &objectPoolData, bool appendToPool)=0
This function is called when the server wants you to save a DDOP to non volatile memory (NVM)....
LanguageCommandInterface languageCommandInterface
The language command interface used to communicate with the client which language/units are in use.
virtual bool deactivate_object_pool(std::shared_ptr< ControlFunction > clientControlFunction)=0
This function will be called by the server when the client wants to deactivate its DDOP....
bool send_version(std::shared_ptr< ControlFunction > clientControlFunction) const
Sends the version message to a client.
std::deque< std::shared_ptr< ActiveClient > > activeClients
A list of clients that are currently being communicated with.
bool send_object_pool_activate_deactivate_response(std::shared_ptr< ControlFunction > clientControlFunction, std::uint8_t activationErrorBitfield, std::uint8_t objectPoolErrorBitfield, std::uint16_t parentOfFaultingObject, std::uint16_t faultingObject) const
Sends a response to an object pool activate/deactivate command.
bool send_structure_label(std::shared_ptr< ControlFunction > clientControlFunction, std::vector< std::uint8_t > &structureLabel, const std::vector< std::uint8_t > &extendedStructureLabel) const
Sends a response to a request structure label command.
bool get_initialized() const
Returns whether or not the task controller server has been initialized.
TaskControllerServer(std::shared_ptr< InternalControlFunction > internalControlFunction, std::uint8_t numberBoomsSupported, std::uint8_t numberSectionsSupported, std::uint8_t numberChannelsSupportedForPositionBasedControl, const TaskControllerOptions &options, TaskControllerVersion versionToReport=TaskControllerVersion::SecondPublishedEdition)
Constructor for a TC server.
const std::uint8_t optionsBitfieldToReport
The options bitfield that will be reported as supported by the TC.
bool initialized
Whether or not the task controller server has been initialized.
std::condition_variable & get_condition_variable()
Returns a condition variable which you can optionally use to wake up your server's thread when messag...
bool send_process_data_acknowledge(std::shared_ptr< ControlFunction > clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint8_t errorBitfield, ProcessDataCommands processDataCommand) const
Sends a process data acknowledge message to the client.
bool send_set_value_and_acknowledge(std::shared_ptr< ControlFunction > clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t processDataValue) const
Sends a set value and acknowledge command. This command is used to set the value of a process data en...
bool send_request_value(std::shared_ptr< ControlFunction > clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber) const
Sends a request to a client for an element's value of a particular DDI.
static constexpr std::uint32_t STATUS_MESSAGE_RATE_MS
The rate at which status messages are sent to the clients in milliseconds.
DeviceDescriptorCommandParameters
Enumerates subcommands for the transfer and management of device descriptors. These device descriptor...
@ ObjectPoolTransferResponse
Enables the client to transfer (part of) the device descriptor object pool to the TC.
@ LocalizationLabel
Allows the client to determine the availability of the requested device descriptor localization.
@ ObjectPoolTransfer
Sent in response to Request Object-pool Transfer message.
@ DeleteObjectPoolResponse
This is a message to delete the device descriptor object pool for the client that sends this message.
@ DeleteObjectPool
Sent by a client to complete its connection procedure to a TC or DL or to disconnect from a TC or DL.
@ RequestLocalizationLabel
The Structure Label message is sent by the TC or DL to inform the client about the availability of th...
@ RequestObjectPoolTransfer
/// Sent by the TC or DL to inform the client about the availability of the requested localization ve...
@ RequestObjectPoolTransferResponse
/// The Request Object-pool Transfer message allows the client to determine whether it is allowed to ...
@ ObjectPoolActivateDeactivateResponse
Sent by a client to complete its connection procedure to a TC or DL or to disconnect from a TC or DL.
@ StructureLabel
Allows the client to determine the availability of the requested device descriptor structure.
@ ChangeDesignator
TC response to a Object-pool Delete message.
@ ObjectPoolActivateDeactivate
Response to an object pool transfer message.
@ ChangeDesignatorResponse
This message is used to update the designator of an object.
ObjectPoolDeletionErrors
Enumerates the different error codes that can be returned when deleting a device descriptor object po...
bool send_time_interval_measurement_command(std::shared_ptr< ControlFunction > clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t timeInterval) const
Sends a time interval measurement command. The process data value for this command is the time interv...
std::shared_ptr< InternalControlFunction > serverControlFunction
The control function used to communicate with the clients.
virtual bool delete_device_descriptor_object_pool(std::shared_ptr< ControlFunction > clientControlFunction, ObjectPoolDeletionErrors &returnedErrorCode)=0
This function will be called by the server when the client wants to delete its DDOP....
bool send_delete_object_pool_response(std::shared_ptr< ControlFunction > clientControlFunction, bool deletionResult, std::uint8_t errorCode) const
Sends a response to a delete object pool command.
virtual void on_process_data_acknowledge(std::shared_ptr< ControlFunction > clientControlFunction, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint8_t errorCodesFromClient, ProcessDataCommands processDataCommand)=0
This function will be called by the server when a client sends an acknowledgement for a process data ...
bool send_process_data_to_client(std::shared_ptr< ControlFunction > clientControlFunction, const std::uint8_t *dataBuffer, std::uint32_t dataLength, CANIdentifier::CANPriority priority=CANIdentifier::CANPriority::Priority5) const
Sends a process data message to a client with a slightly shorter signature than calling send_can_mess...
std::uint8_t currentCommandByte
The current command byte to send in the status message.
ObjectPoolActivationError
Enumerates the different error codes that can be returned when activating a device descriptor object ...
bool nack_process_data_command(std::shared_ptr< ControlFunction > clientControlFunction) const
Sends a negative acknowledge for a the process data PGN which indicates to clients that we aren't lis...
virtual bool activate_object_pool(std::shared_ptr< ControlFunction > clientControlFunction, ObjectPoolActivationError &activationError, ObjectPoolErrorCodes &objectPoolError, std::uint16_t &parentObjectIDOfFaultyObject, std::uint16_t &faultyObjectID)=0
This function will be called by the server when the client wants to activate its DDOP....
bool send_measurement_command(std::shared_ptr< ControlFunction > clientControlFunction, std::uint8_t commandValue, std::uint16_t dataDescriptionIndex, std::uint16_t elementNumber, std::uint32_t processDataValue) const
Sends a measurement command to the client.
std::uint8_t currentStatusByte
The current status byte to send in the status message.
An abstract task controller server class. You can consume this file and implement the pure virtual fu...
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.
@ Negative
"NACK" Indicates the request was not completed or we do not support the PGN