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:
Bill Somerville 2016-12-04 00:55:15 +00:00
parent ac859c8f68
commit 2255b17e91
11 changed files with 79 additions and 23 deletions

View File

@ -21,9 +21,12 @@ class MessageClient::impl
Q_OBJECT;
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}
, id_ {id}
, version_ {version}
, revision_ {revision}
, server_port_ {server_port}
, schema_ {2} // use 2 prior to negotiation not 1 which is broken
, heartbeat_timer_ {new QTimer {this}}
@ -66,6 +69,8 @@ public:
MessageClient * self_;
QString id_;
QString version_;
QString revision_;
QString server_string_;
port_type server_port_;
QHostAddress server_;
@ -188,6 +193,11 @@ void MessageClient::impl::parse_message (QByteArray const& msg)
default:
// 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;
}
}
@ -208,7 +218,8 @@ void MessageClient::impl::heartbeat ()
{
QByteArray message;
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))
{
writeDatagram (message, server_, server_port_);
@ -273,9 +284,10 @@ auto MessageClient::impl::check_status (QDataStream const& stream) const -> Stre
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}
, m_ {id, server_port, this}
, m_ {id, version, revision, server_port, this}
{
connect (&*m_, static_cast<void (impl::*) (impl::SocketError)> (&impl::error)
, [this] (impl::SocketError e)

View File

@ -32,7 +32,8 @@ public:
// instantiate and initiate a host lookup on the server
//
// 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
QHostAddress server_address () const;

View File

@ -21,8 +21,10 @@ class MessageServer::impl
Q_OBJECT;
public:
impl (MessageServer * self)
impl (MessageServer * self, QString const& version, QString const& revision)
: self_ {self}
, version_ {version}
, revision_ {revision}
, port_ {0u}
, clock_ {new QTimer {this}}
{
@ -60,6 +62,8 @@ public:
}
MessageServer * self_;
QString version_;
QString revision_;
port_type port_;
QHostAddress multicast_group_address_;
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))
{
auto& client = (clients_[id] = {sender, sender_port});
QByteArray client_version;
QByteArray client_revision;
if (NetworkMessage::Heartbeat == in.type ())
{
@ -159,7 +165,8 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s
// negotiated schema number
QByteArray message;
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))
{
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");
}
}
// 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 ();
@ -350,9 +360,9 @@ auto MessageServer::impl::check_status (QDataStream const& stream) const -> Stre
return result;
}
MessageServer::MessageServer (QObject * parent)
MessageServer::MessageServer (QObject * parent, QString const& version, QString const& revision)
: QObject {parent}
, m_ {this}
, m_ {this, version, revision}
{
}

View File

@ -31,12 +31,14 @@ public:
using port_type = quint16;
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
// argument is given it is assumed to be a multicast group address
// 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
// as a double click on the decode would
@ -59,7 +61,7 @@ public:
// the following signals are emitted when a client broadcasts the
// 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
, QString const& report, QString const& tx_mode, bool tx_enabled
, bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df

View File

@ -78,6 +78,8 @@
* Heartbeat Out/In 0 quint32
* Id (unique key) utf8
* Maximum schema number quint32
* version utf8
* revision utf8
*
* The heartbeat message shall be sent on a periodic basis every
* NetworkMessage::pulse seconds (see below), the WSJT-X

View File

@ -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
, QString const& id, QWidget * parent)
: QDockWidget {id, parent}
, QString const& id, QString const& version, QString const& revision
, QWidget * parent)
: QDockWidget {make_title (id, version, revision), parent}
, id_ {id}
, decodes_proxy_model_ {id_}
, decodes_table_view_ {new QTableView}

View File

@ -21,7 +21,8 @@ class ClientWidget
public:
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
, QString const& report, QString const& tx_mode, bool tx_enabled

View File

@ -126,9 +126,9 @@ void MessageAggregatorMainWindow::log_qso (QString const& /*id*/, QDateTime time
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);
auto view_action = dock->toggleViewAction ();
view_action->setEnabled (true);

View File

@ -32,7 +32,7 @@ public:
, QString const& name);
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);
QStandardItemModel * log_;

View File

@ -112,7 +112,7 @@ public:
}
private:
void add_client (QString const& id)
void add_client (QString const& id, QString const& version, QString const& revision)
{
auto client = new Client {id};
connect (server_, &MessageServer::status_update, client, &Client::update_status);
@ -120,7 +120,16 @@ private:
connect (server_, &MessageServer::WSPR_decode, client, &Client::beacon_spot_added);
clients_[id] = client;
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)

View File

@ -332,8 +332,9 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
"Please be patient,\n"
"this may take a few minutes", QString {}, 0, 1, this},
m_messageClient {new MessageClient {QApplication::applicationName (),
m_config.udp_server_name (), m_config.udp_server_port (),
this}},
version (), revision (),
m_config.udp_server_name (), m_config.udp_server_port (),
this}},
psk_Reporter {new PSK_Reporter {m_messageClient, this}},
m_manual {network_manager}
{