Added virtual destructors to CANSocketBCM and CANSocketRaw
[profile/ivi/automotive-message-broker.git] / xwalk / vehicle.cc
1 // Copyright (c) 2014 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "vehicle.h"
6
7 #include <abstractpropertytype.h>
8 #include <debugout.h>
9 #include <gio/gio.h>
10 #include <glib.h>
11 #include <listplusplus.h>
12 #include <picojson.h>
13 #include <superptr.hpp>
14
15 #include <algorithm>
16 #include <map>
17 #include <memory>
18
19 #include "common/extension.h"
20
21 common::Instance* Vehicle::CallbackInfo::instance = nullptr;
22
23 namespace {
24 const char* amb_service = "org.automotive.message.broker";
25 const char* prop_iface = "org.freedesktop.DBus.Properties";
26
27 const char* vehicle_error_permission_denied = "permission_denied";
28 const char* vehicle_error_invalid_operation = "invalid_operation";
29 const char* vehicle_error_timeout = "timeout";
30 const char* vehicle_error_invalid_zone = "invalid_zone";
31 const char* vehicle_error_unknown = "unknown";
32
33 picojson::value::array AmbZoneToW3C(const std::vector<int>& amb_zones);
34 picojson::value::array AmbZoneToW3C(int amb_zone);
35
36 template<typename T> unique_ptr<T> make_unique(T* t) {
37         return unique_ptr<T>(t);
38 }
39
40 void PostReply(Vehicle::CallbackInfo* cb_obj, picojson::value object) {
41         DebugOut() << "Posting reply" << endl;
42         picojson::object msg;
43
44         msg["method"] = picojson::value(cb_obj->method);
45         msg["asyncCallId"] = picojson::value(cb_obj->callback_id);
46         msg["value"] = object;
47
48         std::string message = picojson::value(msg).serialize();
49
50         DebugOut() << "Reply message: " << message << endl;
51
52         cb_obj->instance->PostMessage(message.c_str());
53 }
54
55 void PostError(Vehicle::CallbackInfo* cb_obj, const std::string& error) {
56         picojson::object msg;
57         msg["method"] = picojson::value(cb_obj->method);
58         msg["error"] = picojson::value(true);
59         msg["value"] = picojson::value(error);
60         msg["asyncCallId"] =
61                         picojson::value(static_cast<double>(cb_obj->callback_id));
62
63         std::string message = picojson::value(msg).serialize();
64
65         DebugOut() << "Error Reply message: " << message << endl;
66
67         cb_obj->instance->PostMessage(message.c_str());
68 }
69
70 picojson::value GetBasic(GVariant* value) {
71         std::string type = g_variant_get_type_string(value);
72         picojson::value v;
73
74         if (type == "i") {
75                 int tempVal = GVS<int>::value(value);
76                 v = picojson::value(static_cast<double>(tempVal));
77         } else if (type == "d") {
78                 v = picojson::value(GVS<double>::value(value));
79         } else if (type == "q") {
80                 v = picojson::value(static_cast<double>(GVS<uint16_t>::value(value)));
81         } else if (type == "n") {
82                 v = picojson::value(static_cast<double>(GVS<int16_t>::value(value)));
83         } else if (type == "y") {
84                 v = picojson::value(static_cast<double>(GVS<char>::value(value)));
85         } else if (type == "u") {
86                 v = picojson::value(static_cast<double>(GVS<uint32_t>::value(value)));
87         } else if (type == "x") {
88                 v = picojson::value(static_cast<double>(GVS<int64_t>::value(value)));
89         } else if (type == "t") {
90                 v = picojson::value(static_cast<double>(GVS<uint64_t>::value(value)));
91         } else if (type == "b") {
92                 v = picojson::value(GVS<bool>::value(value));
93         } else if (type == "s") {
94                 v = picojson::value(g_variant_get_string(value, nullptr));
95         } else {
96                 DebugOut(DebugOut::Error) << "Unsupported type: " << type << endl;
97         }
98
99         return v;
100 }
101
102 GVariant* GetBasic(picojson::value value, const std::string& type) {
103         GVariant* v = nullptr;
104
105         if (type == "i") {
106                 v = g_variant_new(type.c_str(), (int32_t)value.get<double>());
107         } else if (type == "d") {
108                 v = g_variant_new(type.c_str(), value.get<double>());
109         } else if (type == "q") {
110                 v = g_variant_new(type.c_str(), (uint16_t)value.get<double>());
111         } else if (type == "n") {
112                 v = g_variant_new(type.c_str(), (int16_t)value.get<double>());
113         } else if (type == "u") {
114                 v = g_variant_new(type.c_str(), (uint32_t)value.get<double>());
115         } else if (type == "x") {
116                 v = g_variant_new(type.c_str(), (int64_t)value.get<double>());
117         } else if (type == "t") {
118                 v = g_variant_new(type.c_str(), (uint64_t)value.get<double>());
119         } else if (type == "b") {
120                 v = g_variant_new(type.c_str(), value.get<bool>());
121         } else if (type == "s") {
122                 v = g_variant_new(type.c_str(), value.get<std::string>().c_str());
123         } else {
124                 DebugOut(DebugOut::Error) << "Unsupported type: " << type << endl;
125         }
126
127         return v;
128 }
129
130 void AsyncGetCallback(GObject* source, GAsyncResult* res, gpointer user_data) {
131         debugOut("GetAll() method call completed");
132
133         Vehicle::CallbackInfo *cb_obj =
134                         static_cast<Vehicle::CallbackInfo*>(user_data);
135
136         auto cb_obj_ptr = make_unique(cb_obj);
137
138         if (!cb_obj_ptr) {
139                 debugOut("invalid cb object");
140                 return;
141         }
142
143         GError* error = nullptr;
144
145         auto property_map = amb::make_super(
146                                 g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error));
147
148         auto error_ptr = amb::make_super(error);
149
150         if (error_ptr) {
151                 DebugOut() << "failed to call GetAll on interface: "
152                                    << error_ptr->message << endl;
153                 PostError(cb_obj_ptr.get(), "unknown");
154                 return;
155         }
156
157         GVariantIter* iter;
158         gchar* key;
159         GVariant* value;
160
161         g_variant_get(property_map.get(), "(a{sv})", &iter);
162
163         auto iter_ptr = amb::make_super(iter);
164
165         picojson::value::object object;
166
167         while (g_variant_iter_next(iter_ptr.get(), "{sv}", &key, &value)) {
168                 auto key_ptr = amb::make_super(key);
169                 auto value_ptr = amb::make_super(value);
170
171                 std::string temp_key = key_ptr.get();
172
173                 std::transform(temp_key.begin(), temp_key.begin() + 1,
174                                            temp_key.begin(), ::tolower);
175
176                 object[temp_key] = GetBasic(value_ptr.get());
177
178                 if (temp_key == "zone") {
179                         object[temp_key] =
180                                         picojson::value(AmbZoneToW3C(object[temp_key].get<double>()));
181                 }
182         }
183
184         PostReply(cb_obj_ptr.get(), picojson::value(object));
185 }
186
187 picojson::value::array AmbZoneToW3C(int amb_zone) {
188         picojson::value::array z;
189
190         if (amb_zone & Zone::Left) {
191                 z.push_back(picojson::value("left"));
192         }
193         if (amb_zone & Zone::Right) {
194                 z.push_back(picojson::value("right"));
195         }
196         if (amb_zone & Zone::Front) {
197                 z.push_back(picojson::value("front"));
198         }
199         if (amb_zone & Zone::Middle) {
200                 z.push_back(picojson::value("middle"));
201         }
202         if (amb_zone & Zone::Center) {
203                 z.push_back(picojson::value("center"));
204         }
205         if (amb_zone & Zone::Rear) {
206                 z.push_back(picojson::value("rear"));
207         }
208
209         return z;
210 }
211
212 picojson::value::array AmbZoneToW3C(const std::vector<int>& amb_zones) {
213         picojson::value::array zones;
214
215         for (auto i : amb_zones) {
216                 zones.push_back(picojson::value(AmbZoneToW3C(i)));
217         }
218
219         return zones;
220 }
221
222 static void SignalCallback(GDBusConnection* connection,
223                                                    const gchar*,
224                                                    const gchar* object_path,
225                                                    const gchar*,
226                                                    const gchar*,
227                                                    GVariant* parameters,
228                                                    gpointer user_data) {
229         DebugOut() << "Got signal" << endl;
230         std::vector<ObjectZone*> amb_objects_ =
231                         *(static_cast<std::vector<ObjectZone*>*>(user_data));
232
233         GVariant* value_array;
234         GVariant* iface_name;
235         GVariant* invalidated;
236
237         g_variant_get(parameters,
238                                   "(&s@a{sv}^a&s)",
239                                   &iface_name,
240                                   &value_array,
241                                   &invalidated);
242
243         GVariantIter iter;
244
245         g_variant_iter_init(&iter, value_array);
246
247         ObjectZone* object = nullptr;
248
249         for (auto i : amb_objects_) {
250                 if (i->object_path == object_path) {
251                         object = i;
252                 }
253         }
254
255         if (!object) {
256                 DebugOut(DebugOut::Error) << "received signal for which "
257                                                                   << "we have no corresponding amb object" << endl;
258                 return;
259         }
260
261         char* key;
262         GVariant* value;
263
264         while (g_variant_iter_next(&iter, "{sv}", &key, &value)) {
265                 auto key_ptr = amb::make_super(key);
266                 auto value_ptr = amb::make_super(value);
267
268                 std::string tempkey = key_ptr.get();
269
270                 std::transform(tempkey.begin(), tempkey.begin() + 1, tempkey.begin(),
271                                            ::tolower);
272
273                 object->value[tempkey] = GetBasic(value_ptr.get());
274
275                 if (tempkey == "zone") {
276                         object->value[tempkey] =
277                                         picojson::value(AmbZoneToW3C(object->value[tempkey].get<double>()));
278                 }
279         }
280
281         object->value["interfaceName"] = picojson::value(object->name);
282
283         Vehicle::CallbackInfo call;
284         call.method = "subscribe";
285         call.callback_id = -1;
286
287         PostReply(&call, picojson::value(object->value));
288 }
289
290 }  // namespace
291
292 Vehicle::Vehicle(common::Instance* instance)
293         : main_loop_(g_main_loop_new(0, FALSE)),
294           thread_(Vehicle::SetupMainloop, this),
295           instance_(instance),
296           manager_proxy_(nullptr){
297         CallbackInfo::instance = instance_;
298         thread_.detach();
299
300         GError* error = nullptr;
301
302         dbus_connection_ = amb::make_super(g_bus_get_sync(G_BUS_TYPE_SYSTEM,
303                                                                                                           nullptr,
304                                                                                                           &error));
305
306         auto errorPtr = amb::make_super(error);
307         if (errorPtr) {
308                 DebugOut(DebugOut::Error) << "getting bus: "
309                                    << errorPtr->message << std::endl;
310         }
311
312         GError* error_manager = nullptr;
313         manager_proxy_ = amb::make_super(g_dbus_proxy_new_sync(dbus_connection_.get(),
314                                                                                                                    G_DBUS_PROXY_FLAGS_NONE, NULL,
315                                                                                                                    amb_service,
316                                                                                                                    "/",
317                                                                                                                    "org.automotive.Manager",
318                                                                                                                    NULL,
319                                                                                                                    &error));
320
321         auto error_ptr = amb::make_super(error_manager);
322
323         if (error_ptr) {
324                 DebugOut(DebugOut::Error) << "calling GetAutomotiveManager: "
325                                    << error_ptr->message << endl;
326         }
327
328
329         GError* list_error = nullptr;
330         auto supported_list_variant = amb::make_super(
331                                 g_dbus_proxy_call_sync(manager_proxy_.get(),
332                                                                            "List",
333                                                                            nullptr,
334                                                                            G_DBUS_CALL_FLAGS_NONE,
335                                                                            -1, NULL, &list_error));
336
337         auto list_error_ptr = amb::make_super(list_error);
338
339         if (list_error_ptr) {
340                 DebugOut(DebugOut::Error) << "error calling List: "
341                                    << error_ptr->message << endl;
342                 return;
343         }
344
345         GVariantIter iter;
346         g_variant_iter_init(&iter, supported_list_variant.get());
347         picojson::array list;
348
349         gchar* propertyName = nullptr;
350
351         while(g_variant_iter_next(&iter,"s", &propertyName))
352         {
353                 auto propertyNamePtr = amb::make_super(propertyName);
354
355                 std::string p = propertyNamePtr.get();
356
357                 std::transform(p.begin(), p.begin()+1, p.begin(), ::tolower);
358                 list.push_back(picojson::value(p));
359         }
360
361         picojson::object obj;
362         obj["method"] = picojson::value("vehicleSupportedAttributes");
363         obj["value"] = picojson::value(list);
364
365         instance->PostMessage(picojson::value(obj).serialize().c_str());
366 }
367
368 Vehicle::~Vehicle() {
369         g_main_loop_quit(main_loop_);
370         g_main_loop_unref(main_loop_);
371
372         for (auto i : amb_objects_) {
373                 delete i;
374         }
375 }
376
377 void Vehicle::Get(const std::string& property, Zone::Type zone, double ret_id) {
378         CallbackInfo* data = new CallbackInfo;
379
380         data->callback_id = ret_id;
381         data->method = "get";
382         data->instance = instance_;
383
384
385         std::string find_error;
386         std::string obj_pstr = FindProperty(property, zone, find_error);
387
388         if (obj_pstr.empty()) {
389                 debugOut("could not find property " + property);
390                 PostError(data, find_error);
391                 return;
392         }
393
394         GError* error = nullptr;
395
396         auto properties_proxy = amb::make_super(
397                                 g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
398                                                                                           G_DBUS_PROXY_FLAGS_NONE, NULL,
399                                                                                           amb_service,
400                                                                                           obj_pstr.c_str(),
401                                                                                           prop_iface,
402                                                                                           NULL,
403                                                                                           &error));
404
405         auto error_ptr = amb::make_super(error);
406
407         if (error_ptr) {
408                 DebugOut(DebugOut::Error) << "failed to get properties proxy: " << error->message << endl;
409                 return;
410         }
411
412         std::string interfaceName = "org.automotive." + property;
413
414         g_dbus_proxy_call(properties_proxy.get(),
415                                           "GetAll",
416                                           g_variant_new("(s)", interfaceName.c_str()),
417                                           G_DBUS_CALL_FLAGS_NONE, -1, NULL,
418                                           AsyncGetCallback, data);
419 }
420
421 void Vehicle::GetZones(const std::string& object_name, double ret_id) {
422         GError* error(nullptr);
423
424         auto zones_variant = amb::make_super(
425                                 g_dbus_proxy_call_sync(manager_proxy_.get(),
426                                                                            "ZonesForObjectName",
427                                                                            g_variant_new("(s)",
428                                                                                                          object_name.c_str()),
429                                                                            G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error));
430
431         auto error_ptr = amb::make_super(error);
432
433         if (error_ptr) {
434                 DebugOut() << "error calling ZonesForObjectName: "
435                                    << error_ptr->message << endl;
436                 return;
437         }
438
439         if (!zones_variant) {
440                 DebugOut() << "Invalid response from ZonesForObjectName " << endl;
441                 return;
442         }
443
444         GVariantIter* iter(nullptr);
445
446         g_variant_get(zones_variant.get(), "(ai)", &iter);
447
448         if (!iter) {
449                 DebugOut() << "No zones for object " << object_name << endl;
450                 return;
451         }
452
453         auto iter_ptr = amb::make_super(iter);
454
455         std::vector<int> zones_array;
456
457         GVariant* value(nullptr);
458
459         while ((value = g_variant_iter_next_value(iter_ptr.get()))) {
460                 auto value_ptr = amb::make_super(value);
461                 int v = 0;
462
463                 g_variant_get(value_ptr.get(), "i", &v);
464                 zones_array.push_back(v);
465         }
466
467         picojson::value::array w3c_zones = AmbZoneToW3C(zones_array);
468
469         CallbackInfo* data = new CallbackInfo;
470
471         data->callback_id = ret_id;
472         data->method = "zones";
473         data->instance = instance_;
474
475         PostReply(data, picojson::value(w3c_zones));
476 }
477
478 std::string Vehicle::FindProperty(const std::string& object_name, int zone, std::string& error_str) {
479         GError* error(nullptr);
480
481         auto object_path_variant = amb::make_super(
482                                 g_dbus_proxy_call_sync(manager_proxy_.get(),
483                                                                            "FindObjectForZone",
484                                                                            g_variant_new("(si)",
485                                                                                                          object_name.c_str(),
486                                                                                                          zone),
487                                                                            G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error));
488
489         auto error_ptr = amb::make_super(error);
490
491         if (error_ptr) {
492                 DebugOut(DebugOut::Error) << "error calling FindObjectForZone: "
493                                    << error_ptr->message << endl;
494
495                 DebugOut() << "Could not find object in zone: " << zone << endl;
496                 error_str = vehicle_error_invalid_operation;
497                 return "";
498         }
499
500         if (!object_path_variant) {
501                 DebugOut() << "Could not find object in zone: "  << zone << endl;
502                 error_str = vehicle_error_invalid_operation;
503                 return "";
504         }
505
506         gchar* obj_path = nullptr;
507         g_variant_get(object_path_variant.get(), "(o)", &obj_path);
508
509         auto obj_path_ptr = amb::make_super(obj_path);
510
511         DebugOut() << "FindObjectForZone() returned object path: "
512                            << obj_path_ptr.get() << endl;
513
514         return obj_path;
515 }
516
517 void Vehicle::SetupMainloop(void* data) {
518         Vehicle* self = reinterpret_cast<Vehicle*>(data);
519         GMainContext* ctx = g_main_context_default();
520
521         g_main_context_push_thread_default(ctx);
522         g_main_loop_run(self->main_loop_);
523 }
524
525
526 void Vehicle::Subscribe(const std::string& object_name, Zone::Type zone) {
527         std::string find_error;
528         std::string object_path = FindProperty(object_name, zone, find_error);
529
530         if (object_path.empty()) {
531                 DebugOut() << "Error FindProperty failed for " << object_name;
532                 return;
533         }
534
535         bool already_subscribed = false;
536
537         for (auto i : amb_objects_) {
538                 if (i->object_path == object_path) {
539                         already_subscribed = true;
540                         break;
541                 }
542         }
543
544         if (!already_subscribed) {
545                 GError* proxy_error = nullptr;
546
547                 auto properties_proxy =
548                                 amb::make_super(g_dbus_proxy_new_sync(dbus_connection_.get(),
549                                                                                                           G_DBUS_PROXY_FLAGS_NONE,
550                                                                                                           NULL,
551                                                                                                           amb_service,
552                                                                                                           object_path.c_str(),
553                                                                                                           prop_iface,
554                                                                                                           NULL,
555                                                                                                           &proxy_error));
556
557                 auto proxy_error_ptr = amb::make_super(proxy_error);
558
559                 if (proxy_error_ptr) {
560                         DebugOut() << "error creating properties proxy: "
561                                            << proxy_error_ptr->message << endl;
562                 }
563
564                 std::string interface_name = "org.automotive." + object_name;
565
566                 GError* get_all_error = nullptr;
567
568                 GVariant* property_map =
569                                 g_dbus_proxy_call_sync(properties_proxy.get(),
570                                                                            "GetAll",
571                                                                            g_variant_new("(s)", interface_name.c_str()),
572                                                                            G_DBUS_CALL_FLAGS_NONE, -1, NULL,
573                                                                            &get_all_error);
574
575                 auto get_all_error_ptr = amb::make_super(get_all_error);
576
577                 if (get_all_error_ptr) {
578                         DebugOut(DebugOut::Error) << "failed to call GetAll on interface "
579                                                                           << interface_name << " "
580                                                                           << get_all_error_ptr->message << endl;
581                         return;
582                 }
583
584                 GVariantIter* iter;
585
586                 g_variant_get(property_map, "(a{sv})", &iter);
587
588                 auto iter_ptr = amb::make_super(iter);
589
590                 char* key;
591                 GVariant* value;
592
593                 ObjectZone* object = new ObjectZone(object_name, zone, object_path);
594
595                 while (g_variant_iter_next(iter_ptr.get(), "{sv}", &key, &value)) {
596                         auto key_ptr = amb::make_super(key);
597                         auto value_ptr = amb::make_super(value);
598
599                         std::string tempkey = key_ptr.get();
600
601                         std::transform(tempkey.begin(), tempkey.begin() + 1, tempkey.begin(),
602                                                    ::tolower);
603
604                         object->value[tempkey] = GetBasic(value_ptr.get());
605                 }
606
607                 object->handle =
608                                 g_dbus_connection_signal_subscribe(dbus_connection_.get(),
609                                                                                                    amb_service,
610                                                                                                    prop_iface,
611                                                                                                    "PropertiesChanged",
612                                                                                                    object_path.c_str(), NULL,
613                                                                                                    G_DBUS_SIGNAL_FLAGS_NONE,
614                                                                                                    SignalCallback, &amb_objects_,
615                                                                                                    NULL);
616
617                 amb_objects_.push_back(object);
618         } else {
619                 DebugOut() << "Already subscribed to " << object_name << endl;
620         }
621 }
622
623
624 void Vehicle::Unsubscribe(const std::string& property, Zone::Type zone) {
625         std::vector<ObjectZone*> to_clean;
626
627         for (auto obj : amb_objects_) {
628                 if (obj->name == property && obj->zone == zone) {
629                         g_dbus_connection_signal_unsubscribe(dbus_connection_.get(),
630                                                                                                  obj->handle);
631                         to_clean.push_back(obj);
632                 }
633         }
634
635         for (auto obj : to_clean) {
636                 removeOne(&amb_objects_, obj);
637                 delete obj;
638         }
639 }
640
641
642 void Vehicle::Set(const std::string &object_name, picojson::object value,
643                                   Zone::Type zone, double ret_id)
644 {
645         std::string find_error;
646         std::string object_path = FindProperty(object_name, zone, find_error);
647
648         Vehicle::CallbackInfo callback;
649         callback.callback_id = ret_id;
650         callback.method = "set";
651         callback.instance = instance_;
652
653         if (object_path.empty() || !find_error.empty()) {
654                 DebugOut(DebugOut::Error) << "Object not found.  Check object Name and zone."
655                                                                   << object_name << std::endl;
656                 PostError(&callback, find_error);
657                 return;
658         }
659
660         GError* proxy_error = nullptr;
661
662         auto properties_proxy =
663                         amb::make_super(g_dbus_proxy_new_sync(dbus_connection_.get(),
664                                                                                                   G_DBUS_PROXY_FLAGS_NONE,
665                                                                                                   NULL,
666                                                                                                   amb_service,
667                                                                                                   object_path.c_str(),
668                                                                                                   prop_iface,
669                                                                                                   NULL,
670                                                                                                   &proxy_error));
671
672         auto proxy_error_ptr = amb::make_super(proxy_error);
673
674         if (proxy_error_ptr) {
675                 DebugOut(DebugOut::Error) << "Error creating property proxy for " << object_path << std::endl;
676                 PostError(&callback, vehicle_error_unknown);
677                 return;
678         }
679
680         std::string interface_name = "org.automotive." + object_name;
681
682         for (auto itr : value) {
683                 GError* err = nullptr;
684                 std::string attribute = itr.first;
685
686                 std::transform(attribute.begin(), attribute.begin()+1, attribute.begin(), ::toupper);
687
688                 auto var_value =
689                                 amb::make_super(g_dbus_proxy_call_sync(properties_proxy.get(),
690                                                                                                            "Get",
691                                                                                                            g_variant_new("(ss)",
692                                                                                                                                          interface_name.c_str(),
693                                                                                                                                          attribute.c_str()),
694                                                                                                            G_DBUS_CALL_FLAGS_NONE,
695                                                                                                            -1,
696                                                                                                            NULL,
697                                                                                                            &err));
698                 auto err_ptr = amb::make_super(err);
699                 if (err_ptr || !var_value) {
700                         DebugOut(DebugOut::Error) << "Error getting initial property signature type: " <<
701                                                                                  err_ptr->message << endl;
702                         PostError(&callback, vehicle_error_unknown);
703                         return;
704                 }
705
706                 GVariant* get_value = nullptr;
707                 g_variant_get(var_value.get(), "(v)", &get_value);
708
709                 auto get_value_ptr = amb::make_super(get_value);
710
711                 if (!get_value_ptr) {
712                         DebugOut(DebugOut::Error) << "Error getting variant value." << endl;
713                         PostError(&callback, vehicle_error_unknown);
714                         return;
715                 }
716
717                 GVariant* v = GetBasic(itr.second, g_variant_get_type_string(get_value_ptr.get()));
718
719                 if (!v) {
720                         DebugOut(DebugOut::Error) << "Error converting value to GVariant" << endl;
721                         PostError(&callback, vehicle_error_unknown);
722                         return;
723                 }
724
725                 GError* set_error = nullptr;
726
727                 DebugOut() << "Trying to set " << attribute << " to " << itr.second.serialize() << endl;
728
729                 g_dbus_proxy_call_sync(properties_proxy.get(), "Set",
730                                                            g_variant_new("(ssv)",
731                                                                                          interface_name.c_str(),
732                                                                                          attribute.c_str(),
733                                                                                          v),
734                                                            G_DBUS_CALL_FLAGS_NONE,
735                                                            -1, NULL, &set_error);
736
737                 auto set_error_ptr = amb::make_super(set_error);
738
739                 if (set_error_ptr) {
740                         DebugOut(DebugOut::Error) << "error setting property:" << set_error_ptr->message << endl;
741
742                         if(set_error_ptr->code == G_IO_ERROR_PERMISSION_DENIED
743                                         || std::string(g_dbus_error_get_remote_error(set_error_ptr.get())) == "org.freedesktop.DBus.Error.AccessDenied")
744                         {
745                                 DebugOut(DebugOut::Error) << "permission denied" << endl;
746                                 PostError(&callback, vehicle_error_permission_denied);
747                                 return;
748                         }
749                         PostError(&callback, vehicle_error_unknown);
750                         return;
751                 }
752         }
753
754         PostReply(&callback, picojson::value());
755 }
756
757 void Vehicle::Supported(const string& object_name, double ret_id)
758 {
759         Vehicle::CallbackInfo callback;
760         callback.callback_id = ret_id;
761         callback.method = "supported";
762         callback.instance = instance_;
763
764         GError* error(nullptr);
765
766         auto object_path_variant = amb::make_super(
767                                 g_dbus_proxy_call_sync(manager_proxy_.get(),
768                                                                            "FindObject",
769                                                                            g_variant_new("(s)", object_name.c_str()),
770                                                                            G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error));
771
772         auto error_ptr = amb::make_super(error);
773
774         if (error_ptr) {
775                 DebugOut(DebugOut::Error) << "error calling FindObjectForZone: "
776                                    << error_ptr->message << endl;
777
778                 DebugOut() << "Could not find object for: "  << object_name << endl;
779                 PostReply(&callback, picojson::value(false));
780                 return;
781         }
782
783         if (!object_path_variant) {
784                 DebugOut() << "Could not find object for: "  << object_name << endl;
785                 PostReply(&callback, picojson::value(false));
786                 return;
787         }
788
789         PostReply(&callback, picojson::value(true));
790 }
791
792 bool Vehicle::AvailableForRetrieval(const string &objectName, const string &attName)
793 {
794         GError* error = nullptr;
795
796         auto supportedVariant = amb::make_super(
797                                 g_dbus_proxy_call_sync(manager_proxy_.get(),
798                                                                            "SupportsProperty",
799                                                                            g_variant_new("(ss)", objectName.c_str(), attName.c_str()),
800                                                                            G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error));
801
802         auto error_ptr = amb::make_super(error);
803
804         if (error_ptr) {
805                 DebugOut(DebugOut::Error) << "error calling SupportsProperty: "
806                                    << error_ptr->message << endl;
807
808                 DebugOut() << "Could not find object for: "  << objectName << endl;
809                 return false;
810         }
811
812         bool supported = false;
813         g_variant_get(supportedVariant.get(), "(b)", &supported);
814
815         return supported;
816 }