automotive-message-broker  0.14.803
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
dbussignaller.h
1 #ifndef _DBUSSIGNALLER_H_
2 #define _DBUSSIGNALLER_H_
3 
4 #include <gio/gio.h>
5 
6 #include <vector>
7 #include <string>
8 #include <memory>
9 #include <unordered_map>
10 
11 #include "debugout.h"
12 #include "varianttype.h"
13 #include "superptr.hpp"
14 #include "listplusplus.h"
15 
17 {
18 public:
19  DBusSignal():connection(nullptr), property(nullptr){}
20  DBusSignal(GDBusConnection* conn, const std::string & objPath, const std::string & iface, const std::string & sigName, VariantType* var)
21  : connection(conn), objectPath(objPath), interface(iface), signalName(sigName), property(var)
22  {
23 
24  }
25 
26  ~DBusSignal()
27  {
28 
29  }
30 
31  bool operator == (const DBusSignal &other) const
32  {
33  return connection == other.connection &&
34  objectPath == other.objectPath &&
35  interface == other.interface &&
36  signalName == other.signalName &&
37  property == other.property;
38  }
39 
40  GDBusConnection* connection;
41  std::string objectPath;
42  std::string interface;
43  std::string signalName;
45 };
46 
48 {
49 public:
50 
51  static DBusSignaller* factory(int timeout)
52  {
53  if(!singleton)
54  return singleton = new DBusSignaller(timeout);
55  return singleton;
56  }
57 
58  void fireSignal(GDBusConnection* conn, const std::string & objPath, const std::string & iface,
59  const std::string & sigName, VariantType* prop)
60  {
61  DBusSignal * signal = new DBusSignal(conn, objPath, iface, sigName, prop);
62 
63  if(queue.find(objPath) != queue.end())
64  {
65  bool isFound = false;
66  for(auto i : queue[objPath])
67  {
68  if(*i == *signal)
69  {
70  isFound = true;
71  break;
72  }
73  }
74 
75  if(!isFound)
76  queue[objPath].push_back(signal);
77  }
78  else
79  {
80  queue[objPath].push_back(signal);
81  }
82  }
83 
84 private:
85 
86  DBusSignaller() { }
87 
88  DBusSignaller(int timeout)
89  {
90  g_timeout_add(timeout,[](gpointer userData)
91  {
92  std::unordered_map<std::string, std::vector<DBusSignal*>> *q = static_cast<std::unordered_map<std::string, std::vector<DBusSignal*>>*>(userData);
93  std::unordered_map<std::string, std::vector<DBusSignal*>> queue = *q;
94 
95  for(auto itr : queue)
96  {
97  std::string objectPath;
98  GDBusConnection* connection;
99  std::string interfaceName;
100  std::string signalName;
101 
102  std::unordered_map<std::string, GVariant*> variantMap;
103 
104  for(auto s : itr.second)
105  {
106  std::unique_ptr<DBusSignal> signal(s);
107  objectPath = signal->objectPath;
108  connection = signal->connection;
109  interfaceName = signal->interface;
110  signalName = signal->signalName;
111 
112  VariantType* property = signal->property;
113 
114  auto val = g_variant_ref(property->toVariant());
115  std::string sequenceName = property->name() + "Sequence";
116 
117  variantMap[property->name()] = val;
118  variantMap[sequenceName] = g_variant_new("i", property->sequence());
119  variantMap["Time"] = g_variant_new("d", property->timestamp());
120  variantMap["Zone"] = g_variant_new("i", property->zoneFilter());
121  }
122 
123  GVariantBuilder builder;
124  g_variant_builder_init(&builder, G_VARIANT_TYPE_DICTIONARY);
125 
126  for(auto sv : variantMap)
127  {
129  auto key = sv.first;
130  auto value = sv.second;
131 
132  g_variant_builder_add(&builder, "{sv}", key.c_str(), value);
133  }
134 
135  GError* error = nullptr;
136 
137  g_dbus_connection_emit_signal(connection, NULL, objectPath.c_str(),
138  "org.freedesktop.DBus.Properties",
139  signalName.c_str(),
140  g_variant_new("(sa{sv}as)", interfaceName.c_str(), &builder, NULL),
141  &error);
142 
143  auto errorPtr = amb::make_super(error);
144 
145  if(errorPtr)
146  {
147  DebugOut(DebugOut::Error)<<errorPtr->message<<std::endl;
148  }
149  }
150 
151  q->clear();
152 
153  return 1;
154 
155  },&queue);
156  }
157 
158  std::unordered_map<std::string, std::vector<DBusSignal*>> queue;
159 
160  static DBusSignaller * singleton;
161 };
162 
163 #endif