6bb6459f1c6708d83cd992cc0b38bc0a03cddd4b
[apps/low-level-can-service.git] / src / can_decode_message.cpp
1 /*
2  * Copyright (C) 2015, 2016 "IoT.bzh"
3  * Author "Romain Forlot" <romain.forlot@iot.bzh>
4  * Author "Loic Collignon" <loic.collignon@iot.bzh>
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *       http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <linux/can.h>
20 #include <linux/can/raw.h>
21 #include <queue>
22 #include <sys/timeb.h>
23
24 #include <afb/afb-binding.h>
25
26 #include "can-utils.h"
27 #include "can-decoder.h"
28 #include "openxc.pb.h"
29
30 union DynamicField
31 {
32         char string[100];
33         double numeric_value;
34         bool boolean_value;
35 };
36
37 void can_decode_message(can_bus_t &can_bus)
38 {
39         can_message_t *can_message;
40         std:vector <CanSignal> signals;
41         std:vector <CanSignal>::iterator signals_i;
42         openxc_VehicleMessage vehicle_message;
43         openxc_DynamicField search_key, ret;
44         
45         decoder_t decoder();
46
47
48         while(true)
49         {
50                 if(can_message = can_bus.next_can_message())
51                 {
52                         /* First we have to found which CanSignal is */
53                         DynamicField signal_id = (double)can_message.get_id();
54                         search_key = build_DynamicField(openxc_DynamicField_Type_NUM, signal_id)
55
56                         signals = find_signals(search_key);
57                         
58                         /* Decoding the message ! Don't kill the messenger ! */
59                         for(signals_i=signals.begin(); signal_i != signals.end(); signals_i++)
60                         {
61                                 subscribed_signals_i = subscribed_signals.find(signals_i);
62                                 
63                                 if(subscribed_signals_i != subscribed_signals.end() &&
64                                         afb_event_is_valid(subscribed_signals_i->second))
65                                 {
66                                         ret = decoder.decodeSignal(&sig, can_message, SIGNALS, SIGNALS.size(), true);
67
68                                         s_message = build_SimpleMessage(subscribed_signals_i->first->genericName, ret);
69                                                 
70                                         vehicle_message = build_VehicleMessage_with_SimpleMessage(openxc_DynamicField_Type::openxc_DynamicField_Type_NUM, s_message);
71                                         vehicle_message_q.push(vehicle_message);
72                                 }
73                         }
74                 }
75         }
76 }
77
78 /*
79  * Build a specific VehicleMessage containing a SimpleMessage.
80  */
81 openxc_VehicleMessage build_VehicleMessage_with_SimpleMessage(openxc_DynamicField_Type type,
82                                                                                                                           openxc_SimpleMessage message)
83 {
84         struct timeb t_msec;
85         long long int timestamp_msec;
86         if(!ftime(&t_msec))
87         {
88                 timestamp_msec = ((long long int) t_msec.time) * 1000ll + 
89                         (long long int) t_msec.millitm;
90
91         return openxc_VehicleMessage v = {.has_type = true,
92                                           .type = openxc_VehicleMessage_Type::openxc_VehicleMessage_Type_SIMPLE,
93                                           .has_simple_message = true,
94                                           .simple_message =  message,
95                                           .has_timestamp = true,
96                                           .timestamp = timestamp_msec};
97         }
98
99         return openxc_VehicleMessage v = {.has_type = true,
100                                           .type = openxc_VehicleMessage_Type::openxc_VehicleMessage_Type_SIMPLE,
101                                           .has_simple_message = true,
102                                           .simple_message =  message};
103 }
104
105 /*
106  * Build an openxc_SimpleMessage associating a name to an openxc_DynamicField
107  */
108 openxc_SimpleMessage build_SimpleMessage(std:string name, openxc_DynamicField value)
109 {
110         return openxc_SimpleMessage s = {.has_name = true,
111                                                                          .name = name,
112                                                                          .has_value = true,
113                                                                          .value = value};
114 }
115
116
117 }
118
119 /* 
120  * Build an openxc_DynamicField using its type and an union.
121  * Why do not use of union in first place anyway...
122  */
123 openxc_DynamicField build_DynamicField(openxc_DynamicField_Type type, DynamicField field)
124 {
125         openxc_DynamicField d = {.has_type = true,
126                                                                         .type = type};
127         
128         switch(type)
129         {
130                 case openxc_DynamicField_Type_BOOL:
131                         d.has_boolean_value = true;
132                         d.boolean_value = field;
133                         break;
134                 case openxc_DynamicField_Type_NUM:
135                         d.has_numeric_value = true;
136                         d.numeric_value = field;
137                         break;
138                 case openxc_DynamicField_Type_STRING:
139                         d.has_string_value = true;
140                         strcpy(d.string_value, field);
141                         break;
142                 default:
143                         return nullptr;
144         }
145
146         return d;
147 }