FlightGear next
traffic.cpp
Go to the documentation of this file.
1/*
2 * Traffic module for swift<->FG connection
3 * SPDX-FileCopyrightText: (C) 2019-2022 swift Project Community / Contributors (https://swift-project.org/)
4 * SPDX-FileCopyrightText: (C) 2019-2022 Lars Toenning <dev@ltoenning.de>
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8
9#include "traffic.h"
11
12#include <algorithm>
13#include <iostream>
14
15
16namespace flightgear::swift {
17
18static const std::string k_fgswiftbus_traffic_interfacename = "org.swift_project.fgswiftbus.traffic";
19static const std::string k_fgswiftbus_traffic_objectpath = "/fgswiftbus/traffic";
20
22{
23 SG_LOG(SG_NETWORK, SG_INFO, "FGSwiftBus Traffic started");
24}
25
27{
28 cleanup();
29 SG_LOG(SG_NETWORK, SG_INFO, "FGSwiftBus Traffic stopped");
30}
31
32const std::string& CTraffic::InterfaceName()
33{
35}
36
37const std::string& CTraffic::ObjectPath()
38{
40}
41
43{
44 acm.reset(new FGSwiftAircraftManager());
45 return acm->isInitialized();
46}
47
49{
50 if (m_emitSimFrame) { sendDBusSignal("simFrame"); }
51 m_emitSimFrame = !m_emitSimFrame;
52}
53
54void CTraffic::emitPlaneAdded(const std::string& callsign)
55{
57 signalPlaneAdded.beginArgumentWrite();
58 signalPlaneAdded.appendArgument(callsign);
59 sendDBusMessage(signalPlaneAdded);
60}
61
62void CTraffic::cleanup()
63{
64 acm.reset();
65}
66
68{
69 if (acm)
70 acm->removeAllPlanes();
71}
72
73const char* introspection_traffic = DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE;
74
75DBusHandlerResult CTraffic::dbusMessageHandler(const CDBusMessage& message_)
76{
77 CDBusMessage message(message_);
78 const std::string sender = message.getSender();
79 const dbus_uint32_t serial = message.getSerial();
80 const bool wantsReply = message.wantsReply();
81
82 if (message.getInterfaceName() == DBUS_INTERFACE_INTROSPECTABLE) {
83 if (message.getMethodName() == "Introspect") {
84 sendDBusReply(sender, serial, introspection_traffic);
85 }
87 if (message.getMethodName() == "acquireMultiplayerPlanes") {
88 queueDBusCall([=]() {
89 std::string owner;
90 bool acquired = true;
91 CDBusMessage reply = CDBusMessage::createReply(sender, serial);
92 reply.beginArgumentWrite();
93 reply.appendArgument(acquired);
94 reply.appendArgument(owner);
95 sendDBusMessage(reply);
96 });
97 } else if (message.getMethodName() == "initialize") {
98 sendDBusReply(sender, serial, initialize());
99 } else if (message.getMethodName() == "cleanup") {
100 maybeSendEmptyDBusReply(wantsReply, sender, serial);
101 queueDBusCall([=]() {
102 cleanup();
103 });
104 } else if (message.getMethodName() == "addPlane") {
105 maybeSendEmptyDBusReply(wantsReply, sender, serial);
106 std::string callsign;
107 std::string modelName;
108 std::string aircraftIcao;
109 std::string airlineIcao;
110 std::string livery;
111 message.beginArgumentRead();
112 message.getArgument(callsign);
113 message.getArgument(modelName);
114 message.getArgument(aircraftIcao);
115 message.getArgument(airlineIcao);
116 message.getArgument(livery);
117
118 queueDBusCall([=]() {
119 if (acm->addPlane(callsign, modelName)) {
120 emitPlaneAdded(callsign);
121 }
122 });
123 } else if (message.getMethodName() == "removePlane") {
124 maybeSendEmptyDBusReply(wantsReply, sender, serial);
125 std::string callsign;
126 message.beginArgumentRead();
127 message.getArgument(callsign);
128 queueDBusCall([=]() {
129 acm->removePlane(callsign);
130 });
131 } else if (message.getMethodName() == "removeAllPlanes") {
132 maybeSendEmptyDBusReply(wantsReply, sender, serial);
133 queueDBusCall([=]() {
134 acm->removeAllPlanes();
135 });
136 } else if (message.getMethodName() == "setPlanesPositions") {
137 maybeSendEmptyDBusReply(wantsReply, sender, serial);
138 std::vector<std::string> callsigns;
139 std::vector<double> latitudes;
140 std::vector<double> longitudes;
141 std::vector<double> altitudes;
142 std::vector<double> pitches;
143 std::vector<double> rolls;
144 std::vector<double> headings;
145 std::vector<double> groundspeeds;
146 std::vector<bool> onGrounds;
147 message.beginArgumentRead();
148 message.getArgument(callsigns);
149 message.getArgument(latitudes);
150 message.getArgument(longitudes);
151 message.getArgument(altitudes);
152 message.getArgument(pitches);
153 message.getArgument(rolls);
154 message.getArgument(headings);
155 message.getArgument(groundspeeds);
156 message.getArgument(onGrounds);
157 queueDBusCall([=]() {
158 std::vector<SwiftPlaneUpdate> updates;
159 for (long unsigned int i = 0; i < latitudes.size(); i++) {
160 SGGeod pos;
161 pos.setLatitudeDeg(latitudes.at(i));
162 pos.setLongitudeDeg(longitudes.at(i));
163 pos.setElevationFt(altitudes.at(i));
164 SGVec3d orientation(pitches.at(i), rolls.at(i), headings.at(i));
165 updates.push_back({callsigns.at(i), pos, orientation, groundspeeds.at(i), onGrounds.at(i)});
166 }
167 acm->updatePlanes(updates);
168 });
169 } else if (message.getMethodName() == "getRemoteAircraftData") {
170 std::vector<std::string> requestedcallsigns;
171 message.beginArgumentRead();
172 message.getArgument(requestedcallsigns);
173 queueDBusCall([=]() {
174 std::vector<std::string> callsigns = requestedcallsigns;
175 std::vector<double> latitudesDeg;
176 std::vector<double> longitudesDeg;
177 std::vector<double> elevationsM;
178 std::vector<double> verticalOffsets;
179 acm->getRemoteAircraftData(callsigns, latitudesDeg, longitudesDeg, elevationsM, verticalOffsets);
180 CDBusMessage reply = CDBusMessage::createReply(sender, serial);
181 reply.beginArgumentWrite();
182 reply.appendArgument(callsigns);
183 reply.appendArgument(latitudesDeg);
184 reply.appendArgument(longitudesDeg);
185 reply.appendArgument(elevationsM);
186 reply.appendArgument(verticalOffsets);
187 sendDBusMessage(reply);
188 });
189 } else if (message.getMethodName() == "getElevationAtPosition") {
190 std::string callsign;
191 double latitudeDeg;
192 double longitudeDeg;
193 double altitudeMeters;
194 message.beginArgumentRead();
195 message.getArgument(callsign);
196 message.getArgument(latitudeDeg);
197 message.getArgument(longitudeDeg);
198 message.getArgument(altitudeMeters);
199 queueDBusCall([=]() {
200 SGGeod pos;
201 pos.setLatitudeDeg(latitudeDeg);
202 pos.setLongitudeDeg(longitudeDeg);
203 pos.setElevationM(altitudeMeters);
204 double elevation = acm->getElevationAtPosition(callsign, pos);
205 CDBusMessage reply = CDBusMessage::createReply(sender, serial);
206 reply.beginArgumentWrite();
207 reply.appendArgument(callsign);
208 reply.appendArgument(elevation);
209 sendDBusMessage(reply);
210 });
211 } else if (message.getMethodName() == "setPlanesTransponders") {
212 maybeSendEmptyDBusReply(wantsReply, sender, serial);
213 std::vector<std::string> callsigns;
214 std::vector<int> codes;
215 std::vector<bool> modeCs;
216 std::vector<bool> idents;
217 message.beginArgumentRead();
218 message.getArgument(callsigns);
219 message.getArgument(codes);
220 message.getArgument(modeCs);
221 message.getArgument(idents);
222 std::vector<AircraftTransponder> transponders;
223 transponders.reserve(callsigns.size());
224 for (long unsigned int i = 0; i < callsigns.size(); i++) {
225 transponders.emplace_back(callsigns.at(i), codes.at(i), modeCs.at(i), idents.at(i));
226 }
227 queueDBusCall([=]() {
228 acm->setPlanesTransponders(transponders);
229 });
230 } else if (message.getMethodName() == "setPlanesSurfaces") {
231 maybeSendEmptyDBusReply(wantsReply, sender, serial);
232 std::vector<std::string> callsigns;
233 std::vector<double> gears;
234 std::vector<double> flaps;
235 std::vector<double> spoilers;
236 std::vector<double> speedBrakes;
237 std::vector<double> slats;
238 std::vector<double> wingSweeps;
239 std::vector<double> thrusts;
240 std::vector<double> elevators;
241 std::vector<double> rudders;
242 std::vector<double> ailerons;
243 std::vector<bool> landLights;
244 std::vector<bool> taxiLights;
245 std::vector<bool> beaconLights;
246 std::vector<bool> strobeLights;
247 std::vector<bool> navLights;
248 std::vector<int> lightPatterns;
249 message.beginArgumentRead();
250 message.getArgument(callsigns);
251 message.getArgument(gears);
252 message.getArgument(flaps);
253 message.getArgument(spoilers);
254 message.getArgument(speedBrakes);
255 message.getArgument(slats);
256 message.getArgument(wingSweeps);
257 message.getArgument(thrusts);
258 message.getArgument(elevators);
259 message.getArgument(rudders);
260 message.getArgument(ailerons);
261 message.getArgument(landLights);
262 message.getArgument(taxiLights);
263 message.getArgument(beaconLights);
264 message.getArgument(strobeLights);
265 message.getArgument(navLights);
266 message.getArgument(lightPatterns);
267 std::vector<AircraftSurfaces> surfaces;
268 surfaces.reserve(callsigns.size());
269 for (long unsigned int i = 0; i < callsigns.size(); i++) {
270 surfaces.emplace_back(callsigns.at(i), gears.at(i), flaps.at(i), spoilers.at(i), speedBrakes.at(i), slats.at(i),
271 wingSweeps.at(i), thrusts.at(i), elevators.at(i), rudders.at(i), ailerons.at(i),
272 landLights.at(i), taxiLights.at(i), beaconLights.at(i), strobeLights.at(i), navLights.at(i), lightPatterns.at(i));
273 }
274 queueDBusCall([=]() {
275 acm->setPlanesSurfaces(surfaces);
276 });
277 } else {
278 // Unknown message. Tell DBus that we cannot handle it
279 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
280 }
281 }
282 return DBUS_HANDLER_RESULT_HANDLED;
283}
284
286{
288 return 1;
289}
290
291} // namespace flightgear::swift
#define i(x)
static CDBusMessage createSignal(const std::string &path, const std::string &interfaceName, const std::string &signalName)
Creates a DBus message containing a DBus signal.
void appendArgument(bool value)
Append argument.
static CDBusMessage createReply(const std::string &destination, dbus_uint32_t serial)
Creates a DBus message containing a DBus reply.
std::string getSender() const
Get the message sender.
dbus_uint32_t getSerial() const
Get the message serial. This is usally required for reply message.
std::string getMethodName() const
Get the called method name.
std::string getInterfaceName() const
Get the called interface name.
bool wantsReply() const
Does this message want a reply?
void getArgument(int &value)
Read single argument.
void beginArgumentRead()
Begin reading arguments.
void beginArgumentWrite()
Begin writing argument.
void sendDBusMessage(const CDBusMessage &message)
Send DBus message.
void invokeQueuedDBusCalls()
Invoke all pending DBus calls. They will be executed in the calling thread.
void sendDBusReply(const std::string &destination, dbus_uint32_t serial, const T &argument)
Send DBus reply.
Definition dbusobject.h:53
void sendDBusSignal(const std::string &name)
Send DBus signal.
void maybeSendEmptyDBusReply(bool wantsReply, const std::string &destination, dbus_uint32_t serial)
Maybe sends an empty DBus reply (acknowledgement)
void queueDBusCall(const std::function< void()> &func)
Queue a DBus call to be executed in a different thread.
DBusHandlerResult dbusMessageHandler(const CDBusMessage &message) override
DBus message handler.
Definition traffic.cpp:75
virtual void dbusDisconnectedHandler() override
Handler which is called when DBusConnection disconnected.
Definition traffic.cpp:67
static const std::string & ObjectPath()
DBus object path.
Definition traffic.cpp:37
static const std::string & InterfaceName()
DBus interface name.
Definition traffic.cpp:32
int process()
Perform generic processing.
Definition traffic.cpp:285
~CTraffic() override
Destructor.
Definition traffic.cpp:26
bool initialize()
Initialize the multiplayer planes rendering and return true if successful.
Definition traffic.cpp:42
static const std::string k_fgswiftbus_traffic_objectpath
Definition traffic.cpp:19
static const std::string k_fgswiftbus_traffic_interfacename
Definition traffic.cpp:18
const char * introspection_traffic
Definition traffic.cpp:73