6f6c8890534e6bf51651da6b54988f93235d20cd
[profile/ivi/automotive-message-broker.git] / tools / AmbSignalMapper / lib / Intel / IviPoc / templates / ambtmpl_plugin.cpp
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 #include <boost/assert.hpp>
20 #include <glib.h>
21 #include <cstdarg>
22
23 #include <vehicleproperty.h>
24 #include <listplusplus.h>
25
26 #include <logger.h>
27
28 #include "ambtmpl_plugin.h"
29 #include "ambtmpl_cansignals.h"
30
31 //using namespace AmbTmplPlugin;
32
33 static const char* DEFAULT_CAN_IF_NAME = "vcan0";
34
35 // library exported function for plugin loader
36 extern "C" AbstractSource * create(AbstractRoutingEngine* routingengine, std::map<std::string, std::string> config)
37 {
38 #ifndef UNIT_TESTS
39     DEBUG_CONF("AmbTmplPlugin",
40         CUtil::Logger::file_off|CUtil::Logger::screen_on,
41         CUtil::Logger::EInfo, CUtil::Logger::EInfo
42     );
43 #endif
44
45     std::unique_ptr< AmbPlugin<AmbTmplPlugin> > plugin(new AmbPlugin<AmbTmplPlugin>(routingengine, config));
46     plugin->init();
47     return plugin.release();
48 }
49
50 void AmbTmplPlugin::timerDestroyNotify(gpointer data)
51 {
52     TimerData* timerData = reinterpret_cast<TimerData*>(data);
53     if(timerData){
54         AmbTmplPlugin* plugin = std::get<0>(*timerData);
55         const can_frame& frame = std::get<3>(*timerData);
56         plugin->eraseTimer(frame.can_id);
57         delete timerData;
58     }
59
60 }
61
62 gboolean AmbTmplPlugin::timeoutCallback(gpointer data)
63 {
64     TimerData* timerData = reinterpret_cast<TimerData*>(data);
65     if(!timerData)
66         return false;
67
68     CANBus* bus = std::get<1>(*timerData);
69     int retries = --std::get<2>(*timerData);
70     const can_frame& frame = std::get<3>(*timerData);
71
72     if(retries > 0){
73         if(bus)
74             bus->sendStandardFrame(frame);
75         return true;
76     }
77     else return false;
78 }
79
80 //----------------------------------------------------------------------------
81 // AmbTmplPlugin
82 //----------------------------------------------------------------------------
83
84 AmbTmplPlugin::AmbTmplPlugin(AbstractRoutingEngine* re, const map<string, string>& config, AbstractSource& parent) :
85       AmbPluginImpl(re, config, parent),
86       interface(DEFAULT_CAN_IF_NAME),
87       canBus(new CANBus(*static_cast<CANObserver*>(this))),
88       announcementIntervalTimer(1000),
89       announcementCount(20)
90 {
91     auto it = config.find("interface");
92     if (it != config.end() && it->second.length())
93         interface = it->second;
94
95     it = config.find("announcementIntervalTimer");
96     if (it != config.end() && it->second.length())
97         announcementIntervalTimer = atoi(std::string(it->second).c_str());
98     if(announcementIntervalTimer < 20)
99         announcementIntervalTimer = 20;
100
101     it = config.find("announcementCount");
102     if (it != config.end() && it->second.length())
103         announcementCount = atoi(std::string(it->second).c_str());
104     if(announcementCount < 1)
105             announcementIntervalTimer = 1;
106
107     registerMessages();
108 }
109
110 AmbTmplPlugin::~AmbTmplPlugin()
111 {
112     std::list<guint> timerList;
113
114     mutex.lock();
115     for(auto it=timers.begin();it!=timers.end();++it)
116         timerList.push_back(it->second);
117     mutex.unlock();
118
119     for(auto it=timerList.begin();it!=timerList.end();++it)
120         g_source_remove(*it);
121
122     canBus->stop();
123 }
124
125 void AmbTmplPlugin::init()
126 {
127     canBus->start(interface.c_str());
128 }
129
130 AsyncPropertyReply *AmbTmplPlugin::setProperty(const AsyncSetPropertyRequest& request )
131 {
132     AsyncPropertyReply* reply = new AsyncPropertyReply(request);
133     reply->success = false;
134     reply->error = AsyncPropertyReply::InvalidOperation;
135
136     AbstractPropertyType *value = findPropertyType(request.property, request.zoneFilter);
137     if (value && request.value) {
138         DebugOut(2) << "updating property "<< request.property << " to: " << request.value->toString() << endl;
139
140         std::unique_ptr<GVariant, decltype(&g_variant_unref)> variant(request.value->toVariant(), &g_variant_unref);
141         value->fromVariant(variant.get());
142
143         if(sendValue(request.value)) {
144             DebugOut(2) << "New value of property "<< request.property << " is: " << value->toString() << endl;
145             value->timestamp = amb::currentTime();
146             routingEngine->updateProperty(value, uuid());
147
148             reply->success = true;
149             reply->error = AsyncPropertyReply::NoError;
150         }
151     }
152
153     try {
154         if(reply->completed)
155             reply->completed(reply);
156     }
157     catch (...) { }
158
159     return reply;
160 }
161
162 int AmbTmplPlugin::supportedOperations() const
163 {
164     return AbstractSource::Get | AbstractSource::Set;
165 }
166
167 void AmbTmplPlugin::onMessage(const can_frame& frame)
168 {
169     auto messageIt = messages.find(frame.can_id);
170     if(messageIt == messages.end())
171         return;
172
173     CANMessage& message(messageIt->second);
174     const std::string guid = uuid();
175     AbstractRoutingEngine* re = routingEngine;
176     message.onMessage( frame, [&re, &guid](AbstractPropertyType* value){re->updateProperty(value, guid);} );
177 }
178
179 bool AmbTmplPlugin::sendValue(AbstractPropertyType* value)
180 {
181     if(!value)
182         return false;
183
184     auto it = propertyToMessage.find(value->name);
185     if(it == propertyToMessage.end())
186         return false;
187
188     CANMessage* canMessage = it->second;
189     can_frame frame;
190     canMessage->setupFrame(&frame);
191     return sendStandardFrame(frame);
192 }
193
194 // from CANObserver
195 void AmbTmplPlugin::errorOccured(CANObserver::CANError error)
196 {
197     (void) error;
198     LOG_INFO( "AmbTmplPlugin::errorOccured() not implemented "<< std::endl );
199 }
200
201 void AmbTmplPlugin::standardFrameReceived(const can_frame& frame)
202 {
203     LOG_INFO("AmbTmplPlugin::standardFrameReceived()");
204     printFrame( frame );
205
206     onMessage(frame);
207 }
208
209 void AmbTmplPlugin::extendedFrameReceived(const can_frame& frame)
210 {
211     LOG_INFO("AmbTmplPlugin::extendedFrameReceived()");
212     printFrame(frame);
213
214     onMessage(frame);
215 }
216
217 void AmbTmplPlugin::errorFrameReceived(const can_frame& frame)
218 {
219     LOG_INFO("AmbTmplPlugin::errorFrameReceived()");
220     printFrame(frame);
221 }
222
223 void AmbTmplPlugin::remoteTransmissionRequest(const can_frame& frame)
224 {
225     (void) frame;
226     LOG_INFO( "AmbTmplPlugin::remoteTransmissionRequest() not implemented "<< std::endl );
227 }
228
229 bool AmbTmplPlugin::sendStandardFrame(const can_frame& frame)
230 {
231     guint oldTimer(0);
232     mutex.lock();
233     auto it = timers.find(frame.can_id);
234     if(it != timers.end()){
235         oldTimer = it->second;
236         timers.erase(it);
237     }
238     mutex.unlock();
239
240     if(oldTimer != 0)
241         g_source_remove(oldTimer);
242
243     if ( canBus->sendStandardFrame(frame) ) {
244         LOG_TRACE( "AmbTmplPlugin::sendStandardFrame() success "<< std::endl );
245         scoped_lock<interprocess_recursive_mutex> lock(mutex);
246         std::unique_ptr< TimerData > timerData(new TimerData(this, canBus.get(), announcementCount, frame));
247         guint timer = g_timeout_add_full(G_PRIORITY_HIGH, announcementIntervalTimer, timeoutCallback, timerData.get(), timerDestroyNotify);
248         if(timer){
249             timers[frame.can_id] = timer;
250             timerData.release();
251         }
252         return true;
253     }
254     else {
255         LOG_WARNING( "AmbTmplPlugin::sendStandardFrame() failed "<< std::endl );
256         return false;
257     }
258 }
259
260 bool AmbTmplPlugin::sendExtendedFrame(const can_frame& frame)
261 {
262     if ( canBus->sendExtendedFrame(frame) ) {
263         LOG_TRACE( "AmbTmplPlugin::sendExtendedFrame() success "<< std::endl );
264         return true;
265     }
266     else {
267         LOG_WARNING( "AmbTmplPlugin::sendExtendedFrame() failed "<< std::endl );
268         return false;
269     }
270 }
271
272 void AmbTmplPlugin::printFrame(const can_frame& frame) const
273 {
274     LOG_INFO( "AmbTmplPlugin::printFrame can_id: " << std::hex << frame.can_id << std::dec );
275     LOG_INFO( "AmbTmplPlugin::printFrame can_dlc: " << int(frame.can_dlc) );
276
277     std::stringstream ss;
278     for(int i=0; i<frame.can_dlc; ++i){
279         ss << " " << std::hex << (int)(frame.data[i]);
280     }
281     ss << std::dec;
282
283     LOG_INFO( "AmbTmplPlugin::printFrame can data" << ss.str() );
284 }
285
286 void AmbTmplPlugin::registerMessages()
287 {
288 /*GENERATED_CODE*/
289 }