Detect engine state and use it during diagnostic messages subscriptions 43/13743/2
authorJonathan Aillet <jonathan.aillet@iot.bzh>
Mon, 9 Apr 2018 07:50:15 +0000 (09:50 +0200)
committerJonathan Aillet <jonathan.aillet@iot.bzh>
Tue, 17 Apr 2018 09:42:37 +0000 (11:42 +0200)
Get engine state recurringly by requesting a permanent
diagnostic messages request.
Use these information to warn that diagnostic request won't have any responses
at the moment of subscription if engine is off.

Bug-AGL: SPEC-1347

Change-Id: If8bd79bba89acd1c8f5452d3efdbf00a89f8cc77
Signed-off-by: Jonathan Aillet <jonathan.aillet@iot.bzh>
low-can-binding/binding/application.cpp
low-can-binding/binding/application.hpp
low-can-binding/binding/low-can-cb.cpp

index 6f2310c..153821c 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include <ctime>
+
 #include "application.hpp"
 
 #include "../utils/signals.hpp"
 #include "../utils/openxc-utils.hpp"
 #include "low-can-socket.hpp"
 
+#define MICROSECONDS_IN_SECOND 1000000
+#define ENGINE_VALUE_TIMEOUT   5
+
 /// @brief Return singleton instance of configuration object.
 application_t& application_t::instance()
 {
@@ -81,3 +86,54 @@ void application_t::set_active_message_set(uint8_t id)
 {
        active_message_set_ = id;
 }
+
+bool application_t::isEngineOn()
+{
+       struct utils::signals_found sf;
+       openxc_DynamicField search_key = build_DynamicField("engine.speed");
+       sf = utils::signals_manager_t::instance().find_signals(search_key);
+       bool engine_on = false;
+       uint64_t last_timestamp_in_s;
+
+       if(sf.can_signals.size() == 1)
+       {
+               last_timestamp_in_s = sf.can_signals.front()->get_last_value_with_timestamp().second
+                                               / MICROSECONDS_IN_SECOND;
+
+               if(sf.can_signals.front()->get_last_value_with_timestamp().first > 0 &&
+                  std::difftime(std::time(nullptr), last_timestamp_in_s) < ENGINE_VALUE_TIMEOUT)
+               {
+                       engine_on = true;
+               }
+               else
+               {
+                       AFB_NOTICE("is_engine_on: engine.speed CAN signal found, but engine seems off");
+               }
+       }
+       else
+       {
+               AFB_NOTICE("is_engine_on: Can't identify a useable engine.speed CAN signal");
+       }
+
+       if(sf.diagnostic_messages.size() == 1)
+       {
+               last_timestamp_in_s = sf.diagnostic_messages.front()->get_last_value_with_timestamp().second
+                                               / MICROSECONDS_IN_SECOND;
+
+               if(sf.diagnostic_messages.front()->get_last_value_with_timestamp().first > 0 &&
+                  std::difftime(std::time(nullptr), last_timestamp_in_s) < ENGINE_VALUE_TIMEOUT)
+               {
+                       engine_on = true;
+               }
+               else
+               {
+                       AFB_NOTICE("is_engine_on: engine.speed diagnostic message found, but engine seems off");
+               }
+       }
+       else
+       {
+               AFB_NOTICE("is_engine_on: Can't identify a useable engine.speed diagnostic message");
+       }
+
+       return engine_on;
+}
\ No newline at end of file
index fa2204f..9349487 100644 (file)
@@ -78,6 +78,8 @@ class application_t
 
                uint32_t get_signal_id(can_signal_t& sig) const;
 
+               bool isEngineOn();
+
                void set_active_message_set(uint8_t id);
 
 /*
index d8365da..bff5c93 100644 (file)
@@ -210,6 +210,9 @@ static int subscribe_unsubscribe_diagnostic_messages(struct afb_req request,
                // poll a PID for nothing.
                if(sig->get_supported() && subscribe)
                {
+                       if (!app.isEngineOn())
+                               AFB_WARNING("signal: Engine is off, %s won't received responses until it's on",  sig->get_name().c_str());
+
                        diag_m.add_recurring_request(diag_req, sig->get_name().c_str(), false, sig->get_decoder(), sig->get_callback(), event_filter.frequency, perm_rec_diag_req);
                        if(can_subscription->create_rx_filter(sig) < 0)
                                {return -1;}
@@ -651,6 +654,7 @@ void list(struct afb_req request)
 /// @return Exit code, zero if success.
 int initv2()
 {
+       uint32_t ret = 1;
        can_bus_t& can_bus_manager = application_t::instance().get_can_bus_manager();
 
        can_bus_manager.set_can_devices();
@@ -660,8 +664,29 @@ int initv2()
        /// We pass by default the first CAN bus device to its Initialization.
        /// TODO: be able to choose the CAN bus device that will be use as Diagnostic bus.
        if(application_t::instance().get_diagnostic_manager().initialize())
-               return 0;
+               ret = 0;
+
+       // Add a recurring dignostic message request to get engine speed continuously
+       openxc_DynamicField search_key = build_DynamicField("diagnostic_messages.engine.speed");
+       struct utils::signals_found sf = utils::signals_manager_t::instance().find_signals(search_key);
+
+       if(sf.can_signals.empty() && sf.diagnostic_messages.size() == 1)
+       {
+               struct afb_req request;
+               request.itf = nullptr;
+               request.closure = nullptr;
+
+               struct event_filter_t event_filter;
+               event_filter.frequency = sf.diagnostic_messages.front()->get_frequency();
 
-       AFB_ERROR("There was something wrong with CAN device Initialization.");
-       return 1;
+               utils::signals_manager_t& sm = utils::signals_manager_t::instance();
+               std::map<int, std::shared_ptr<low_can_subscription_t> >& s = sm.get_subscribed_signals();
+
+               subscribe_unsubscribe_diagnostic_messages(request, true, sf.diagnostic_messages, event_filter, s, true);
+       }
+
+       if(ret)
+               AFB_ERROR("There was something wrong with CAN device Initialization.");
+
+       return ret;
 }