From 94337a2760371ab2267e6e03fe9a92e701918ae3 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 10 Sep 2014 09:18:41 +0000 Subject: [PATCH] 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 --- DXLabSuiteCommanderTransceiver.cpp | 49 +++++++++-------- DXLabSuiteCommanderTransceiver.hpp | 4 +- HRDTransceiver.cpp | 88 +++++++++++++++--------------- HRDTransceiver.hpp | 1 + 4 files changed, 72 insertions(+), 70 deletions(-) diff --git a/DXLabSuiteCommanderTransceiver.cpp b/DXLabSuiteCommanderTransceiver.cpp index da35f0c55..85736eae2 100644 --- a/DXLabSuiteCommanderTransceiver.cpp +++ b/DXLabSuiteCommanderTransceiver.cpp @@ -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; +} diff --git a/DXLabSuiteCommanderTransceiver.hpp b/DXLabSuiteCommanderTransceiver.hpp index b33ac3715..4ef11dfc2 100644 --- a/DXLabSuiteCommanderTransceiver.hpp +++ b/DXLabSuiteCommanderTransceiver.hpp @@ -3,12 +3,11 @@ #include -#include - #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 wrapped_; bool use_for_ptt_; diff --git a/HRDTransceiver.cpp b/HRDTransceiver.cpp index b9ab9ec13..523a38df8 100644 --- a/HRDTransceiver.cpp +++ b/HRDTransceiver.cpp @@ -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 message (new (string) HRDMessage); - bytes_to_send = message->size_; - while (total_bytes_sent < bytes_to_send) + if (!write_to_port (reinterpret_cast (message.data ()), message->size_)) { - auto bytes_sent = hrd_->write (reinterpret_cast (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)) diff --git a/HRDTransceiver.hpp b/HRDTransceiver.hpp index b23161673..f0001b7d3 100644 --- a/HRDTransceiver.hpp +++ b/HRDTransceiver.hpp @@ -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;