fixed obd2. added getSourcesForInterface
[profile/ivi/automotive-message-broker.git] / ambd / core.cpp
1 /*
2     Copyright (C) 2012  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
20 #include "core.h"
21 #include <functional>
22 #include <glib.h>
23 #include "listplusplus.h"
24 #include "debugout.h"
25
26 using namespace std::placeholders;
27
28 int lastpps=0;
29
30 static int PPSUpdate(void* data)
31 {
32         int* pps = (int*)data;
33
34         int temp = *pps;
35
36         if(temp > 0 && temp != lastpps)
37         {
38                 lastpps = temp;
39                 DebugOut(1)<<"Property updates per second: "<<temp<<endl;
40         }
41
42         *pps = 0;
43 }
44
45 Core::Core()
46         :propertiesPerSecond(0)
47 {
48         g_timeout_add(1000,PPSUpdate,&propertiesPerSecond);
49 }
50
51 Core::~Core()
52 {
53         std::vector<AbstractSink*> toDelete;
54         for(auto itr = mSinks.begin(); itr != mSinks.end(); itr++)
55         {
56                 AbstractSink* sink = *itr;
57                 toDelete.push_back(sink);
58         }
59
60         for(int i=0; i<toDelete.size(); i++)
61         {
62                 delete toDelete[i];
63         }
64 }
65
66
67 void Core::setSupported(PropertyList supported, AbstractSource* source)
68 {
69
70         if(!ListPlusPlus<AbstractSource*>(&mSources).contains(source))
71                 mSources.push_back(source);
72                 
73         for(PropertyList::iterator itr = supported.begin(); itr != supported.end(); itr++)
74         {
75                 if(!ListPlusPlus<VehicleProperty::Property>(&mMasterPropertyList).contains((*itr)))
76                 {
77                         DebugOut()<<__FUNCTION__<<"() adding support for property "<<(*itr)<<endl;
78                         mMasterPropertyList.push_back((*itr));
79                 }
80         }
81
82         /// tell all new sinks about the newly supported properties.
83
84         for(SinkList::iterator itr = mSinks.begin(); itr != mSinks.end(); itr++)
85         {
86                 (*itr)->supportedChanged(mMasterPropertyList);
87         }
88
89         /// iterate through subscribed properties and resubscribe.  This catches newly supported properties in the process.
90
91         for(map<VehicleProperty::Property, SinkList>::iterator itr = propertySinkMap.begin(); itr != propertySinkMap.end(); itr++)
92         {
93                 VehicleProperty::Property  property = (*itr).first;
94
95                 for(SourceList::iterator source = mSources.begin(); source != mSources.end(); source++)
96                 {
97                         PropertyList properties = (*source)->supported();
98
99                         if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(property))
100                         {
101                                 (*source)->subscribeToPropertyChanges(property);
102                         }
103                 }
104         }
105 }
106
107
108 void Core::updateSupported(PropertyList added, PropertyList removed)
109 {
110         
111         /// add the newly supported to master list
112         
113         for(PropertyList::iterator itr = added.begin(); itr != added.end(); itr++)
114         {
115                 if(ListPlusPlus<VehicleProperty::Property>(&added).contains(*itr))
116                 {
117                         mMasterPropertyList.push_back(*itr);
118                 }
119         }
120         
121         /// removed no longer supported properties from master list.
122         
123         for(PropertyList::iterator itr = removed.begin(); itr != removed.end(); itr++)
124         {
125                 ListPlusPlus<VehicleProperty::Property>(&mMasterPropertyList).removeOne(*itr);
126         }
127         
128         /// tell all new sinks about the newly supported properties.
129         
130         for(SinkList::iterator itr = mSinks.begin(); itr != mSinks.end(); itr++)
131         {
132                 (*itr)->supportedChanged(mMasterPropertyList);
133         }
134         
135         /// iterate through subscribed properties and resubscribe.  This catches newly supported properties in the process.
136         
137         for(map<VehicleProperty::Property, SinkList>::iterator itr = propertySinkMap.begin(); itr != propertySinkMap.end(); itr++)
138         {
139                 VehicleProperty::Property  property = (*itr).first;
140                 
141                 for(SourceList::iterator source = mSources.begin(); source != mSources.end(); source++)
142                 {
143                         PropertyList properties = (*source)->supported();
144                         
145                         if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(property))
146                         {
147                                 (*source)->subscribeToPropertyChanges(property);
148                         }
149                 }
150         }
151 }
152
153 void Core::updateProperty(VehicleProperty::Property property, AbstractPropertyType *value, std::string uuid)
154 {
155         SinkList list = propertySinkMap[property];
156         
157         DebugOut()<<__FUNCTION__<<"() there are "<<list.size()<<" sinks connected to property: "<<property<<endl;
158
159         propertiesPerSecond++;
160
161
162         for(SinkList::iterator itr = list.begin(); itr != list.end(); itr++)
163         {
164                 (*itr)->propertyChanged(property, value, uuid);
165         }
166 }
167
168 std::list<std::string> Core::sourcesForProperty(VehicleProperty::Property property)
169 {
170         std::list<std::string> l;
171
172         for(auto itr = mSources.begin(); itr != mSources.end(); itr++)
173         {
174                 AbstractSource* src = *itr;
175
176                 PropertyList s = src->supported();
177
178                 if(ListPlusPlus<VehicleProperty::Property>(&s).contains(property))
179                 {
180                         l.push_back(src->uuid());
181                 }
182         }
183
184         return l;
185 }
186
187 void Core::registerSink(AbstractSink *self)
188 {
189         if(!ListPlusPlus<AbstractSink*>(&mSinks).contains(self))
190         {
191                 mSinks.push_back(self);
192         }
193 }
194
195 void Core::unregisterSink(AbstractSink *self)
196 {
197         if(ListPlusPlus<AbstractSink*>(&mSinks).contains(self))
198         {
199                 ListPlusPlus<AbstractSink*>(&mSinks).removeOne(self);
200         }
201 }
202
203
204 AsyncPropertyReply *Core::getPropertyAsync(AsyncPropertyRequest request)
205 {
206         AsyncPropertyReply * reply = new AsyncPropertyReply(request);
207
208         for(SourceList::iterator itr = mSources.begin(); itr != mSources.end(); itr++)
209         {
210                 AbstractSource* src = (*itr);
211                 PropertyList properties = src->supported();
212                 int supportedOps = src->supportedOperations();
213
214                 bool supportsGet = supportedOps & AbstractSource::Get;
215
216                 if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(request.property) && supportsGet && (request.sourceUuid == "" || request.sourceUuid == src->uuid()))
217                 {
218                         src->getPropertyAsync(reply);
219
220                         /** right now the owner of the reply becomes the requestor that called this method.
221                          *  reply will become invalid after the first reply. */
222                         return reply;
223                 }
224         }
225
226         return reply;
227 }
228
229 AsyncRangePropertyReply *Core::getRangePropertyAsync(AsyncRangePropertyRequest request)
230 {
231         AsyncRangePropertyReply * reply = new AsyncRangePropertyReply(request);
232
233         for(SourceList::iterator itr = mSources.begin(); itr != mSources.end(); itr++)
234         {
235                 AbstractSource* src = (*itr);
236                 PropertyList properties = src->supported();
237                 if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(request.property)
238                                 && (src->supportedOperations() & AbstractSource::GetRanged)
239                                 && (request.sourceUuid == "" || request.sourceUuid == src->uuid()))
240                 {
241                         src->getRangePropertyAsync(reply);
242                 }
243         }
244
245         return reply;
246 }
247
248 AsyncPropertyReply * Core::setProperty(AsyncSetPropertyRequest request)
249 {
250         for(SourceList::iterator itr = mSources.begin(); itr != mSources.end(); itr++)
251         {
252                 AbstractSource* src = (*itr);
253                 PropertyList properties = src->supported();
254                 if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(request.property) && src->supportedOperations() & AbstractSource::Set)
255                 {
256                         return src->setProperty(request);
257                 }
258         }
259
260         DebugOut(0)<<"Error: setProperty opration failed"<<endl;
261         return NULL;
262 }
263
264 void Core::subscribeToProperty(VehicleProperty::Property property, AbstractSink* self)
265 {
266         DebugOut(1)<<"Subscribing to: "<<property<<endl;
267
268         /** TODO: Change behavior of subscribe to subscribe even if no sources provide a
269          *  given property.  When subscribers come online with support, core should tell
270          *  the sources what properties have already been subscribed to.
271          */
272
273         /*if(!ListPlusPlus<VehicleProperty::Property>(&mMasterPropertyList).contains((property)))
274         {
275                 DebugOut(1)<<__FUNCTION__<<"(): property not supported: "<<property<<endl;
276                 return; 
277         }*/
278         
279         if(propertySinkMap.find(property) == propertySinkMap.end())
280         {
281                 propertySinkMap[property] = SinkList();
282         }
283         
284         SinkList list = propertySinkMap[property];
285         
286         if(!ListPlusPlus<AbstractSink*>(&list).contains(self))
287         {
288                 propertySinkMap[property].push_back(self);
289         }
290         
291         for(SourceList::iterator itr = mSources.begin(); itr != mSources.end(); itr++)
292         {
293                 AbstractSource* src = (*itr);
294                 PropertyList properties = src->supported();
295                 if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(property))
296                 {
297                         src->subscribeToPropertyChanges(property);
298                 }
299         }
300 }
301
302 void Core::unsubscribeToProperty(VehicleProperty::Property property, AbstractSink* self)
303 {
304         if(propertySinkMap.find(property) == propertySinkMap.end())
305         {
306                 DebugOut(1)<<__FUNCTION__<<"property not supported: "<<property<<endl;
307                 return; 
308         }
309                 
310         ListPlusPlus<AbstractSink*>(&propertySinkMap[property]).removeOne(self);
311
312         /// Now we check to see if this is the last subscriber
313         if(propertySinkMap.find(property) == propertySinkMap.end())
314         {
315                 for(SourceList::iterator itr = mSources.begin(); itr != mSources.end(); itr++)
316                 {
317                         AbstractSource* src = (*itr);
318                         PropertyList properties = src->supported();
319
320                         if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(property))
321                         {
322                                 src->unsubscribeToPropertyChanges(property);
323                         }
324                 }
325         }
326 }
327