added tools
[profile/ivi/automotive-message-broker.git] / tools / AmbSignalMapper / lib / Intel / IviPoc / templates / ambtmpl_cansignal.h
1 /*****************************************************************
2 Copyright (C) 2014  Intel Corporation
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  *****************************************************************/
18
19 #ifndef AMBTMPL_CANSIGNAL_H_
20 #define AMBTMPL_CANSIGNAL_H_
21
22 #include <map>
23 #include <limits>
24 #include <glib.h>
25 #include <abstractpropertytype.h>
26 #include <vehicleproperty.h>
27 #include <byteswap.h>
28 #include <boost/any.hpp>
29
30 #include <canbus.h>
31 #include <canobserver.h>
32
33 enum Endian{
34     Motorola = 0x0,     // BigEndian
35     Intel = 0x1         // LittleEndian
36 };
37
38 enum Signedness{
39     Unsigned = 0x0,     // Unsigned
40     Signed = 0x1        // Signed
41 };
42
43 const int CANFrameDataSize = 8*sizeof(can_frame::data);
44
45 template<typename T>
46 T convert( double temp )
47 {
48     return static_cast<T>(temp);
49 }
50
51 template<typename T>
52 T convert( const boost::any& temp )
53 {
54     return boost::any_cast<T>(temp);
55 }
56
57 template<typename T>
58 GVariant* toGVariant(const T& value, const GVariantClass& c)
59 {
60     if(c == G_VARIANT_CLASS_BOOLEAN)
61         return g_variant_new_boolean(static_cast<gboolean>(value));
62
63     else if(c == G_VARIANT_CLASS_BYTE)
64         return g_variant_new_byte(static_cast<guchar>(value));
65
66     else if(c == G_VARIANT_CLASS_INT16)
67         return g_variant_new_int16(static_cast<gshort>(value));
68
69     else if(c == G_VARIANT_CLASS_UINT16)
70         return g_variant_new_uint16(static_cast<gushort>(value));
71
72     else if(c == G_VARIANT_CLASS_INT32)
73         return g_variant_new_int32(static_cast<gint>(value));
74
75     else if(c ==  G_VARIANT_CLASS_UINT32)
76         return g_variant_new_uint32(static_cast<guint>(value));
77
78     else if(c == G_VARIANT_CLASS_INT64)
79         return g_variant_new_int64(static_cast<gint64>(value));
80
81     else if(c == G_VARIANT_CLASS_UINT64)
82         return g_variant_new_int64(static_cast<guint64>(value));
83
84     else if(c == G_VARIANT_CLASS_DOUBLE)
85         return g_variant_new_double(static_cast<gdouble>(value));
86
87     else
88         return nullptr;
89 }
90
91 class CANSignal {
92
93 public:
94     explicit CANSignal(std::function<AbstractPropertyType* ()> factoryFunction);
95     virtual ~CANSignal();
96
97     virtual GVariant *processSignal( const can_frame& frame ) = 0;
98
99     virtual void onMessage( const can_frame& frame, std::function<void (AbstractPropertyType*)> changeCallback );
100
101     virtual bool updateFrame( can_frame* frame );
102
103     template <typename T>
104     GVariant* processFrameBits( const can_frame& frame )
105     {
106         int64_t bits = getSignalBits( frame );
107         double temp = static_cast<double>(bits)*signalInfo.m_factor + signalInfo.m_offset;
108         T value(convert<T>(conversionFunctionFrom(temp, bits)));
109         return toGVariant<T>(value, signature);
110     }
111
112     virtual boost::any conversionFunctionFrom(double value, int64_t bits) = 0;
113
114     virtual uint64_t conversionFunctionTo(double value, uint64_t bits) = 0;
115
116     void setAmbProperty(std::shared_ptr<AbstractPropertyType> ambProperty);
117
118     inline std::function<AbstractPropertyType* ()> factory()
119     {
120         return factoryFunction;
121     }
122
123 protected:
124     int64_t getSignalBits( const can_frame& frame );
125     uint64_t toSignalBits( int64_t bits );
126
127 protected:
128     struct SignalInfo {
129         uint8_t m_startbit;
130         uint8_t m_length;
131         Endian m_byteOrdering;
132         Signedness m_signedness;
133         double m_factor;
134         double m_offset;
135     };
136
137     SignalInfo signalInfo;
138     std::shared_ptr<AbstractPropertyType> ambProperty;
139     GVariantClass signature;
140     std::function<AbstractPropertyType* ()> factoryFunction;
141 };
142
143 class CANMessage
144 {
145 public:
146     CANMessage() = delete;
147
148     CANMessage(canid_t canId, __u8 canDlc) :
149         canId(canId),
150         canDlc(canDlc)
151     {
152     }
153
154     void addSignal(const VehicleProperty::Property& name, std::shared_ptr<CANSignal> signal)
155     {
156         if(signal)
157             canSignals[name] = signal;
158     }
159
160     void onMessage(const can_frame& frame, std::function<void (AbstractPropertyType*)> changeCallback)
161     {
162         if(frame.can_dlc != canDlc || frame.can_id != canId)
163             return;
164
165         for ( auto it = canSignals.begin(); it != canSignals.end(); ++it ) {
166             std::shared_ptr<CANSignal> signal(it->second);
167
168             if ( signal ) {
169                 signal->onMessage(frame, changeCallback);
170             }
171         }
172     }
173
174     void setupFrame(can_frame* frame)
175     {
176         if(!frame)
177             return;
178
179         memset(frame, 0, sizeof(can_frame));
180         frame->can_id = canId;
181         frame->can_dlc = canDlc;
182
183         for ( auto it = canSignals.begin(); it != canSignals.end(); ++it ) {
184             it->second->updateFrame(frame);
185         }
186     }
187
188 private:
189     canid_t canId;
190     __u8 canDlc;
191     std::map< VehicleProperty::Property , std::shared_ptr<CANSignal> > canSignals;
192 };
193
194 #define CANSIGNAL(property, valueType, startbit, length, byteOrdering, signedness, factor, offset, minValue, maxValue, convertFrom, convertTo) \
195     class property ## Type : public CANSignal { \
196     public: property ## Type() : \
197             CANSignal([](){ return new BasicPropertyType<valueType>(property); } ) \
198             , convertFromFunction(convertFrom) \
199             , convertToFunction(convertTo) \
200     {\
201         signalInfo.m_startbit = startbit; \
202         signalInfo.m_length = length; \
203         signalInfo.m_byteOrdering = byteOrdering; \
204         signalInfo.m_signedness = signedness; \
205         signalInfo.m_factor = factor; \
206         signalInfo.m_offset = offset; \
207         m_minValue = minValue; \
208         m_maxValue = maxValue; \
209     } \
210     GVariant *processSignal( const can_frame& frame ) { \
211         return processFrameBits<valueType>( frame ); \
212     } \
213     boost::any conversionFunctionFrom(double value, int64_t bits) { \
214         valueType targetValue(convert<valueType>(value)); \
215         if(convertFromFunction) \
216             return convertFromFunction(targetValue, bits); \
217         else return targetValue; \
218     } \
219     uint64_t conversionFunctionTo(double value, uint64_t bits) { \
220         if(convertToFunction) \
221             convertToFunction(convert<valueType>(value), bits); \
222         else return bits; \
223     } \
224     valueType m_minValue; \
225     valueType m_maxValue; \
226     std::function<valueType(valueType, int64_t)> convertFromFunction; \
227     std::function<uint64_t(valueType, uint64_t)> convertToFunction; \
228     typedef valueType value_type; \
229     };
230
231 #endif /* AMBTMPL_CANSIGNAL_H_ */