42#include "isobus/utility/system_timing.hpp"
49 suspectParameterNumber(spn),
50 failureModeIdentifier(failureMode),
64 return occurrenceCount;
69 return suspectParameterNumber;
74 return failureModeIdentifier;
122 LOG_WARNING(
"[DP] DiagnosticProtocol's initialize() called when already initialized");
251 inactiveLocation->occurrenceCount++;
379 std::uint8_t retVal = 0;
612 if ((
nullptr != affectedControlFunction) &&
617 constexpr std::uint32_t ADDRESS_VIOLATION_SPN_BASE = 2000;
636 std::vector<std::uint8_t> buffer;
641 bool tempLampState =
false;
646 buffer[0] = tempLampState;
652 buffer[0] |= (
static_cast<std::uint8_t
>(tempLampState) << 2);
658 buffer[0] |= (
static_cast<std::uint8_t
>(tempLampState) << 4);
664 buffer[0] |= (
static_cast<std::uint8_t
>(tempLampState) << 6);
724 std::vector<std::uint8_t> buffer;
729 bool tempLampState =
false;
734 buffer[0] = tempLampState;
740 buffer[0] |= (
static_cast<std::uint8_t
>(tempLampState) << 2);
746 buffer[0] |= (
static_cast<std::uint8_t
>(tempLampState) << 4);
752 buffer[0] |= (
static_cast<std::uint8_t
>(tempLampState) << 6);
809 constexpr std::uint8_t SUPPORTED_DIAGNOSTIC_PROTOCOLS_BITFIELD = 0x01;
810 std::array<std::uint8_t, CAN_DATA_LENGTH> buffer;
813 buffer[0] = SUPPORTED_DIAGNOSTIC_PROTOCOLS_BITFIELD;
824 const std::array<std::uint8_t, CAN_DATA_LENGTH> buffer = {
829 static_cast<std::uint8_t
>(suspendTime_seconds & 0xFF),
830 static_cast<std::uint8_t
>(suspendTime_seconds >> 8),
842 std::string ecuIdString =
"";
845 for (std::size_t i = 0; i < maxComponent; i++)
850 std::vector<std::uint8_t> buffer(ecuIdString.begin(), ecuIdString.end());
860 std::vector<std::uint8_t> buffer(productIdString.begin(), productIdString.end());
874 std::string softIDString =
"";
878 [&softIDString](
const std::string &field) {
879 softIDString.append(field);
880 softIDString.append(
"*");
883 std::vector<std::uint8_t> buffer(softIDString.begin(), softIDString.end());
900 for (std::size_t i = 0; i < numberOfMessage; i++)
902 std::array<std::uint8_t, CAN_DATA_LENGTH> buffer;
905 if (currentMessageData.
nack)
962 case static_cast<std::uint32_t
>(CANLibParameterGroupNumber::DiagnosticMessage13):
971 case static_cast<std::uint32_t
>(CANLibParameterGroupNumber::DiagnosticMessage22):
975 const auto &messageData = message.
get_data();
978 bool wasDTCCleared =
false;
988 switch (messageData.at(0))
1001 wasDTCCleared =
true;
1002 tempDM22Data.
nack =
false;
1012 tempDM22Data.
nack =
true;
1045 wasDTCCleared =
true;
1046 tempDM22Data.
nack =
false;
1056 tempDM22Data.
nack =
true;
1096 if (
nullptr != parent)
1104 bool retVal =
false;
1109 const auto &messageData = message.
get_data();
1158 command =
static_cast<StopStartCommand>((messageData[0] & (DM13_NETWORK_BITMASK << (DM13_BITS_PER_NETWORK * static_cast<std::uint8_t>(NetworkType::CurrentDataLink)))) >> (
DM13_BITS_PER_NETWORK *
static_cast<std::uint8_t
>(NetworkType::CurrentDataLink)));
1212 std::shared_ptr<ControlFunction> requestingControlFunction,
1216 bool retVal =
false;
1217 acknowledge =
false;
1220 if (
nullptr != requestingControlFunction)
1222 switch (parameterGroupNumber)
1224 case static_cast<std::uint32_t
>(CANLibParameterGroupNumber::DiagnosticMessage1):
1231 case static_cast<std::uint32_t
>(CANLibParameterGroupNumber::DiagnosticMessage2):
1238 case static_cast<std::uint32_t
>(CANLibParameterGroupNumber::DiagnosticMessage3):
1247 case static_cast<std::uint32_t
>(CANLibParameterGroupNumber::DiagnosticMessage11):
1256 case static_cast<std::uint32_t
>(CANLibParameterGroupNumber::ProductIdentification):
1263 case static_cast<std::uint32_t
>(CANLibParameterGroupNumber::DiagnosticProtocolIdentification):
1270 case static_cast<std::uint32_t
>(CANLibParameterGroupNumber::SoftwareIdentification):
1277 case static_cast<std::uint32_t
>(CANLibParameterGroupNumber::ECUIdentificationInformation):
1295 std::shared_ptr<ControlFunction> requestingControlFunction,
1298 void *parentPointer)
1300 bool retVal =
false;
1302 if (
nullptr != parentPointer)
1311 if (
nullptr != parentPointer)
1314 bool transmitSuccessful =
false;
1320 transmitSuccessful = parent->send_diagnostic_message_1();
1322 if (transmitSuccessful)
1324 parent->lastDM1SentTimestamp = SystemTiming::get_timestamp_ms();
1331 transmitSuccessful = parent->send_diagnostic_message_2();
1337 transmitSuccessful = parent->send_diagnostic_protocol_identification();
1343 transmitSuccessful = parent->send_product_identification();
1349 transmitSuccessful = parent->process_all_dm22_responses();
1355 transmitSuccessful = parent->send_ecu_identification();
1361 transmitSuccessful = parent->send_software_identification();
1369 if (
false == transmitSuccessful)
1371 parent->txFlags.set_flag(flag);
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 protocol that handles PGN requests.
A class that acts as a logging sink. The intent is that someone could make their own derived class of...
std::uint32_t get_parameter_group_number() const
Returns the PGN encoded in the identifier.
std::uint8_t get_destination_address() const
Returns the destination address of the frame 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::shared_ptr< ControlFunction > get_source_control_function() const
Gets the source control function that the message is from.
std::uint16_t get_uint16_at(const std::uint32_t index, const ByteFormat format=ByteFormat::LittleEndian) const
Get a 16-bit unsigned integer from the buffer at a specific index. A 16-bit unsigned integer can hold...
CANIdentifier get_identifier() const
Returns the identifier of the message.
std::shared_ptr< ControlFunction > get_destination_control_function() const
Gets the destination control function that the message is to.
EventDispatcher< std::shared_ptr< InternalControlFunction > > & get_address_violation_event_dispatcher()
Returns the network manager's event dispatcher for notifying consumers whenever an address violation ...
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.
bool remove_protocol_parameter_group_number_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parentPointer)
Removes a PGN callback for a protocol class.
bool add_protocol_parameter_group_number_callback(std::uint32_t parameterGroupNumber, CANLibCallback callback, void *parentPointer)
Adds a PGN callback for a protocol class.
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.
void update()
The diagnostic protocol will call this update function, make sure to call DiagnosticProtocol::update(...
A storage class for describing a complete DTC.
std::uint32_t suspectParameterNumber
This 19-bit number is used to identify the item for which diagnostics are being reported.
DiagnosticTroubleCode()=default
Constructor for a DTC, sets default values at construction time.
LampStatus lampState
The J1939 lamp state for this DTC.
bool operator==(const DiagnosticTroubleCode &obj) const
A useful way to compare DTC objects to each other for equality.
std::uint8_t get_occurrence_count() const
Returns the occurrence count, which will be kept track of by the protocol.
std::uint32_t get_suspect_parameter_number() const
Returns the suspect parameter number.
FailureModeIdentifier get_failure_mode_identifier() const
Returns the failure mode indicator.
FailureModeIdentifier failureModeIdentifier
The FMI defines the type of failure detected in the sub-system identified by an SPN.
Manages the DM1, DM2, and DM3 messages for ISO11783 or J1939.
SuspendSignalState
Enumerates the different suspend signals for DM13.
@ IndefiniteSuspension
Indefinite suspension of all broadcasts.
@ PartialTemporarySuspension
Temporary suspension of some messages.
@ PartialIndefiniteSuspension
Indefinite suspension of some messages.
@ TemporarySuspension
Temporary suspension of all broadcasts.
bool broadcastState
Bitfield for tracking the network broadcast state for DM13.
~DiagnosticProtocol()
The destructor for this protocol.
void process_message(const CANMessage &message)
A generic way for a protocol to process a received message.
FailureModeIdentifier
FMI as defined in ISO11783-12 Annex E.
@ ConditionExists
The condition that is identified by the SPN exists when no applicable FMI exists (any other error)
ProcessingFlags txFlags
An instance of the processing flags to handle retries of some messages.
void get_inactive_list_lamp_state_and_flash_state(Lamps targetLamp, FlashState &flash, bool &lampOn) const
This is a way to find the overall lamp states to report.
std::string productIdentificationBrand
The product identification brand for sending the product identification message.
static void process_flags(std::uint32_t flag, void *parentPointer)
A generic callback for a the class to process flags from the ProcessingFlags
void clear_software_id_fields()
Clears all previously configured software ID fields set with set_software_id_field.
NetworkType networkType
The diagnostic network type that this protocol will use.
bool get_initialized() const
Returns if the protocol has been initialized.
bool set_product_identification_model(const std::string &value)
Sets the product identification model used in the diagnostic protocol "Product Identification" messag...
static constexpr std::uint16_t MAX_PAYLOAD_SIZE_BYTES
DM 1 and 2 are limited to the BAM message max, because ETP does not allow global destinations.
EventCallbackHandle addressViolationEventHandle
Stores the handle from registering for address violation events.
static constexpr std::uint32_t DM_MAX_FREQUENCY_MS
You are technically allowed to send more than this under limited circumstances, but a hard limit save...
bool suspend_broadcasts(std::uint16_t suspendTime_seconds=0xFFFF)
Informs the diagnostic protocol that you are going to suspend broadcasts.
bool send_ecu_identification() const
Sends the ECU ID message.
NetworkType
Enumerates the different networks in the DM13.
bool send_dm13_announce_suspension(std::uint16_t suspendTime_seconds) const
Sends the DM13 to alert network devices of impending suspended broadcasts.
bool send_diagnostic_protocol_identification() const
Sends a message that identifies which diagnostic protocols are supported.
StopStartCommand
Enumerates the commands in the DM13.
@ StopBroadcast
Stop broadcast.
@ StartBroadcast
Start broadcast.
std::vector< std::string > ecuIdentificationFields
Stores the ECU ID fields so we can transmit them when ECU ID's PGN is requested.
FlashState
Enumerates lamp flash states in J1939.
std::uint16_t customDM13SuspensionTime
If using a non-standard DM13 suspension time, this tracks that duration in milliseconds.
void update()
Updates the diagnostic protocol.
DiagnosticProtocol(std::shared_ptr< InternalControlFunction > internalControlFunction, NetworkType networkType=NetworkType::ProprietaryNetwork1)
The constructor for this protocol.
bool set_diagnostic_trouble_code_active(const DiagnosticTroubleCode &dtc, bool active)
Adds a DTC to the active list, or removes one from the active list.
std::shared_ptr< InternalControlFunction > myControlFunction
The internal control function that this protocol will send from.
LampStatus
The DTC lamp status as defined in J1939-73. Not used when in ISO11783 mode.
@ EngineProtectLampSolid
This lamp is used to relay trouble code information that is reporting a problem with a vehicle system...
@ EngineProtectLampSlowFlash
This lamp is used to relay trouble code information that is reporting a problem with a vehicle system...
@ EngineProtectLampFastFlash
This lamp is used to relay trouble code information that is reporting a problem with a vehicle system...
@ AmberWarningLampSlowFlash
This lamp is used to relay trouble code information that is reporting a problem with the vehicle syst...
@ AmberWarningLampFastFlash
This lamp is used to relay trouble code information that is reporting a problem with the vehicle syst...
@ AmberWarningLampSolid
This lamp is used to relay trouble code information that is reporting a problem with the vehicle syst...
@ MalfunctionIndicatorLampSolid
A lamp used to relay only emissions-related trouble code information.
@ RedStopLampSolid
This lamp is used to relay trouble code information that is of a severe-enough condition that it warr...
@ MalfunctionIndicatorLampSlowFlash
A lamp used to relay only emissions-related trouble code information.
@ MalfunctionIndicatorLampFastFlash
A lamp used to relay only emissions-related trouble code information.
@ RedStopLampFastFlash
This lamp is used to relay trouble code information that is of a severe-enough condition that it warr...
@ RedStopLampSlowFlash
This lamp is used to relay trouble code information that is of a severe-enough condition that it warr...
Lamps
Lists the different lamps in J1939-73.
@ MalfunctionIndicatorLamp
The "MIL".
@ AmberWarningLamp
The "AWL".
@ ProtectLamp
The engine protect lamp.
std::uint32_t lastDM13ReceivedTimestamp
A timestamp in milliseconds when we last got a DM13 message.
void clear_inactive_diagnostic_trouble_codes()
Clears the list of inactive DTCs and clears occurrence counts.
@ NegativeAcknowledgeOfPreviouslyActiveDTCClear
NACK for clearing a previously active DTC.
@ RequestToClearPreviouslyActiveDTC
Clear a previously active DTC.
@ PositiveAcknowledgeOfPreviouslyActiveDTCClear
ACK for clearing a previously active DTC.
@ RequestToClearActiveDTC
Clear an active DTC.
@ PositiveAcknowledgeOfActiveDTCClear
ACK clearing an active DTC.
@ NegativeAcknowledgeOfActiveDTCClear
NACK clearing an active DTC.
bool set_product_identification_brand(const std::string &value)
Sets the product identification brand used in the diagnostic protocol "Product Identification" messag...
static constexpr std::uint32_t DM13_TIMEOUT_MS
The timeout in 5.7.13 after which nodes shall revert back to the normal broadcast state.
@ DTCNoLongerActive
DTC is inactive, not active, but active was requested to be cleared.
@ DTCNoLongerPreviouslyActive
The DTC in in the active list but it was requested to clear from inactive list.
@ UnknownOrDoesNotExist
The DTC is unknown or does not exist.
std::string productIdentificationModel
The product identification model name for sending the product identification message.
std::vector< std::string > softwareIdentificationFields
Stores the Software ID fields so we can transmit them when the PGN is requested.
static constexpr std::uint8_t PRODUCT_IDENTIFICATION_MAX_STRING_LENGTH
The max string length allowed in the fields of product ID, as defined in ISO 11783-12.
ControlFunctionFunctionalities ControlFunctionFunctionalitiesMessageInterface
Use this interface to configure your CF's functionalities. This info will be reported to any ECU that...
std::string productIdentificationCode
The product identification code for sending the product identification message.
bool set_product_identification_code(const std::string &value)
Sets the product ID code used in the diagnostic protocol "Product Identification" message (PGN 0xFC8D...
void terminate()
The protocol's terminate function.
bool get_j1939_mode() const
Returns true if the protocol is in J1939 mode instead of ISO11783 mode, false if using ISO11783 mode.
std::uint8_t convert_flash_state_to_byte(FlashState flash) const
A utility function to get the CAN representation of a FlashState.
std::vector< DM22Data > dm22ResponseQueue
Maintaining a list of DM22 responses we need to send to allow for retrying in case of Tx failures.
bool get_diagnostic_trouble_code_active(const DiagnosticTroubleCode &dtc)
Returns if a DTC is active.
bool initialize()
The protocol's initializer function.
bool send_diagnostic_message_2() const
Sends a DM2 encoded CAN message.
bool j1939Mode
Tells the protocol to operate according to J1939 instead of ISO11783.
void set_software_id_field(std::uint32_t index, const std::string &value)
Adds an ascii string to this internal control function's software ID.
bool get_broadcast_state() const
Gets the current broadcast state for the connected network type.
void set_ecu_id_field(ECUIdentificationFields field, const std::string &value)
Sets one of the ECU identification strings for the ECU ID message.
static constexpr std::uint8_t DM13_BITS_PER_NETWORK
Number of bits for the network SPNs.
TransmitFlags
A set of transmit flags to manage sending DM1, DM2, and protocol ID.
@ DM1
A flag to manage sending the DM1 message.
@ ProductIdentification
A flag to manage sending the product identification message.
@ DM2
A flag to manage sending the DM2 message.
@ SoftwareIdentification
A flag to manage sending the software ID message.
@ ECUIdentification
A flag to manage sending the ECU ID message.
@ DiagnosticProtocolID
A flag to manage sending the Diagnostic protocol ID message.
@ DM22
Process queued up DM22 responses.
@ NumberOfFlags
The number of flags in the enum.
std::vector< DiagnosticTroubleCode > inactiveDTCList
Keeps track of all the previously active DTCs.
void clear_active_diagnostic_trouble_codes()
Clears the list of active DTCs and makes them all inactive.
void set_j1939_mode(bool value)
Enables the protocol to run in J1939 mode instead of ISO11783 mode.
bool parse_j1939_network_states(const CANMessage &message)
Parses out the DM13 J1939 network states from a CAN message.
static constexpr std::uint8_t DM_PAYLOAD_BYTES_PER_DTC
The number of payload bytes per DTC that gets encoded into the messages.
void get_active_list_lamp_state_and_flash_state(Lamps targetLamp, FlashState &flash, bool &lampOn) const
This is a way to find the overall lamp states to report.
void on_address_violation(std::shared_ptr< InternalControlFunction > affectedControlFunction)
A callback function used to consume address violation events and activate a DTC as required in ISO117...
bool send_product_identification() const
Sends the product identification message (PGN 0xFC8D)
bool send_diagnostic_message_1() const
Sends a DM1 encoded CAN message.
std::uint32_t lastDM1SentTimestamp
A timestamp in milliseconds of the last time a DM1 was sent.
ECUIdentificationFields
Enumerates the different fields in the ECU identification message.
@ NumberOfFields
The number of fields currently defined in the ISO standard.
@ HardwareID
ISO 11783 only, This parameter is used to associate the hardware version of an ECU connected to the I...
bool initialized
Stores if the interface has been initialized.
std::vector< DiagnosticTroubleCode > activeDTCList
Keeps track of all the active DTCs.
bool process_parameter_group_number_request(std::uint32_t parameterGroupNumber, std::shared_ptr< ControlFunction > requestingControlFunction, bool &acknowledge, AcknowledgementType &acknowledgementType)
Handles PGN requests for the diagnostic protocol.
bool process_all_dm22_responses()
Processes any DM22 responses from the queue.
bool send_software_identification() const
Sends the software ID message.
static constexpr std::uint16_t MAX_DM13_CUSTOM_SUSPEND_TIME_MS
The max valid value for a DM13 suspension time in milliseconds.
A protocol that handles the ISO 11783-12 Diagnostic Protocol and some J1939 DMs.
This namespace encompasses all of the ISO11783 stack's functionality to reduce global namespace pollu...
constexpr std::uint8_t NULL_CAN_ADDRESS
The NULL CAN address defined by J1939 and ISO11783.
constexpr std::uint8_t CAN_DATA_LENGTH
The length of a classical CAN frame.
constexpr std::uint8_t BROADCAST_CAN_ADDRESS
The global/broadcast CAN address.
AcknowledgementType
The types of acknowledgement that can be sent in the Ack PGN.
@ Positive
"ACK" Indicates that the request was completed
@ Negative
"NACK" Indicates the request was not completed or we do not support the PGN
A structure to hold data about DM22 responses we need to send.
std::uint8_t nackIndicator
The NACK reason, if applicable.
std::uint32_t suspectParameterNumber
SPN of the DTC for the DM22.
bool nack
true if we are sending a NACK instead of PACK. Determines if we use nackIndicator
bool clearActive
true if the DM22 was for an active DTC, false for previously active
std::shared_ptr< ControlFunction > destination
Destination for the DM22 message.
std::uint8_t failureModeIdentifier
FMI of the DTC for the DM22.