bcb8d73236a64daded23d552386540558ffe0140
[apps/agl-service-can-low-level.git] / low-can-binding / binding / application.cpp
1 /*
2  * Copyright (C) 2015, 2016 "IoT.bzh"
3  * Author "Romain Forlot" <romain.forlot@iot.bzh>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #include <ctime>
18
19 #include "application.hpp"
20
21 #include "../utils/signals.hpp"
22 #include "../utils/openxc-utils.hpp"
23 #include "low-can-subscription.hpp"
24
25 #define MICROSECONDS_IN_SECOND  1000000
26 #define ENGINE_VALUE_TIMEOUT    5
27
28 /// @brief Return singleton instance of configuration object.
29 application_t& application_t::instance()
30 {
31         static application_t config;
32         return config;
33 }
34
35 can_bus_t& application_t::get_can_bus_manager()
36 {
37         return can_bus_manager_;
38 }
39
40 std::map<std::string, std::shared_ptr<low_can_subscription_t> >& application_t::get_can_devices()
41 {
42         return can_devices_;
43 }
44
45 diagnostic_manager_t& application_t::get_diagnostic_manager()
46 {
47         return diagnostic_manager_;
48 }
49
50 uint8_t application_t::get_active_message_set() const
51 {
52         return active_message_set_;
53 }
54
55 int application_t::add_message_set(std::shared_ptr<message_set_t> new_message_set)
56 {
57
58         vect_ptr_msg_def_t messages_definition = new_message_set->get_messages_definition();
59         for(std::shared_ptr<message_definition_t> cmd : messages_definition)
60         {
61                 cmd->set_parent(new_message_set);
62                 std::vector<std::shared_ptr<signal_t>> signals = cmd->get_signals();
63                 for(std::shared_ptr<signal_t> sig: signals)
64                         sig->set_parent(cmd);
65         }
66
67         std::vector<std::shared_ptr<diagnostic_message_t>> diagnostic_messages = new_message_set->get_diagnostic_messages();
68         for(std::shared_ptr<diagnostic_message_t> dm : diagnostic_messages)
69                 dm->set_parent(new_message_set);
70
71         for(auto old_msg_set : message_set_)
72         {
73                 if(old_msg_set->get_index() == new_message_set->get_index())
74                 {
75
76                         for(auto new_msg_def : new_message_set->get_messages_definition())
77                         {
78                                 if(old_msg_set->add_message_definition(new_msg_def) < 0)
79                                         return -1;
80                         }
81
82                         for(auto new_diag_msg : new_message_set->get_diagnostic_messages())
83                         {
84                                 if(old_msg_set->add_diagnostic_message(new_diag_msg) < 0)
85                                         return -1;
86                         }
87
88                         return 0;
89                 }
90         }
91
92         message_set_.push_back(new_message_set);
93         return 0;
94 }
95
96 std::vector<std::shared_ptr<message_set_t> > application_t::get_message_set()
97 {
98         return message_set_;
99 }
100
101 vect_ptr_signal_t application_t::get_all_signals()
102 {
103         return message_set_[active_message_set_]->get_all_signals();
104 }
105
106 vect_ptr_diag_msg_t application_t::get_diagnostic_messages()
107 {
108         return message_set_[active_message_set_]->get_diagnostic_messages();
109 }
110
111 vect_ptr_msg_def_t application_t::get_messages_definition()
112 {
113         return message_set_[active_message_set_]->get_messages_definition();
114 }
115
116
117 std::shared_ptr<message_definition_t> application_t::get_message_definition(uint32_t id)
118 {
119         std::shared_ptr<message_definition_t> ret = nullptr;
120         vect_ptr_msg_def_t messages_definition = get_messages_definition();
121         for(std::shared_ptr<message_definition_t> &msg_def : messages_definition)
122         {
123                 if(msg_def->get_id() == id)
124                 {
125                         ret = msg_def;
126                         break;
127                 }
128         }
129         return ret;
130 }
131
132
133 uint32_t application_t::get_signal_id(diagnostic_message_t& sig) const
134 {
135         return sig.get_pid();
136 }
137
138 uint32_t application_t::get_signal_id(signal_t& sig) const
139 {
140         return sig.get_message()->get_id();
141 }
142
143 void application_t::set_active_message_set(uint8_t id)
144 {
145         active_message_set_ = id;
146 }
147
148 bool application_t::isEngineOn()
149 {
150         struct utils::signals_found sf;
151         openxc_DynamicField search_key = build_DynamicField("engine.speed");
152         sf = utils::signals_manager_t::instance().find_signals(search_key);
153         bool engine_on = false;
154         uint64_t last_timestamp_in_s;
155
156         if(sf.signals.size() == 1)
157         {
158                 last_timestamp_in_s = sf.signals.front()->get_last_value_with_timestamp().second
159                                                 / MICROSECONDS_IN_SECOND;
160
161                 if(sf.signals.front()->get_last_value_with_timestamp().first > 0 &&
162                    std::difftime(std::time(nullptr), last_timestamp_in_s) < ENGINE_VALUE_TIMEOUT)
163                 {
164                         engine_on = true;
165                 }
166                 else
167                 {
168                         AFB_NOTICE("is_engine_on: engine.speed CAN signal found, but engine seems off");
169                 }
170         }
171         else
172         {
173                 AFB_NOTICE("is_engine_on: Can't identify a useable engine.speed CAN signal");
174         }
175
176         if(sf.diagnostic_messages.size() == 1)
177         {
178                 last_timestamp_in_s = sf.diagnostic_messages.front()->get_last_value_with_timestamp().second
179                                                 / MICROSECONDS_IN_SECOND;
180
181                 if(sf.diagnostic_messages.front()->get_last_value_with_timestamp().first > 0 &&
182                    std::difftime(std::time(nullptr), last_timestamp_in_s) < ENGINE_VALUE_TIMEOUT)
183                 {
184                         engine_on = true;
185                 }
186                 else
187                 {
188                         AFB_NOTICE("is_engine_on: engine.speed diagnostic message found, but engine seems off");
189                 }
190         }
191         else
192         {
193                 AFB_NOTICE("is_engine_on: Can't identify a useable engine.speed diagnostic message");
194         }
195
196         return engine_on;
197 }
198
199 #ifdef USE_FEATURE_J1939
200 std::shared_ptr<utils::socketcan_t> application_t::get_socket_address_claiming()
201 {
202         return subscription_address_claiming_->get_socket();
203 }
204
205 std::shared_ptr<low_can_subscription_t> application_t::get_subscription_address_claiming()
206 {
207         return subscription_address_claiming_;
208 }
209
210
211 void application_t::set_subscription_address_claiming(std::shared_ptr<low_can_subscription_t> new_subscription)
212 {
213         subscription_address_claiming_ = new_subscription;
214 }
215
216 #endif