: initialized_{false}
{}
-/// @brief Diagnostic manager isn't initialized at launch but after
-/// CAN bus devices initialization. For the moment, it is only possible
+
+diagnostic_manager_t::~diagnostic_manager_t()
+{
+ for(auto r: recurring_requests_)
+ {
+ delete(r);
+ }
+ for(auto r: non_recurring_requests_)
+ {
+ delete(r);
+ }
+}
+
+/// @brief Diagnostic manager is not initialized at launch but after
+/// the initialization of CAN bus devices. For the moment, it is only possible
/// to have 1 diagnostic bus which are the first bus declared in the JSON
/// description file. Configuration instance will return it.
///
-/// this will initialize DiagnosticShims and cancel all active requests
+/// this will initialize DiagnosticShims and cancel all active requests
/// if there are any.
bool diagnostic_manager_t::initialize()
{
reset();
initialized_ = true;
- DEBUG("Diagnostic Manager initialized");
+ AFB_DEBUG("Diagnostic Manager initialized");
return initialized_;
}
void diagnostic_manager_t::init_diagnostic_shims()
{
shims_ = diagnostic_init_shims(shims_logger, shims_send, NULL);
- DEBUG("Shims initialized");
+ AFB_DEBUG("Shims initialized");
}
/// @brief Force cleanup all active requests.
void diagnostic_manager_t::reset()
{
- DEBUG("Clearing existing diagnostic requests");
+ AFB_DEBUG("Clearing existing diagnostic requests");
cleanup_active_requests(true);
}
/// @param[in] data - The data payload for the message. NULL is valid if size is also 0.
/// @param[in] size - The size of the data payload, in bytes.
///
-/// @return true if the CAN message was sent successfully.
+/// @return true if the CAN message was sent successfully.
bool diagnostic_manager_t::shims_send(const uint32_t arbitration_id, const uint8_t* data, const uint8_t size)
{
diagnostic_manager_t& dm = application_t::instance().get_diagnostic_manager();
char buffer[256];
vsnprintf(buffer, 256, format, args);
- DEBUG("%s", buffer);
+ AFB_DEBUG("%s", buffer);
va_end(args);
}
-/// @brief The type signature for a... OpenXC TODO: not used yet.
-void diagnostic_manager_t::shims_timer()
-{}
-
const std::string diagnostic_manager_t::get_bus_name() const
{
return bus_;
}
/// @brief Cleanup a specific request if it isn't running and get complete. As it is almost
-/// impossible to get that state for a recurring request without waiting for that, you can
+/// impossible to get that state for a recurring request without waiting for that, you can
/// force the cleaning operation.
///
/// @param[in] entry - the request to clean
{
cancel_request(entry);
find_and_erase(entry, recurring_requests_);
- DEBUG("Cancelling completed, recurring request: %s", request_string);
+ AFB_DEBUG("Cancelling completed, recurring request: %s", request_string);
}
else if (!entry->get_recurring())
{
- DEBUG("Cancelling completed, non-recurring request: %s", request_string);
+ AFB_DEBUG("Cancelling completed, non-recurring request: %s", request_string);
cancel_request(entry);
find_and_erase(entry, non_recurring_requests_);
}
///
/// @param[in] request - The parameters for the request.
/// @param[in] name - Human readable name this response, to be used when
-/// publishing received responses. TODO: If the name is NULL, the published output
-/// will use the raw OBD-II response format.
+/// publishing received responses.
/// @param[in] wait_for_multiple_responses - If false, When any response is received
/// for this request it will be removed from the active list. If true, the
/// request will remain active until the timeout clock expires, to allow it
/// response is received for this request.
///
/// @return true if the request was added successfully. Returns false if there
-/// wasn't a free active request entry, if the frequency was too high or if the
-/// CAN acceptance filters could not be configured,
+/// wasn't a free active request entry.
active_diagnostic_request_t* diagnostic_manager_t::add_request(DiagnosticRequest* request, const std::string& name,
bool wait_for_multiple_responses, const DiagnosticResponseDecoder decoder,
const DiagnosticResponseCallback callback)
if (non_recurring_requests_.size() <= MAX_SIMULTANEOUS_DIAG_REQUESTS)
{
- // TODO: implement Acceptance Filter
- // if(updateRequiredAcceptanceFilters(bus, request)) {
- active_diagnostic_request_t* entry = new active_diagnostic_request_t(bus_, request->arbitration_id, name,
- wait_for_multiple_responses, decoder, callback, 0);
- entry->set_handle(shims_, request);
+ active_diagnostic_request_t* entry = new active_diagnostic_request_t(bus_, request->arbitration_id, name,
+ wait_for_multiple_responses, decoder, callback, 0, false);
+ entry->set_handle(shims_, request);
- char request_string[128] = {0};
- diagnostic_request_to_string(&entry->get_handle()->request, request_string,
- sizeof(request_string));
+ char request_string[128] = {0};
+ diagnostic_request_to_string(&entry->get_handle()->request, request_string,
+ sizeof(request_string));
- // Erase any existing request not already cleaned.
- cleanup_request(entry, true);
- DEBUG("Added one-time diagnostic request on bus %s: %s",
- bus_.c_str(), request_string);
+ // Erase any existing request not already cleaned.
+ cleanup_request(entry, true);
+ AFB_DEBUG("Added one-time diagnostic request on bus %s: %s",
+ bus_.c_str(), request_string);
- non_recurring_requests_.push_back(entry);
+ non_recurring_requests_.push_back(entry);
}
else
{
- WARNING("There isn't enough request entry. Vector exhausted %d/%d", (int)non_recurring_requests_.size(), MAX_SIMULTANEOUS_DIAG_REQUESTS);
+ AFB_WARNING("There isn't enough request entry. Vector exhausted %d/%d", (int)non_recurring_requests_.size(), MAX_SIMULTANEOUS_DIAG_REQUESTS);
non_recurring_requests_.resize(MAX_SIMULTANEOUS_DIAG_REQUESTS);
}
return entry;
bool diagnostic_manager_t::validate_optional_request_attributes(float frequencyHz)
{
if(frequencyHz > MAX_RECURRING_DIAGNOSTIC_FREQUENCY_HZ) {
- DEBUG("Requested recurring diagnostic frequency %lf is higher than maximum of %d",
+ AFB_DEBUG("Requested recurring diagnostic frequency %lf is higher than maximum of %d",
frequencyHz, MAX_RECURRING_DIAGNOSTIC_FREQUENCY_HZ);
return false;
}
/// function return false.
///
/// @return true if the request was added successfully. Returns false if there
-/// was too much already running requests, if the frequency was too high TODO:or if the
-/// CAN acceptance filters could not be configured,
+/// was too much already running requests, or if the frequency was too high.
active_diagnostic_request_t* diagnostic_manager_t::add_recurring_request(DiagnosticRequest* request, const char* name,
bool wait_for_multiple_responses, const DiagnosticResponseDecoder decoder,
- const DiagnosticResponseCallback callback, float frequencyHz)
+ const DiagnosticResponseCallback callback, float frequencyHz, bool permanent)
{
active_diagnostic_request_t* entry = nullptr;
if(recurring_requests_.size() <= MAX_SIMULTANEOUS_DIAG_REQUESTS)
{
entry = new active_diagnostic_request_t(bus_, request->arbitration_id, name,
- wait_for_multiple_responses, decoder, callback, frequencyHz);
+ wait_for_multiple_responses, decoder, callback, frequencyHz, permanent);
recurring_requests_.push_back(entry);
entry->set_handle(shims_, request);
- start_diagnostic_request(&shims_, entry->get_handle());
+ start_diagnostic_request(&shims_, entry->get_handle());
}
else
{
- WARNING("There isn't enough request entry. Vector exhausted %d/%d", (int)recurring_requests_.size(), MAX_SIMULTANEOUS_DIAG_REQUESTS);
+ AFB_WARNING("There isn't enough request entry. Vector exhausted %d/%d", (int)recurring_requests_.size(), MAX_SIMULTANEOUS_DIAG_REQUESTS);
recurring_requests_.resize(MAX_SIMULTANEOUS_DIAG_REQUESTS);
}
}
else
- { DEBUG("Can't add request, one already exists with same key");}
+ { AFB_DEBUG("Can't add request, one already exists with same key");}
return entry;
}
/// @param[in] response - The response to decode from which the Vehicle message will be built and returned
///
/// @return A filled openxc_VehicleMessage or a zeroed struct if there is an error.
-openxc_VehicleMessage diagnostic_manager_t::relay_diagnostic_response(active_diagnostic_request_t* adr, const DiagnosticResponse& response)
+openxc_VehicleMessage diagnostic_manager_t::relay_diagnostic_response(active_diagnostic_request_t* adr, const DiagnosticResponse& response, const uint64_t timestamp)
{
openxc_VehicleMessage message = build_VehicleMessage();
float value = (float)diagnostic_payload_to_integer(&response);
+
+ struct utils::signals_found found_signals;
+ found_signals = utils::signals_manager_t::instance().find_signals(build_DynamicField((double) adr->get_pid()));
+
if(adr->get_decoder() != nullptr)
{
value = adr->get_decoder()(&response, value);
// If not success but completed then the pid isn't supported
if(!response.success)
{
- struct utils::signals_found found_signals;
- found_signals = utils::signals_manager_t::instance().find_signals(build_DynamicField(adr->get_name()));
found_signals.diagnostic_messages.front()->set_supported(false);
cleanup_request(adr, true);
- NOTICE("PID not supported or ill formed. Please unsubscribe from it. Error code : %d", response.negative_response_code);
+ AFB_NOTICE("PID not supported or ill formed. Please unsubscribe from it. Error code : %d", response.negative_response_code);
message = build_VehicleMessage(build_SimpleMessage(adr->get_name(), build_DynamicField("This PID isn't supported by your vehicle.")));
}
// Reset the completed flag handle to make sure that it will be reprocessed the next time.
adr->get_handle()->success = false;
+
+ // Save value and timestamp of diagnostic message
+ if(!found_signals.diagnostic_messages.empty())
+ {
+ // Then, for each diag_message found
+ for(const auto& diag_mess: found_signals.diagnostic_messages)
+ {
+ // Save value and timestamp for this message
+ diag_mess->set_received(true);
+ diag_mess->set_last_value(value);
+ diag_mess->set_timestamp(timestamp);
+ }
+ }
+
return message;
}
/// @brief Will take the CAN message and pass it to the receive functions that will process
-/// diagnostic handle for each active diagnostic request then depending on the result we will
+/// diagnostic handle for each active diagnostic request then depending on the result we will
/// return pass the diagnostic response to decode it.
///
/// @param[in] entry - A pointer to an active diagnostic request holding a valid diagnostic handle
if(response.completed && entry->get_handle()->completed)
{
if(entry->get_handle()->success)
- return relay_diagnostic_response(entry, response);
+ return relay_diagnostic_response(entry, response, cm.get_timestamp());
}
else if(!response.completed && response.multi_frame)
{
}
/// @brief Tell if the CAN message received is a diagnostic response.
-/// Request broadcast ID use 0x7DF and assigned ID goes from 0x7E0 to Ox7E7. That allows up to 8 ECU to respond
+/// Request broadcast ID use 0x7DF and assigned ID goes from 0x7E0 to Ox7E7. That allows up to 8 ECU to respond
/// at the same time. The response is the assigned ID + 0x8, so response ID can goes from 0x7E8 to 0x7EF.
///
/// @param[in] cm - CAN message received from the socket.