X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=low-can-binding%2Fdiagnostic%2Fdiagnostic-manager.cpp;h=5242c5bbd0aaf36c21a80ac40fd7fc2715a4e1a0;hb=42163fc4757fa2bb4a8fba54afb8a092ccd0878d;hp=61aa699d7889c3221f356659c77f948b30ac25e1;hpb=32e25cbca210a359b09768537b6f443fe90a3070;p=apps%2Fagl-service-can-low-level.git diff --git a/low-can-binding/diagnostic/diagnostic-manager.cpp b/low-can-binding/diagnostic/diagnostic-manager.cpp index 61aa699d..5242c5bb 100644 --- a/low-can-binding/diagnostic/diagnostic-manager.cpp +++ b/low-can-binding/diagnostic/diagnostic-manager.cpp @@ -36,12 +36,25 @@ diagnostic_manager_t::diagnostic_manager_t() : 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() { @@ -52,7 +65,7 @@ bool diagnostic_manager_t::initialize() reset(); initialized_ = true; - DEBUG("Diagnostic Manager initialized"); + AFB_DEBUG("Diagnostic Manager initialized"); return initialized_; } @@ -62,13 +75,13 @@ bool diagnostic_manager_t::initialize() 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); } @@ -80,7 +93,7 @@ void diagnostic_manager_t::reset() /// @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(); @@ -89,29 +102,33 @@ bool diagnostic_manager_t::shims_send(const uint32_t arbitration_id, const uint8 // Make sure that socket has been opened. if(! tx_socket) - tx_socket.open( - dm.get_bus_device_name()); + tx_socket.open(dm.get_bus_device_name()); - struct utils::simple_bcm_msg bcm_msg; - struct can_frame cfd; - - memset(&cfd, 0, sizeof(cfd)); - memset(&bcm_msg.msg_head, 0, sizeof(bcm_msg.msg_head)); + struct bcm_msg bcm_msg; + struct can_frame cf; struct timeval freq = current_adr->get_frequency_clock().get_timeval_from_period(); bcm_msg.msg_head.opcode = TX_SETUP; bcm_msg.msg_head.can_id = arbitration_id; bcm_msg.msg_head.flags = SETTIMER|STARTTIMER|TX_CP_CAN_ID; + bcm_msg.msg_head.count = 0; bcm_msg.msg_head.ival2.tv_sec = freq.tv_sec; bcm_msg.msg_head.ival2.tv_usec = freq.tv_usec; bcm_msg.msg_head.nframes = 1; - cfd.can_dlc = size; - ::memcpy(cfd.data, data, size); + cf.can_dlc = size; + + ::memset(cf.data, 0, sizeof(cf.data)); + ::memcpy(cf.data, data, size); + + bcm_msg.frames[0] = cf; + - bcm_msg.frames = cfd; + can_message_t msg = can_message_t(); - tx_socket << bcm_msg; + msg.set_bcm_msg(bcm_msg); + + tx_socket.write_message(msg); if(tx_socket) return true; return false; @@ -132,14 +149,10 @@ void diagnostic_manager_t::shims_logger(const char* format, ...) 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_; @@ -185,7 +198,7 @@ void diagnostic_manager_t::cancel_request(active_diagnostic_request_t* entry) } /// @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 @@ -201,11 +214,11 @@ void diagnostic_manager_t::cleanup_request(active_diagnostic_request_t* entry, b { 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_); } @@ -248,7 +261,7 @@ active_diagnostic_request_t* diagnostic_manager_t::find_recurring_request(Diagno } return nullptr; } - +/* /// @brief Add and send a new one-time diagnostic request. DON'T USED AT THIS TIME /// /// A one-time (aka non-recurring) request can existing in parallel with a @@ -259,8 +272,7 @@ active_diagnostic_request_t* diagnostic_manager_t::find_recurring_request(Diagno /// /// @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 @@ -273,8 +285,7 @@ active_diagnostic_request_t* diagnostic_manager_t::find_recurring_request(Diagno /// 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) @@ -285,31 +296,29 @@ active_diagnostic_request_t* diagnostic_manager_t::add_request(DiagnosticRequest 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; } - +*/ /// @brief Validate frequency asked don't get higher than the maximum of a classical /// CAN bus OBD2 request. /// @@ -319,7 +328,7 @@ active_diagnostic_request_t* diagnostic_manager_t::add_request(DiagnosticRequest 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; } @@ -351,11 +360,10 @@ bool diagnostic_manager_t::validate_optional_request_attributes(float frequencyH /// 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; @@ -369,20 +377,20 @@ active_diagnostic_request_t* diagnostic_manager_t::add_recurring_request(Diagnos 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; } @@ -392,10 +400,14 @@ active_diagnostic_request_t* diagnostic_manager_t::add_recurring_request(Diagnos /// @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); @@ -421,11 +433,9 @@ openxc_VehicleMessage diagnostic_manager_t::relay_diagnostic_response(active_dia // 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."))); } @@ -436,24 +446,38 @@ openxc_VehicleMessage diagnostic_manager_t::relay_diagnostic_response(active_dia // 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 /// @param[in] cm - A raw CAN message. /// /// @return A pointer to a filled openxc_VehicleMessage or a nullptr if nothing has been found. -openxc_VehicleMessage diagnostic_manager_t::relay_diagnostic_handle(active_diagnostic_request_t* entry, const can_message_t& cm) +openxc_VehicleMessage diagnostic_manager_t::relay_diagnostic_handle(active_diagnostic_request_t* entry, std::shared_ptr m) { - DiagnosticResponse response = diagnostic_receive_can_frame(&shims_, entry->get_handle(), cm.get_id(), cm.get_data(), cm.get_length()); + DiagnosticResponse response = diagnostic_receive_can_frame(&shims_, entry->get_handle(), m->get_id(), m->get_data(), (uint8_t)m->get_length()); if(response.completed && entry->get_handle()->completed) { if(entry->get_handle()->success) - return relay_diagnostic_response(entry, response); + return relay_diagnostic_response(entry, response, m->get_timestamp()); } else if(!response.completed && response.multi_frame) { @@ -472,20 +496,20 @@ openxc_VehicleMessage diagnostic_manager_t::relay_diagnostic_handle(active_diagn /// @param[in] cm - Raw CAN message received /// /// @return VehicleMessage with decoded value. -openxc_VehicleMessage diagnostic_manager_t::find_and_decode_adr(const can_message_t& cm) +openxc_VehicleMessage diagnostic_manager_t::find_and_decode_adr(std::shared_ptr m) { openxc_VehicleMessage vehicle_message = build_VehicleMessage(); for ( auto entry : non_recurring_requests_) { - vehicle_message = relay_diagnostic_handle(entry, cm); + vehicle_message = relay_diagnostic_handle(entry, m); if (is_valid(vehicle_message)) return vehicle_message; } for ( auto entry : recurring_requests_) { - vehicle_message = relay_diagnostic_handle(entry, cm); + vehicle_message = relay_diagnostic_handle(entry, m); if (is_valid(vehicle_message)) return vehicle_message; } @@ -494,15 +518,18 @@ openxc_VehicleMessage diagnostic_manager_t::find_and_decode_adr(const can_messag } /// @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. /// /// @return True if the active diagnostic request match the response. -bool diagnostic_manager_t::is_diagnostic_response(const can_message_t& cm) +bool diagnostic_manager_t::is_diagnostic_response(std::shared_ptr m) { - if (cm.get_id() >= 0x7e8 && cm.get_id() <= 0x7ef) - return true; + if(m->get_flags()&STANDARD_ID || m->get_flags()&EXTENDED_ID) + { + if (m->get_id() >= 0x7e8 && m->get_id() <= 0x7ef) + return true; + } return false; }