Enroute Flight Navigation
A navigation app for VFR pilots
TrafficDataSource_Tcp.h
1/***************************************************************************
2 * Copyright (C) 2021-2024 by Stefan Kebekus *
3 * stefan.kebekus@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 3 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21#pragma once
22
23#include <QPointer>
24#include <QTcpSocket>
25
26#include "traffic/TrafficDataSource_AbstractSocket.h"
27
28using namespace Qt::Literals::StringLiterals;
29
30
31namespace Traffic {
32
43
45 Q_OBJECT
46
47public:
58 TrafficDataSource_Tcp(bool isCanonical, QString hostName, quint16 port, QObject *parent = nullptr);
59
60 // Standard destructor
61 ~TrafficDataSource_Tcp() override;
62
63
64
65 //
66 // Properties
67 //
68
71 Q_PROPERTY(QString host READ host CONSTANT)
72
73
75 Q_PROPERTY(quint16 port READ port CONSTANT)
76
77
78
79 //
80 // Getter Methods
81 //
82
87 [[nodiscard]] QString dataFormat() const override { return u"FLARM/NMEA"_s; }
88
93 [[nodiscard]] QString host() const
94 {
95 return m_hostName;
96 }
97
105 [[nodiscard]] QString icon() const override { return u"/icons/material/ic_wifi.svg"_s; }
106
114 [[nodiscard]] auto sourceName() const -> QString override
115 {
116 return tr("TCP connection to %1 port %2").arg(m_hostName).arg(m_port);
117 }
118
123 [[nodiscard]] quint16 port() const
124 {
125 return m_port;
126 }
127
128public slots:
135
142
148 void setPassword(const QString& SSID, const QString& password) override;
149
150private slots:
151 // Read lines from the socket's text stream and passes the string on to
152 // processFLARMMessage.
153 void onReadyRead();
154
155 // This method does the actual job of sending the password to the traffic
156 // data receiver
157 //
158 // It checks if the instance is actually waiting for a password and returns
159 // if it is not.
160 //
161 // It connects the slots updatePasswordStatusOnHeartbeatChange that will
162 // respond to heartbeat (=password accepted) and
163 // updatePasswordStatusOnDisconnected (=password rejected). It will send the
164 // password and set passwordRequest_Status to "waitingForDevice"
165 void sendPassword_internal();
166
167 // This method set passwordRequest_Status to "idle", resets
168 // passwordRequest_SSID and passwordRequest_password, and disconnects the
169 // slots updatePasswordStatusOnHeartbeatChange and
170 // updatePasswordStatusOnDisconnected);
171 void resetPasswordLifecycle();
172
173 // This slot is called when the password has been rejected by the traffic
174 // data receiver. It clears the password from the database, schedules a
175 // reconnect and calls resetPasswordLifecycle().
176 void updatePasswordStatusOnDisconnected();
177
178 // This slot is called when the password has been accepted by the traffic
179 // data receiver. It emits a password storage request if appropriate and
180 // calls resetPasswordLifecycle().
181 void updatePasswordStatusOnHeartbeatChange(bool newHeartbeat);
182
183private:
184 Q_DISABLE_COPY_MOVE(TrafficDataSource_Tcp)
185
186 QTcpSocket m_socket;
187 QTextStream m_textStream;
188 QString m_hostName;
189 quint16 m_port;
190
191
192 /* Password lifecycle
193 *
194 * - The method onReadyRead detects that the device requests password. It
195 * will store the current SSID in passwordRequest_SSID and set
196 * passwordRequest_Status to waitingForPassword.
197 *
198 * - If a password for the SSID is found in the database, the method
199 * sendPassword is called with that password. Otherwise, the signal
200 * passwordRequest is emitted, which will hopefully lead to lead to a
201 * user-provided password through sendPassword()
202 *
203 * - The method send password will store the password in
204 * passwordRequest_password, send the password to the device and set
205 * passwordRequest_Status to waitingForDevice.
206 *
207 * - When the connection is closed while passwordRequest_Status ==
208 * waitingForDevice, this means that the traffic data receiver has
209 * rejected the password. The password stored in passwordRequest_password
210 * for passwordRequest_SSID is removed from the password database,
211 * passwordRequest_Status is set to idle, the members passwordRequest_SSID
212 * and passwordRequest_password are cleared and an immediate reconnect is
213 * scheduled.
214 *
215 * - When the heartbeat is received while passwordRequest_Status ==
216 * waitingForDevice, this means that the traffic data receiver has
217 * accepted the password. The instance will then emit the
218 * passwordStorageRequest. The member passwordRequest_Status is set to
219 * idle, and the members passwordRequest_SSID and passwordRequest_password
220 * are cleared.
221 */
222 enum : quint8 {
223 /* No password-related activity is pending */
224 idle,
225
226 /* Waiting for password
227 *
228 * A password has been requested by the traffic data receiver.
229 *
230 * At this stage, the member passwordRequest_SSID contains the network
231 * name of the WiFi network that the device was connected to at the
232 * time of the request.
233 */
234 waitingForPassword,
235
236 /* Waiting for device
237 *
238 * A password has been sent to the traffic data receiver, and this
239 * class is now waiting for the device to respond.
240 *
241 * At this stage, the member passwordRequest_SSID contains the network
242 * name of the WiFi network that the device was connected to at the
243 * time of the request. The member passwordRequest_password contains
244 * the password that has been sent to the traffic data receiver
245 */
246 waitingForDevice
247 } passwordRequest_Status {idle};
248
249 // See passwordRequest_Status documentation
250 QString passwordRequest_SSID;
251
252 // See passwordRequest_Status documentation
253 QString passwordRequest_password;
254};
255
256} // namespace Traffic
TrafficDataSource_AbstractSocket(bool isCanonical, QObject *parent)
Default constructor.
QString dataFormat() const override
Getter function for the property with the same name.
quint16 port() const
Getter function for the property with the same name.
void disconnectFromTrafficReceiver() override
Disconnect from traffic receiver.
TrafficDataSource_Tcp(bool isCanonical, QString hostName, quint16 port, QObject *parent=nullptr)
Default constructor.
void setPassword(const QString &SSID, const QString &password) override
Set password.
QString host() const
Getter function for the property with the same name.
QString icon() const override
Getter function for the property with the same name.
void connectToTrafficReceiver() override
Start attempt to connect to traffic receiver.
auto sourceName() const -> QString override
Getter function for the property with the same name.