Tidy up DX Lab and HRD interface implementations

Applied techniques  learned from  dealing with  HRD quirks  and TCP/IP
client   issues   on  Windows   to   the   DX  Lab   Suite   Commander
interface. These changes should hopefully make both the HRD and DX Lab
Suite CAT  interfacing more robust  in the  face of network  and other
latency issues or server failures.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@4296 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Bill Somerville 2014-09-10 09:18:41 +00:00
parent 098ec3f923
commit 2099db5ea9
4 changed files with 72 additions and 70 deletions

View File

@ -10,7 +10,6 @@
namespace
{
char const * const commander_transceiver_name {"DX Lab Suite Commander"};
int socket_wait_time {5000};
QString map_mode (Transceiver::MODE mode)
{
@ -68,7 +67,7 @@ void DXLabSuiteCommanderTransceiver::do_start ()
}
commander_->connectToHost (std::get<0> (server_details), std::get<1> (server_details));
if (!commander_->waitForConnected (socket_wait_time))
if (!commander_->waitForConnected ())
{
#if WSJT_TRACE_CAT
qDebug () << "DXLabSuiteCommanderTransceiver::start failed to connect" << commander_->errorString ();
@ -332,17 +331,7 @@ void DXLabSuiteCommanderTransceiver::simple_command (QByteArray const& cmd, bool
#endif
}
if (QTcpSocket::ConnectedState != commander_->state ())
{
#if WSJT_TRACE_CAT
qDebug () << "DXLabSuiteCommanderTransceiver::simple_command failed:" << commander_->errorString ();
#endif
throw error {tr ("DX Lab Suite Commander send command failed\n") + commander_->errorString ()};
}
commander_->write (cmd);
if (!commander_->waitForBytesWritten (socket_wait_time))
if (!write_to_port (cmd))
{
#if WSJT_TRACE_CAT
qDebug () << "DXLabSuiteCommanderTransceiver::simple_command failed:" << commander_->errorString ();
@ -356,21 +345,14 @@ QByteArray DXLabSuiteCommanderTransceiver::command_with_reply (QByteArray const&
{
Q_ASSERT (commander_);
if (QTcpSocket::ConnectedState != commander_->state ())
if (!no_debug)
{
#if WSJT_TRACE_CAT
qDebug () << "DXLabSuiteCommanderTransceiver::command_with_reply \"" << cmd << "\" connection failed:" << commander_->errorString ();
qDebug () << "DXLabSuiteCommanderTransceiver:command_with_reply(" << cmd << ')';
#endif
throw error {
tr ("DX Lab Suite Commander failed to send command \"%1\" connection failed: %2\n")
.arg (cmd.constData ())
.arg (commander_->errorString ())
};
}
commander_->write (cmd);
if (!commander_->waitForBytesWritten (socket_wait_time) || QTcpSocket::ConnectedState != commander_->state ())
if (!write_to_port (cmd))
{
#if WSJT_TRACE_CAT
qDebug () << "DXLabSuiteCommanderTransceiver::command_with_reply failed to send command:" << commander_->errorString ();
@ -389,7 +371,7 @@ QByteArray DXLabSuiteCommanderTransceiver::command_with_reply (QByteArray const&
bool replied {false};
while (!replied && --retries)
{
replied = commander_->waitForReadyRead (socket_wait_time);
replied = commander_->waitForReadyRead ();
if (!replied && commander_->error () != commander_->SocketTimeoutError)
{
#if WSJT_TRACE_CAT
@ -427,3 +409,22 @@ QByteArray DXLabSuiteCommanderTransceiver::command_with_reply (QByteArray const&
return result;
}
bool DXLabSuiteCommanderTransceiver::write_to_port (QByteArray const& data)
{
auto to_send = data.constData ();
auto length = data.size ();
qint64 total_bytes_sent {0};
while (total_bytes_sent < length)
{
auto bytes_sent = commander_->write (to_send + total_bytes_sent, length - total_bytes_sent);
if (bytes_sent < 0 || !commander_->waitForBytesWritten ())
{
return false;
}
total_bytes_sent += bytes_sent;
}
return true;
}

View File

@ -3,12 +3,11 @@
#include <memory>
#include <QByteArray>
#include "TransceiverFactory.hpp"
#include "PollingTransceiver.hpp"
class QTcpSocket;
class QByteArray;
//
// DX Lab Suite Commander Interface
@ -43,6 +42,7 @@ protected:
private:
void simple_command (QByteArray const&, bool no_debug = false);
QByteArray command_with_reply (QByteArray const&, bool no_debug = false);
bool write_to_port (QByteArray const&);
std::unique_ptr<TransceiverBase> wrapped_;
bool use_for_ptt_;

View File

@ -11,7 +11,6 @@
namespace
{
char const * const HRD_transceiver_name = "Ham Radio Deluxe";
int socket_wait_time {5000};
}
void HRDTransceiver::register_transceivers (TransceiverFactory::Transceivers * registry, int id)
@ -111,7 +110,7 @@ void HRDTransceiver::do_start ()
}
hrd_->connectToHost (std::get<0> (server_details), std::get<1> (server_details));
if (!hrd_->waitForConnected (socket_wait_time))
if (!hrd_->waitForConnected ())
{
#if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::start failed to connect:" << hrd_->errorString ();
@ -139,7 +138,7 @@ void HRDTransceiver::do_start ()
protocol_ = v4; // try again with older protocol
hrd_->connectToHost (std::get<0> (server_details), std::get<1> (server_details));
if (!hrd_->waitForConnected (socket_wait_time))
if (!hrd_->waitForConnected ())
{
#if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::do_start failed to connect:" << hrd_->errorString ();
@ -694,68 +693,53 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr
};
}
int bytes_to_send;
int total_bytes_sent {0};
if (!no_debug)
{
#if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::send_command:" << cmd;
#endif
}
if (v4 == protocol_)
{
auto message = ((prepend_context ? context + cmd : cmd) + "\r").toLocal8Bit ();
bytes_to_send = message.size ();
while (total_bytes_sent < bytes_to_send)
{
auto bytes_sent = hrd_->write (message.constData () + total_bytes_sent, bytes_to_send - total_bytes_sent);
if (bytes_sent < 0 || !hrd_->waitForBytesWritten (socket_wait_time))
{
#if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::send_command failed to write command \"" << cmd << "\" to HRD";
#endif
throw error {
tr ("Ham Radio Deluxe: failed to write command \"%1\"")
.arg (cmd)
};
}
total_bytes_sent += bytes_sent;
}
if (!no_debug)
if (!write_to_port (message.constData (), message.size ()))
{
#if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::send_command:" << message;
qDebug () << "HRDTransceiver::send_command failed to write command \"" << cmd << "\" to HRD";
#endif
throw error {
tr ("Ham Radio Deluxe: failed to write command \"%1\"")
.arg (cmd)
};
}
}
else
{
auto string = prepend_context ? context + cmd : cmd;
QScopedPointer<HRDMessage> message (new (string) HRDMessage);
bytes_to_send = message->size_;
while (total_bytes_sent < bytes_to_send)
if (!write_to_port (reinterpret_cast<char const *> (message.data ()), message->size_))
{
auto bytes_sent = hrd_->write (reinterpret_cast<char *> (message.data ()) + total_bytes_sent, bytes_to_send - total_bytes_sent);
if (bytes_sent < 0 || !hrd_->waitForBytesWritten (socket_wait_time))
{
#if WSJT_TRACE_CAT
qDebug () << "HRDTransceiver::send_command failed to write command \"" << cmd << "\" to HRD";
qDebug () << "HRDTransceiver::send_command failed to write command \"" << cmd << "\" to HRD";
#endif
throw error {
tr ("Ham Radio Deluxe: failed to write command \"%1\"")
.arg (cmd)
};
}
total_bytes_sent += bytes_sent;
throw error {
tr ("Ham Radio Deluxe: failed to write command \"%1\"")
.arg (cmd)
};
}
}
// waitForReadReady appears to be unreliable on Windows timing out
// when data is waiting so retry a few times
unsigned retries {5};
// waitForReadReady appears to be occasionally unreliable on Windows
// timing out when data is waiting so retry a few times
unsigned retries {3};
bool replied {false};
while (!replied && --retries)
while (!replied && retries--)
{
replied = hrd_->waitForReadyRead (socket_wait_time);
replied = hrd_->waitForReadyRead ();
if (!replied && hrd_->error () != hrd_->SocketTimeoutError)
{
#if WSJT_TRACE_CAT
@ -823,6 +807,22 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr
return result;
}
bool HRDTransceiver::write_to_port (char const * data, qint64 length)
{
qint64 total_bytes_sent {0};
while (total_bytes_sent < length)
{
auto bytes_sent = hrd_->write (data + total_bytes_sent, length - total_bytes_sent);
if (bytes_sent < 0 || !hrd_->waitForBytesWritten ())
{
return false;
}
total_bytes_sent += bytes_sent;
}
return true;
}
void HRDTransceiver::send_simple_command (QString const& command, bool no_debug)
{
if ("OK" != send_command (command, no_debug))

View File

@ -48,6 +48,7 @@ protected:
private:
QString send_command (QString const&, bool no_debug = false, bool prepend_context = true, bool recurse = false);
void send_simple_command (QString const&, bool no_debug = false);
bool write_to_port (char const *, qint64 length);
void sync_impl ();
int find_button (QRegExp const&) const;
int find_dropdown (QRegExp const&) const;