use ZoneList for zones
[profile/ivi/ico-vic-amb-plugin.git] / src / ambinterface.cc
1 /**
2  * Copyright (C) 2012  TOYOTA MOTOR 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 <memory>
21 #include <sstream>
22
23 #include "debugout.h"
24
25 #include "ambinterface.h"
26 #include "ambconfig.h"
27 #include "convert.h"
28 #include "mwinterface.h"
29 #include "viccommunicator.h"
30
31 extern "C" AbstractSource *
32 create(AbstractRoutingEngine* routingengine, map<string, string> config)
33 {
34     AMBIF *ambif = new AMBIF(routingengine, config);
35     AMBConfig *conf = new AMBConfig();
36     if (!conf->readConfig(config["configfile"])) {
37         DebugOut(DebugOut::Error) << "Failed to Load Configfile for VIC-Plugin.\n";
38         delete ambif;
39         delete conf;
40         return NULL;
41     }
42     VICCommunicator *communicator = new VICCommunicator();
43     MWIF *mwif = new MWIF();
44     Converter *converter = new Converter();
45     if (!ambif->initialize(communicator, conf)) {
46         DebugOut(DebugOut::Error) << "Failed to initialize AMBIF\n";
47         delete ambif;
48         delete conf;
49         delete communicator;
50         delete converter;
51         return NULL;
52     }
53     if (!communicator->initialize(ambif, mwif, converter)) {
54         DebugOut(DebugOut::Error) << "Failed to initialize VICCommunicator\n";
55         delete ambif;
56         delete conf;
57         delete communicator;
58         delete converter;
59         return NULL;
60     }
61     if (!mwif->initialize(communicator, conf)) {
62         DebugOut(DebugOut::Error) << "Failed to initialize MWIF\n";
63         delete ambif;
64         delete conf;
65         delete communicator;
66         delete converter;
67         return NULL;
68     }
69     if (!converter->initialize(conf)) {
70         DebugOut(DebugOut::Error) << "Failed to initialize Converter\n";
71         delete ambif;
72         delete conf;
73         delete communicator;
74         delete converter;
75         return NULL;
76     }
77     return ambif;
78 }
79 AMBIF::AMBIF(AbstractRoutingEngine *engine,
80              std::map<std::string, std::string> config) :
81         AbstractSource(engine, config)
82 {
83 }
84
85 AMBIF::~AMBIF()
86 {
87     propertylist.clear();
88     vehicleinfoArray.clear();
89     pthread_mutex_destroy(&mutex);
90 }
91
92 void
93 AMBIF::getPropertyAsync(AsyncPropertyReply *reply)
94 {
95     reply->success = false;
96     DebugOut(10) << "AMBIF " << "Get Request property : " << reply->property
97             << std::endl;
98     lock();
99     AMBVehicleInfo *vehicleinfo = find(reply->property);
100     DebugOut(50) << "AMBIF " << "Find Data : " << reply->property << std::endl;
101     if (vehicleinfo != NULL) {
102         reply->value = vehicleinfo->value;
103         reply->success = true;
104         reply->completed(reply);
105     }
106     unLock();
107 }
108
109 AsyncPropertyReply *
110 AMBIF::setProperty(AsyncSetPropertyRequest request)
111 {
112     DebugOut(10) << "AMBIF" << "Set Request propety : " << request.property
113                << std::endl;
114     lock();
115     AMBVehicleInfo *vehicleinfo = find(request.property);
116     if (vehicleinfo == NULL) {
117         unLock();
118         return NULL;
119     }
120     AsyncPropertyReply *reply = new AsyncPropertyReply(request);
121     reply->success = true;
122     DebugOut(50) << "AMBIF" << "Update Value!" << std::endl;
123     delete vehicleinfo->value;
124     vehicleinfo->value = request.value->copy();
125     reply->value = vehicleinfo->value;
126     communicator->setMWVehicleInfo(vehicleinfo);
127     DebugOut(50) << "AMBIF setProperty " << "Set Value(" << request.property
128                << "," << reply->value->toString() << ")" << std::endl;
129     reply->completed(reply);
130     #if LATER1024
131     routingEngine->updateProperty(vehicleinfo->value, uuid());
132     #else
133     routingEngine->updateProperty(vehicleinfo->name, vehicleinfo->value, uuid());
134     #endif
135     unLock();
136     return reply;
137 }
138
139 PropertyList
140 AMBIF::supported()
141 {
142     return propertylist;
143 }
144
145 int
146 AMBIF::supportedOperations()
147 {
148     return Get | Set;
149 }
150
151 #if LATER1024
152 const string
153 #else
154 string
155 #endif
156 AMBIF::uuid()
157 {
158     return "f68f8b9a-fafb-4284-8ced-b45b5d720185";
159 }
160
161 void
162 AMBIF::propertyChanged(VehicleProperty::Property property,
163                        AbstractPropertyType *value, std::string uuid)
164 {
165     DebugOut(1) << "INFO CHG_VIC_INF Receive notification from Core. Property is " << property << ".\n";
166     AMBVehicleInfo *vehicleinfo = find(property);
167     lock();
168     if (vehicleinfo != NULL) {
169         delete vehicleinfo->value;
170         vehicleinfo->value = value->copy();
171     }
172     unLock();
173 }
174
175 void
176 AMBIF::setConfiguratin(std::map<std::string, std::string> config)
177 {
178 }
179
180 bool
181 AMBIF::initialize(VICCommunicator *comm, AMBConfig *conf)
182 {
183     DebugOut(50) << "AMBIF Initialize\n";
184     communicator = comm;
185     mutex = PTHREAD_MUTEX_INITIALIZER;
186
187     vector<VehicleInfoDefine> table;
188     table = conf->getVehicleInfoConfig();
189     for (auto itr = table.begin(); itr != table.end(); itr++) {
190         for (auto itr2 = (*itr).status.begin(); itr2 != (*itr).status.end();
191              itr2++) {
192             AMBVehicleInfo vi;
193             vi.isCustom = false;
194             vi.name = (*itr2).ambPropertyName;
195             vi.value = VehicleProperty::getPropertyTypeForPropertyNameValue(
196                     vi.name, (*itr2).defaultvalue);
197             if (vi.value == nullptr) {
198                 if (!registVehicleInfo(vi.name, (*itr2).type,
199                                        (*itr2).defaultvalue)) {
200                     DebugOut(50) << "AMBIF Initialize Couldn't regist property["
201                                << vi.name << "]\n";
202                     continue;
203                 }
204                 vi.value = VehicleProperty::getPropertyTypeForPropertyNameValue(
205                         vi.name, (*itr2).defaultvalue);
206                 vi.isCustom = true;
207             }
208             vi.zone = (*itr2).zone;
209             vehicleinfoArray.push_back(vi);
210             propertylist.push_back(vi.name);
211             DebugOut(50) << "AMBIF Initialize regist propertyname = " << vi.name
212                        << "\n";
213         }
214     }
215     routingEngine->updateSupported(supported(), PropertyList(), this);
216     DebugOut(1) << "INFO CHG_VIC_INF The number of AMB vehicle info is " << vehicleinfoArray.size() << ".\n";
217     return true;
218 }
219
220 AMBVehicleInfo *
221 AMBIF::getPropertyRequest(std::string propertyname)
222 {
223     DebugOut(50) << "AMBIF getPropertyRequest(" << propertyname << ")\n";
224     AsyncPropertyRequest request;
225     request.property = propertyname;
226     request.completed = [](AsyncPropertyReply *reply) {
227         if (reply->success) {
228             DebugOut(50) << "AMBIF getPropertyRequest completed success!!.\n";
229         }
230         else {
231             DebugOut(50) << "AMBIF getPropertyRequest completed false!!.\n";
232         }
233     };
234
235     AsyncPropertyReply *reply = routingEngine->getPropertyAsync(request);
236     lock();
237     AMBVehicleInfo *vehicleinfo = find(propertyname);
238     if (vehicleinfo == NULL) {
239         delete reply;
240         unLock();
241         return NULL;
242     }
243     if (vehicleinfo->value != reply->value && reply->success) {
244         delete vehicleinfo->value;
245         vehicleinfo->value = reply->value->copy();
246     }
247     delete reply;
248     unLock();
249     DebugOut(50) << "AMBIF getPropertyRequest after call "
250                << vehicleinfo->value->toString() << std::endl;
251     return vehicleinfo;
252 }
253
254 void
255 AMBIF::setPropertyRequest(AMBVehicleInfo *vehicleinfo)
256 {
257     AsyncSetPropertyRequest request;
258     request.property = vehicleinfo->name;
259     request.value = vehicleinfo->value;
260     request.completed =
261             [](AsyncPropertyReply *reply) {
262                 if (reply->success) {
263                     DebugOut(50)<<"AMBIF" << reply->property << ":" << reply->value->toString() << std::endl;
264                 }
265                 else {
266                     DebugOut(50)<<"AMBIF" << reply->property << " isn't registered." << std::endl;
267                 }
268             };
269     AsyncPropertyReply *reply = routingEngine->setProperty(request);
270     if (reply != NULL) {
271         delete reply;
272     }
273 }
274
275 void
276 AMBIF::updateProperty(AMBVehicleInfo *vehicleinfo)
277 {
278     if (vehicleinfo->name == VehicleProperty::VehicleSpeed) {
279         static uint16_t prevspd = -1;
280         static const uint16_t unusablespd = -1;
281         uint16_t spd = vehicleinfo->value->value<uint16_t>();
282         if ((prevspd == unusablespd && spd > 0) || (prevspd == 0 && spd > 0)) {
283             DebugOut(3) << "PERF CHG_VIC_INF VIC-Plugin notify Code of update " 
284                         << vehicleinfo->name 
285                         << ". VehicleSpeed is 1km/h or more.\n";
286         }
287         else if ((prevspd == unusablespd && spd == 0) || 
288                  (prevspd > 0 && spd == 0)) {
289             DebugOut(3) << "PERF CHG_VIC_INF VIC-Plugin notify Code of update " 
290                         << vehicleinfo->name << ". VehicleSpeed is 0km/h.\n";
291         }
292         prevspd = spd;
293     }
294     #if LATER1024
295     routingEngine->updateProperty(vehicleinfo->value, uuid());
296     #else
297     routingEngine->updateProperty(vehicleinfo->name, vehicleinfo->value, uuid());
298     #endif
299     AMBVehicleInfo *ambvehicleinfo = find(vehicleinfo->name);
300     lock();
301     if (ambvehicleinfo != NULL) {
302         delete ambvehicleinfo->value;
303         ambvehicleinfo->value = vehicleinfo->value->copy();
304     }
305     unLock();
306 }
307
308 void
309 AMBIF::lock()
310 {
311     pthread_mutex_lock(&mutex);
312 }
313
314 void
315 AMBIF::unLock()
316 {
317     pthread_mutex_unlock(&mutex);
318 }
319
320 void
321 AMBIF::requestUpdate(AMBVehicleInfo *vehicleinfo)
322 {
323     DebugOut(50) << "AMBIF requestUpdate request property name is "
324                << vehicleinfo->name << "\n";
325     if (find(vehicleinfo->name) != NULL) {
326         vehicleinfo->value->zone = vehicleinfo->zone;
327         vehicleinfo->value->priority = AbstractPropertyType::Instant;
328         DebugOut(50) << "AMBIF requestUpdate request property name is "
329                    << vehicleinfo->name << ", zone is " << vehicleinfo->zone << "\n";
330         updateProperty(vehicleinfo);
331     }
332     else {
333         setPropertyRequest(vehicleinfo);
334     }
335 }
336
337 bool
338 AMBIF::registVehicleInfo(std::string propertyName, DataType type, string value)
339 {
340     DebugOut(50) << "AMBIF registVehicleInfo(" << propertyName << ")\n";
341     VehicleProperty::PropertyTypeFactoryCallback factory;
342     switch (type) {
343     case INT:
344     {
345         factory = [value, propertyName]() {
346             return new BasicPropertyType<int>(propertyName, value);
347         };
348         break;
349     }
350     case DOUBLE:
351     {
352         factory = [value, propertyName]() {
353             return new BasicPropertyType<double>(propertyName, value);
354         };
355         break;
356     }
357     case CHAR:
358     {
359         factory = [value, propertyName]() {
360             return new BasicPropertyType<char>(propertyName, value);
361         };
362         break;
363     }
364     case INT16:
365     {
366         factory = [value, propertyName]() {
367             return new BasicPropertyType<int16_t>(propertyName, value);
368         };
369         break;
370     }
371     case UINT16:
372     {
373         factory = [value, propertyName]() {
374             return new BasicPropertyType<uint16_t>(propertyName, value);
375         };
376         break;
377     }
378     case UINT32:
379     {
380         factory = [value, propertyName]() {
381             return new BasicPropertyType<uint32_t>(propertyName, value);
382         };
383         break;
384     }
385     case INT64:
386     {
387         factory = [value, propertyName]() {
388             return new BasicPropertyType<int64_t>(propertyName, value);
389         };
390         break;
391     }
392     case UINT64:
393     {
394         factory = [value, propertyName]() {
395             return new BasicPropertyType<uint64_t>(propertyName, value);
396         };
397         break;
398     }
399     case BOOL:
400     {
401         factory = [value, propertyName]() {
402             return new BasicPropertyType<bool>(propertyName, value);
403         };
404         break;
405     }
406     default:
407     {
408         return false;
409     }
410     }
411     return VehicleProperty::registerProperty(propertyName, factory);
412 }
413
414 AMBVehicleInfo *
415 AMBIF::find(std::string propertyName)
416 {
417     AMBVehicleInfo vi;
418     vi.name = propertyName;
419     std::vector<AMBVehicleInfo>::iterator itr;
420     if ((itr = std::find(vehicleinfoArray.begin(), vehicleinfoArray.end(), vi)) 
421         != vehicleinfoArray.end()) {
422         return &(*itr);
423     }
424     return NULL;
425 }
426
427 #if LATER1024
428 PropertyInfo AMBIF::getPropertyInfo(const VehicleProperty::Property & property) {
429     if (propertyInfoMap.find(property) != propertyInfoMap.end()) {
430         return propertyInfoMap[property];
431     }
432     Zone::ZoneList zones;
433     AMBVehicleInfo vi;
434     vi.name = property;
435     std::vector<AMBVehicleInfo>::iterator itr, itr_idx, itr_end;
436     itr_idx = vehicleinfoArray.begin();
437     itr_end = vehicleinfoArray.end();
438     while ((itr = std::find(itr_idx, itr_end, vi)) != itr_end) {
439         zones.push_back((*itr).zone);
440         itr_idx = (++itr);
441     }
442     if (zones.empty()) {
443         return PropertyInfo::invalid();
444     }
445     else {
446         PropertyInfo info(0, zones);
447         propertyInfoMap[vi.name] = info;
448         return propertyInfoMap[vi.name];
449     }
450 }
451 #endif