1 /*****************************************************************
2 Copyright (C) 2014 Intel Corporation
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.
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.
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 *****************************************************************/
19 #ifndef AMBTMPL_CANSIGNAL_H_
20 #define AMBTMPL_CANSIGNAL_H_
25 #include <abstractpropertytype.h>
26 #include <vehicleproperty.h>
28 #include <boost/any.hpp>
31 #include <canobserver.h>
34 Motorola = 0x0, // BigEndian
35 Intel = 0x1 // LittleEndian
39 Unsigned = 0x0, // Unsigned
40 Signed = 0x1 // Signed
43 const int CANFrameDataSize = 8*sizeof(can_frame::data);
46 T convert( double temp )
48 return static_cast<T>(temp);
52 T convert( const boost::any& temp )
54 return boost::any_cast<T>(temp);
58 GVariant* toGVariant(const T& value, const GVariantClass& c)
60 if(c == G_VARIANT_CLASS_BOOLEAN)
61 return g_variant_new_boolean(static_cast<gboolean>(value));
63 else if(c == G_VARIANT_CLASS_BYTE)
64 return g_variant_new_byte(static_cast<guchar>(value));
66 else if(c == G_VARIANT_CLASS_INT16)
67 return g_variant_new_int16(static_cast<gshort>(value));
69 else if(c == G_VARIANT_CLASS_UINT16)
70 return g_variant_new_uint16(static_cast<gushort>(value));
72 else if(c == G_VARIANT_CLASS_INT32)
73 return g_variant_new_int32(static_cast<gint>(value));
75 else if(c == G_VARIANT_CLASS_UINT32)
76 return g_variant_new_uint32(static_cast<guint>(value));
78 else if(c == G_VARIANT_CLASS_INT64)
79 return g_variant_new_int64(static_cast<gint64>(value));
81 else if(c == G_VARIANT_CLASS_UINT64)
82 return g_variant_new_int64(static_cast<guint64>(value));
84 else if(c == G_VARIANT_CLASS_DOUBLE)
85 return g_variant_new_double(static_cast<gdouble>(value));
94 explicit CANSignal(std::function<AbstractPropertyType* ()> factoryFunction);
97 virtual GVariant *processSignal( const can_frame& frame ) = 0;
99 virtual void onMessage( const can_frame& frame, std::function<void (AbstractPropertyType*)> changeCallback );
101 virtual bool updateFrame( can_frame* frame );
103 template <typename T>
104 GVariant* processFrameBits( const can_frame& frame )
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);
112 virtual boost::any conversionFunctionFrom(double value, int64_t bits) = 0;
114 virtual uint64_t conversionFunctionTo(double value, uint64_t bits) = 0;
116 void setAmbProperty(std::shared_ptr<AbstractPropertyType> ambProperty);
118 inline std::function<AbstractPropertyType* ()> factory()
120 return factoryFunction;
124 int64_t getSignalBits( const can_frame& frame );
125 uint64_t toSignalBits( int64_t bits );
131 Endian m_byteOrdering;
132 Signedness m_signedness;
137 SignalInfo signalInfo;
138 std::shared_ptr<AbstractPropertyType> ambProperty;
139 GVariantClass signature;
140 std::function<AbstractPropertyType* ()> factoryFunction;
146 CANMessage() = delete;
148 CANMessage(canid_t canId, __u8 canDlc) :
154 void addSignal(const VehicleProperty::Property& name, std::shared_ptr<CANSignal> signal)
157 canSignals[name] = signal;
160 void onMessage(const can_frame& frame, std::function<void (AbstractPropertyType*)> changeCallback)
162 if(frame.can_dlc != canDlc || frame.can_id != canId)
165 for ( auto it = canSignals.begin(); it != canSignals.end(); ++it ) {
166 std::shared_ptr<CANSignal> signal(it->second);
169 signal->onMessage(frame, changeCallback);
174 void setupFrame(can_frame* frame)
179 memset(frame, 0, sizeof(can_frame));
180 frame->can_id = canId;
181 frame->can_dlc = canDlc;
183 for ( auto it = canSignals.begin(); it != canSignals.end(); ++it ) {
184 it->second->updateFrame(frame);
191 std::map< VehicleProperty::Property , std::shared_ptr<CANSignal> > canSignals;
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) \
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; \
210 GVariant *processSignal( const can_frame& frame ) { \
211 return processFrameBits<valueType>( frame ); \
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; \
219 uint64_t conversionFunctionTo(double value, uint64_t bits) { \
220 if(convertToFunction) \
221 convertToFunction(convert<valueType>(value), bits); \
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; \
231 #endif /* AMBTMPL_CANSIGNAL_H_ */