mirror of https://github.com/saitohirga/WSJT-X.git
Add version and revision information to UDP heartbeat messages
Updated UDP examples to show the version and revision information received from clients. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@7358 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
parent
ac859c8f68
commit
2255b17e91
|
@ -21,9 +21,12 @@ class MessageClient::impl
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
impl (QString const& id, port_type server_port, MessageClient * self)
|
impl (QString const& id, QString const& version, QString const& revision,
|
||||||
|
port_type server_port, MessageClient * self)
|
||||||
: self_ {self}
|
: self_ {self}
|
||||||
, id_ {id}
|
, id_ {id}
|
||||||
|
, version_ {version}
|
||||||
|
, revision_ {revision}
|
||||||
, server_port_ {server_port}
|
, server_port_ {server_port}
|
||||||
, schema_ {2} // use 2 prior to negotiation not 1 which is broken
|
, schema_ {2} // use 2 prior to negotiation not 1 which is broken
|
||||||
, heartbeat_timer_ {new QTimer {this}}
|
, heartbeat_timer_ {new QTimer {this}}
|
||||||
|
@ -66,6 +69,8 @@ public:
|
||||||
|
|
||||||
MessageClient * self_;
|
MessageClient * self_;
|
||||||
QString id_;
|
QString id_;
|
||||||
|
QString version_;
|
||||||
|
QString revision_;
|
||||||
QString server_string_;
|
QString server_string_;
|
||||||
port_type server_port_;
|
port_type server_port_;
|
||||||
QHostAddress server_;
|
QHostAddress server_;
|
||||||
|
@ -188,6 +193,11 @@ void MessageClient::impl::parse_message (QByteArray const& msg)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Ignore
|
// Ignore
|
||||||
|
//
|
||||||
|
// Note that although server heartbeat messages are not
|
||||||
|
// parsed here they are still partially parsed in the
|
||||||
|
// message reader class to negotiate the maximum schema
|
||||||
|
// number being used on the network.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,7 +218,8 @@ void MessageClient::impl::heartbeat ()
|
||||||
{
|
{
|
||||||
QByteArray message;
|
QByteArray message;
|
||||||
NetworkMessage::Builder hb {&message, NetworkMessage::Heartbeat, id_, schema_};
|
NetworkMessage::Builder hb {&message, NetworkMessage::Heartbeat, id_, schema_};
|
||||||
hb << NetworkMessage::Builder::schema_number; // maximum schema number accepted
|
hb << NetworkMessage::Builder::schema_number // maximum schema number accepted
|
||||||
|
<< version_.toUtf8 () << revision_.toUtf8 ();
|
||||||
if (OK == check_status (hb))
|
if (OK == check_status (hb))
|
||||||
{
|
{
|
||||||
writeDatagram (message, server_, server_port_);
|
writeDatagram (message, server_, server_port_);
|
||||||
|
@ -273,9 +284,10 @@ auto MessageClient::impl::check_status (QDataStream const& stream) const -> Stre
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageClient::MessageClient (QString const& id, QString const& server, port_type server_port, QObject * self)
|
MessageClient::MessageClient (QString const& id, QString const& version, QString const& revision,
|
||||||
|
QString const& server, port_type server_port, QObject * self)
|
||||||
: QObject {self}
|
: QObject {self}
|
||||||
, m_ {id, server_port, this}
|
, m_ {id, version, revision, server_port, this}
|
||||||
{
|
{
|
||||||
connect (&*m_, static_cast<void (impl::*) (impl::SocketError)> (&impl::error)
|
connect (&*m_, static_cast<void (impl::*) (impl::SocketError)> (&impl::error)
|
||||||
, [this] (impl::SocketError e)
|
, [this] (impl::SocketError e)
|
||||||
|
|
|
@ -32,7 +32,8 @@ public:
|
||||||
// instantiate and initiate a host lookup on the server
|
// instantiate and initiate a host lookup on the server
|
||||||
//
|
//
|
||||||
// messages will be silently dropped until a server host lookup is complete
|
// messages will be silently dropped until a server host lookup is complete
|
||||||
MessageClient (QString const& id, QString const& server, port_type server_port, QObject * parent = nullptr);
|
MessageClient (QString const& id, QString const& version, QString const& revision,
|
||||||
|
QString const& server, port_type server_port, QObject * parent = nullptr);
|
||||||
|
|
||||||
// query server details
|
// query server details
|
||||||
QHostAddress server_address () const;
|
QHostAddress server_address () const;
|
||||||
|
|
|
@ -21,8 +21,10 @@ class MessageServer::impl
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
impl (MessageServer * self)
|
impl (MessageServer * self, QString const& version, QString const& revision)
|
||||||
: self_ {self}
|
: self_ {self}
|
||||||
|
, version_ {version}
|
||||||
|
, revision_ {revision}
|
||||||
, port_ {0u}
|
, port_ {0u}
|
||||||
, clock_ {new QTimer {this}}
|
, clock_ {new QTimer {this}}
|
||||||
{
|
{
|
||||||
|
@ -60,6 +62,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageServer * self_;
|
MessageServer * self_;
|
||||||
|
QString version_;
|
||||||
|
QString revision_;
|
||||||
port_type port_;
|
port_type port_;
|
||||||
QHostAddress multicast_group_address_;
|
QHostAddress multicast_group_address_;
|
||||||
static BindMode constexpr bind_mode_ = ShareAddress | ReuseAddressHint;
|
static BindMode constexpr bind_mode_ = ShareAddress | ReuseAddressHint;
|
||||||
|
@ -145,6 +149,8 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s
|
||||||
if (!clients_.contains (id))
|
if (!clients_.contains (id))
|
||||||
{
|
{
|
||||||
auto& client = (clients_[id] = {sender, sender_port});
|
auto& client = (clients_[id] = {sender, sender_port});
|
||||||
|
QByteArray client_version;
|
||||||
|
QByteArray client_revision;
|
||||||
|
|
||||||
if (NetworkMessage::Heartbeat == in.type ())
|
if (NetworkMessage::Heartbeat == in.type ())
|
||||||
{
|
{
|
||||||
|
@ -159,7 +165,8 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s
|
||||||
// negotiated schema number
|
// negotiated schema number
|
||||||
QByteArray message;
|
QByteArray message;
|
||||||
NetworkMessage::Builder hb {&message, NetworkMessage::Heartbeat, id, client.negotiated_schema_number_};
|
NetworkMessage::Builder hb {&message, NetworkMessage::Heartbeat, id, client.negotiated_schema_number_};
|
||||||
hb << NetworkMessage::Builder::schema_number; // maximum schema number accepted
|
hb << NetworkMessage::Builder::schema_number // maximum schema number accepted
|
||||||
|
<< version_.toUtf8 () << revision_.toUtf8 ();
|
||||||
if (impl::OK == check_status (hb))
|
if (impl::OK == check_status (hb))
|
||||||
{
|
{
|
||||||
writeDatagram (message, client.sender_address_, client.sender_port_);
|
writeDatagram (message, client.sender_address_, client.sender_port_);
|
||||||
|
@ -169,8 +176,11 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s
|
||||||
Q_EMIT self_->error ("Error creating UDP message");
|
Q_EMIT self_->error ("Error creating UDP message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// we don't care if this fails to read
|
||||||
|
in >> client_version >> client_revision;
|
||||||
}
|
}
|
||||||
Q_EMIT self_->client_opened (id);
|
Q_EMIT self_->client_opened (id, QString::fromUtf8 (client_version),
|
||||||
|
QString::fromUtf8 (client_revision));
|
||||||
}
|
}
|
||||||
clients_[id].last_activity_ = QDateTime::currentDateTime ();
|
clients_[id].last_activity_ = QDateTime::currentDateTime ();
|
||||||
|
|
||||||
|
@ -350,9 +360,9 @@ auto MessageServer::impl::check_status (QDataStream const& stream) const -> Stre
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageServer::MessageServer (QObject * parent)
|
MessageServer::MessageServer (QObject * parent, QString const& version, QString const& revision)
|
||||||
: QObject {parent}
|
: QObject {parent}
|
||||||
, m_ {this}
|
, m_ {this, version, revision}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,12 +31,14 @@ public:
|
||||||
using port_type = quint16;
|
using port_type = quint16;
|
||||||
using Frequency = Radio::Frequency;
|
using Frequency = Radio::Frequency;
|
||||||
|
|
||||||
MessageServer (QObject * parent = nullptr);
|
MessageServer (QObject * parent = nullptr,
|
||||||
|
QString const& version = QString {}, QString const& revision = QString {});
|
||||||
|
|
||||||
// start or restart the server, if the multicast_group_address
|
// start or restart the server, if the multicast_group_address
|
||||||
// argument is given it is assumed to be a multicast group address
|
// argument is given it is assumed to be a multicast group address
|
||||||
// which the server will join
|
// which the server will join
|
||||||
Q_SLOT void start (port_type port, QHostAddress const& multicast_group_address = QHostAddress {});
|
Q_SLOT void start (port_type port,
|
||||||
|
QHostAddress const& multicast_group_address = QHostAddress {});
|
||||||
|
|
||||||
// ask the client with identification 'id' to make the same action
|
// ask the client with identification 'id' to make the same action
|
||||||
// as a double click on the decode would
|
// as a double click on the decode would
|
||||||
|
@ -59,7 +61,7 @@ public:
|
||||||
|
|
||||||
// the following signals are emitted when a client broadcasts the
|
// the following signals are emitted when a client broadcasts the
|
||||||
// matching message
|
// matching message
|
||||||
Q_SIGNAL void client_opened (QString const& id);
|
Q_SIGNAL void client_opened (QString const& id, QString const& version, QString const& revision);
|
||||||
Q_SIGNAL void status_update (QString const& id, Frequency, QString const& mode, QString const& dx_call
|
Q_SIGNAL void status_update (QString const& id, Frequency, QString const& mode, QString const& dx_call
|
||||||
, QString const& report, QString const& tx_mode, bool tx_enabled
|
, QString const& report, QString const& tx_mode, bool tx_enabled
|
||||||
, bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df
|
, bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df
|
||||||
|
|
|
@ -78,6 +78,8 @@
|
||||||
* Heartbeat Out/In 0 quint32
|
* Heartbeat Out/In 0 quint32
|
||||||
* Id (unique key) utf8
|
* Id (unique key) utf8
|
||||||
* Maximum schema number quint32
|
* Maximum schema number quint32
|
||||||
|
* version utf8
|
||||||
|
* revision utf8
|
||||||
*
|
*
|
||||||
* The heartbeat message shall be sent on a periodic basis every
|
* The heartbeat message shall be sent on a periodic basis every
|
||||||
* NetworkMessage::pulse seconds (see below), the WSJT-X
|
* NetworkMessage::pulse seconds (see below), the WSJT-X
|
||||||
|
|
|
@ -94,9 +94,27 @@ void ClientWidget::IdFilterModel::rx_df (int df)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
QString make_title (QString const& id, QString const& version, QString const& revision)
|
||||||
|
{
|
||||||
|
QString title {id};
|
||||||
|
if (version.size ())
|
||||||
|
{
|
||||||
|
title += QString {" v%1"}.arg (version);
|
||||||
|
}
|
||||||
|
if (revision.size ())
|
||||||
|
{
|
||||||
|
title += QString {" (%1)"}.arg (revision);
|
||||||
|
}
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemModel * beacons_model
|
ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemModel * beacons_model
|
||||||
, QString const& id, QWidget * parent)
|
, QString const& id, QString const& version, QString const& revision
|
||||||
: QDockWidget {id, parent}
|
, QWidget * parent)
|
||||||
|
: QDockWidget {make_title (id, version, revision), parent}
|
||||||
, id_ {id}
|
, id_ {id}
|
||||||
, decodes_proxy_model_ {id_}
|
, decodes_proxy_model_ {id_}
|
||||||
, decodes_table_view_ {new QTableView}
|
, decodes_table_view_ {new QTableView}
|
||||||
|
|
|
@ -21,7 +21,8 @@ class ClientWidget
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemModel * beacons_model
|
explicit ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemModel * beacons_model
|
||||||
, QString const& id, QWidget * parent = nullptr);
|
, QString const& id, QString const& version, QString const& revision
|
||||||
|
, QWidget * parent = nullptr);
|
||||||
|
|
||||||
Q_SLOT void update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call
|
Q_SLOT void update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call
|
||||||
, QString const& report, QString const& tx_mode, bool tx_enabled
|
, QString const& report, QString const& tx_mode, bool tx_enabled
|
||||||
|
|
|
@ -126,9 +126,9 @@ void MessageAggregatorMainWindow::log_qso (QString const& /*id*/, QDateTime time
|
||||||
log_table_view_->scrollToBottom ();
|
log_table_view_->scrollToBottom ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageAggregatorMainWindow::add_client (QString const& id)
|
void MessageAggregatorMainWindow::add_client (QString const& id, QString const& version, QString const& revision)
|
||||||
{
|
{
|
||||||
auto dock = new ClientWidget {decodes_model_, beacons_model_, id, this};
|
auto dock = new ClientWidget {decodes_model_, beacons_model_, id, version, revision, this};
|
||||||
dock->setAttribute (Qt::WA_DeleteOnClose);
|
dock->setAttribute (Qt::WA_DeleteOnClose);
|
||||||
auto view_action = dock->toggleViewAction ();
|
auto view_action = dock->toggleViewAction ();
|
||||||
view_action->setEnabled (true);
|
view_action->setEnabled (true);
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
, QString const& name);
|
, QString const& name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void add_client (QString const& id);
|
void add_client (QString const& id, QString const& version, QString const& revision);
|
||||||
void remove_client (QString const& id);
|
void remove_client (QString const& id);
|
||||||
|
|
||||||
QStandardItemModel * log_;
|
QStandardItemModel * log_;
|
||||||
|
|
|
@ -112,7 +112,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void add_client (QString const& id)
|
void add_client (QString const& id, QString const& version, QString const& revision)
|
||||||
{
|
{
|
||||||
auto client = new Client {id};
|
auto client = new Client {id};
|
||||||
connect (server_, &MessageServer::status_update, client, &Client::update_status);
|
connect (server_, &MessageServer::status_update, client, &Client::update_status);
|
||||||
|
@ -120,7 +120,16 @@ private:
|
||||||
connect (server_, &MessageServer::WSPR_decode, client, &Client::beacon_spot_added);
|
connect (server_, &MessageServer::WSPR_decode, client, &Client::beacon_spot_added);
|
||||||
clients_[id] = client;
|
clients_[id] = client;
|
||||||
server_->replay (id);
|
server_->replay (id);
|
||||||
std::cout << "Discovered WSJT-X instance: " << id.toStdString () << std::endl;
|
std::cout << "Discovered WSJT-X instance: " << id.toStdString ();
|
||||||
|
if (version.size ())
|
||||||
|
{
|
||||||
|
std::cout << " v" << version.toStdString ();
|
||||||
|
}
|
||||||
|
if (revision.size ())
|
||||||
|
{
|
||||||
|
std::cout << " (" << revision.toStdString () << ")";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_client (QString const& id)
|
void remove_client (QString const& id)
|
||||||
|
|
|
@ -332,8 +332,9 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||||
"Please be patient,\n"
|
"Please be patient,\n"
|
||||||
"this may take a few minutes", QString {}, 0, 1, this},
|
"this may take a few minutes", QString {}, 0, 1, this},
|
||||||
m_messageClient {new MessageClient {QApplication::applicationName (),
|
m_messageClient {new MessageClient {QApplication::applicationName (),
|
||||||
m_config.udp_server_name (), m_config.udp_server_port (),
|
version (), revision (),
|
||||||
this}},
|
m_config.udp_server_name (), m_config.udp_server_port (),
|
||||||
|
this}},
|
||||||
psk_Reporter {new PSK_Reporter {m_messageClient, this}},
|
psk_Reporter {new PSK_Reporter {m_messageClient, this}},
|
||||||
m_manual {network_manager}
|
m_manual {network_manager}
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue