mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-03 21:40:52 -05:00 
			
		
		
		
	they are included by automoc. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@4035 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
		
			
				
	
	
		
			398 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			398 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "DXLabSuiteCommanderTransceiver.hpp"
 | 
						|
 | 
						|
#include <QTcpSocket>
 | 
						|
#include <QRegularExpression>
 | 
						|
 | 
						|
#include "NetworkServerLookup.hpp"
 | 
						|
 | 
						|
#include "moc_DXLabSuiteCommanderTransceiver.cpp"
 | 
						|
 | 
						|
namespace
 | 
						|
{
 | 
						|
  char const * const commander_transceiver_name {"DX Lab Suite Commander"};
 | 
						|
  int socket_wait_time {5000};
 | 
						|
 | 
						|
  QString map_mode (Transceiver::MODE mode)
 | 
						|
  {
 | 
						|
    switch (mode)
 | 
						|
      {
 | 
						|
      case Transceiver::AM: return "AM";
 | 
						|
      case Transceiver::CW: return "CW";
 | 
						|
      case Transceiver::CW_R: return "CW-R";
 | 
						|
      case Transceiver::USB: return "USB";
 | 
						|
      case Transceiver::LSB: return "LSB";
 | 
						|
      case Transceiver::FSK: return "RTTY";
 | 
						|
      case Transceiver::FSK_R: return "RTTY-R";
 | 
						|
      case Transceiver::DIG_L: return "DATA-L";
 | 
						|
      case Transceiver::DIG_U: return "DATA-U";
 | 
						|
      case Transceiver::FM:
 | 
						|
      case Transceiver::DIG_FM:
 | 
						|
        return "FM";
 | 
						|
      default: break;
 | 
						|
      }
 | 
						|
    return "USB";
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void DXLabSuiteCommanderTransceiver::register_transceivers (TransceiverFactory::Transceivers * registry, int id)
 | 
						|
{
 | 
						|
  (*registry)[commander_transceiver_name] = TransceiverFactory::Capabilities {id, TransceiverFactory::Capabilities::network, true};
 | 
						|
}
 | 
						|
 | 
						|
DXLabSuiteCommanderTransceiver::DXLabSuiteCommanderTransceiver (std::unique_ptr<TransceiverBase> wrapped, QString const& address, bool use_for_ptt, int poll_interval)
 | 
						|
  : PollingTransceiver {poll_interval}
 | 
						|
  , wrapped_ {std::move (wrapped)}
 | 
						|
  , use_for_ptt_ {use_for_ptt}
 | 
						|
  , server_ {address}
 | 
						|
  , commander_ {nullptr}
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
DXLabSuiteCommanderTransceiver::~DXLabSuiteCommanderTransceiver ()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void DXLabSuiteCommanderTransceiver::do_start ()
 | 
						|
{
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
  qDebug () << "DXLabSuiteCommanderTransceiver::start";
 | 
						|
#endif
 | 
						|
 | 
						|
  wrapped_->start ();
 | 
						|
 | 
						|
  auto server_details = network_server_lookup (server_, 52002u, QHostAddress::LocalHost, QAbstractSocket::IPv4Protocol);
 | 
						|
 | 
						|
  if (!commander_)
 | 
						|
    {
 | 
						|
      commander_ = new QTcpSocket {this}; // QObject takes ownership
 | 
						|
    }
 | 
						|
 | 
						|
  commander_->connectToHost (std::get<0> (server_details), std::get<1> (server_details));
 | 
						|
  if (!commander_->waitForConnected (socket_wait_time))
 | 
						|
    {
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
      qDebug () << "DXLabSuiteCommanderTransceiver::start failed to connect" << commander_->errorString ();
 | 
						|
#endif
 | 
						|
 | 
						|
      throw error {tr ("Failed to connect to DX Lab Suite Commander\n") + commander_->errorString ()};
 | 
						|
    }
 | 
						|
      
 | 
						|
  poll ();
 | 
						|
}
 | 
						|
 | 
						|
void DXLabSuiteCommanderTransceiver::do_stop ()
 | 
						|
{
 | 
						|
  if (commander_)
 | 
						|
    {
 | 
						|
      commander_->close ();
 | 
						|
      delete commander_, commander_ = nullptr;
 | 
						|
    }
 | 
						|
 | 
						|
  wrapped_->stop ();
 | 
						|
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
  qDebug () << "DXLabSuiteCommanderTransceiver::stop";
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
void DXLabSuiteCommanderTransceiver::do_ptt (bool on)
 | 
						|
{
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
  qDebug () << "DXLabSuiteCommanderTransceiver::do_ptt:" << on << state ();
 | 
						|
#endif
 | 
						|
 | 
						|
  if (use_for_ptt_)
 | 
						|
    {
 | 
						|
      simple_command (on  ? "<command:5>CmdTX<parameters:0>" : "<command:5>CmdRX<parameters:0>");
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      wrapped_->ptt (on);
 | 
						|
    }
 | 
						|
 | 
						|
  update_PTT (on);
 | 
						|
 | 
						|
  do_frequency (state ().frequency ()); // gets Commander synchronized
 | 
						|
}
 | 
						|
 | 
						|
void DXLabSuiteCommanderTransceiver::do_frequency (Frequency f)
 | 
						|
{
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
  qDebug () << "DXLabSuiteCommanderTransceiver::do_frequency:" << f << state ();
 | 
						|
#endif
 | 
						|
 | 
						|
  // number is localised
 | 
						|
  // avoid floating point translation errors by adding a small number (0.1Hz)
 | 
						|
  simple_command ("<command:10>CmdSetFreq<parameters:23><xcvrfreq:10>" + QString ("%L1").arg (f / 1e3 + 1e-4, 10, 'f', 3).toLocal8Bit ());
 | 
						|
  update_rx_frequency (f);
 | 
						|
}
 | 
						|
 | 
						|
void DXLabSuiteCommanderTransceiver::do_tx_frequency (Frequency tx, bool /* rationalise_mode */)
 | 
						|
{
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
  qDebug () << "DXLabSuiteCommanderTransceiver::do_tx_frequency:" << tx << state ();
 | 
						|
#endif
 | 
						|
 | 
						|
  if (tx)
 | 
						|
    {
 | 
						|
      simple_command ("<command:8>CmdSplit<parameters:7><1:2>on");
 | 
						|
      update_split (true);
 | 
						|
 | 
						|
      // number is localised
 | 
						|
      // avoid floating point translation errors by adding a small number (0.1Hz)
 | 
						|
 | 
						|
      // set TX frequency after going split because going split
 | 
						|
      // rationalises TX VFO mode and that can change the frequency on
 | 
						|
      // Yaesu rigs if CW is involved
 | 
						|
      simple_command ("<command:12>CmdSetTxFreq<parameters:23><xcvrfreq:10>" + QString ("%L1").arg (tx / 1e3 + 1e-4, 10, 'f', 3).toLocal8Bit ());
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      simple_command ("<command:8>CmdSplit<parameters:8><1:3>off");
 | 
						|
    }
 | 
						|
  update_other_frequency (tx);
 | 
						|
 | 
						|
  do_frequency (state ().frequency ()); // gets Commander synchronized
 | 
						|
}
 | 
						|
 | 
						|
void DXLabSuiteCommanderTransceiver::do_mode (MODE mode, bool /* rationalise */)
 | 
						|
{
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
  qDebug () << "DXLabSuiteCommanderTransceiver::do_mode:" << mode << state ();
 | 
						|
#endif
 | 
						|
 | 
						|
  auto mapped = map_mode (mode);
 | 
						|
  simple_command ((QString ("<command:10>CmdSetMode<parameters:%1><1:%2>").arg (5 + mapped.size ()).arg (mapped.size ()) + mapped).toLocal8Bit ());
 | 
						|
 | 
						|
  if (state ().split ())
 | 
						|
    {
 | 
						|
      // this toggle ensures that the TX VFO mode is the same as the RX VFO
 | 
						|
      simple_command ("<command:8>CmdSplit<parameters:8><1:3>off");
 | 
						|
      simple_command ("<command:8>CmdSplit<parameters:7><1:2>on");
 | 
						|
    }
 | 
						|
 | 
						|
  do_frequency (state ().frequency ()); // gets Commander synchronized
 | 
						|
 | 
						|
  // setting TX frequency rationalises the mode on Icoms so get current and set
 | 
						|
  poll ();
 | 
						|
}
 | 
						|
 | 
						|
void DXLabSuiteCommanderTransceiver::poll ()
 | 
						|
{
 | 
						|
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
 | 
						|
  bool quiet {false};
 | 
						|
#else
 | 
						|
  bool quiet {true};
 | 
						|
#endif
 | 
						|
 | 
						|
  auto reply = command_with_reply ("<command:11>CmdSendFreq<parameters:0>", quiet);
 | 
						|
  if (0 == reply.indexOf ("<CmdFreq:"))
 | 
						|
    {
 | 
						|
      // remove thousands separator and DP - relies of n.nnn kHz
 | 
						|
      // format so we can do uint conversion
 | 
						|
      reply = reply.mid (reply.indexOf ('>') + 1).replace (",", "").replace (".", "");
 | 
						|
 | 
						|
      if (!state ().ptt ()) // Commander is not reliable on frequency
 | 
						|
        										// polls while transmitting
 | 
						|
        {
 | 
						|
          update_rx_frequency (reply.toUInt ());
 | 
						|
        }
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
      qDebug () << "DXLabSuiteCommanderTransceiver::poll: get frequency unexpected response";
 | 
						|
#endif
 | 
						|
 | 
						|
      throw error {tr ("DX Lab Suite Commander didn't respond correctly polling frequency")};
 | 
						|
    }
 | 
						|
 | 
						|
  reply = command_with_reply ("<command:13>CmdSendTXFreq<parameters:0>", quiet);
 | 
						|
  if (0 == reply.indexOf ("<CmdTXFreq:"))
 | 
						|
    {
 | 
						|
      // remove thousands separator and DP - relies of n.nnn kHz format so we ca do uint conversion
 | 
						|
      auto text = reply.mid (reply.indexOf ('>') + 1).replace (",", "").replace (".", "");
 | 
						|
      if ("000" != text)
 | 
						|
        {
 | 
						|
          update_other_frequency (text.toUInt ());
 | 
						|
        }
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
      qDebug () << "DXLabSuiteCommanderTransceiver::poll: get tx frequency unexpected response";
 | 
						|
#endif
 | 
						|
 | 
						|
      throw error {tr ("DX Lab Suite Commander didn't respond correctly polling TX frequency")};
 | 
						|
    }
 | 
						|
 | 
						|
  reply = command_with_reply ("<command:12>CmdSendSplit<parameters:0>", quiet);
 | 
						|
  if (0 == reply.indexOf ("<CmdSplit:"))
 | 
						|
    {
 | 
						|
      auto split = reply.mid (reply.indexOf ('>') + 1);
 | 
						|
      if ("ON" == split)
 | 
						|
        {
 | 
						|
          update_split (true);
 | 
						|
        }
 | 
						|
      else if ("OFF" == split)
 | 
						|
        {
 | 
						|
          update_split (false);
 | 
						|
        }
 | 
						|
      else
 | 
						|
        {
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
          qDebug () << "DXLabSuiteCommanderTransceiver::poll: unexpected split state" << split;
 | 
						|
#endif
 | 
						|
 | 
						|
          throw error {tr ("DX Lab Suite Commander sent an unrecognised split state: ") + split};
 | 
						|
        }
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
      qDebug () << "DXLabSuiteCommanderTransceiver::poll: get split mode unexpected response";
 | 
						|
#endif
 | 
						|
 | 
						|
      throw error {tr ("DX Lab Suite Commander didn't respond correctly polling split status")};
 | 
						|
    }
 | 
						|
 | 
						|
  reply = command_with_reply ("<command:11>CmdSendMode<parameters:0>", quiet);
 | 
						|
  if (0 == reply.indexOf ("<CmdMode:"))
 | 
						|
    {
 | 
						|
      auto mode = reply.mid (reply.indexOf ('>') + 1);
 | 
						|
      MODE m {UNK};
 | 
						|
      if ("AM" == mode)
 | 
						|
        {
 | 
						|
          m = AM;
 | 
						|
        }
 | 
						|
      else if ("CW" == mode)
 | 
						|
        {
 | 
						|
          m = CW;
 | 
						|
        }
 | 
						|
      else if ("CW-R" == mode)
 | 
						|
        {
 | 
						|
          m = CW_R;
 | 
						|
        }
 | 
						|
      else if ("FM" == mode || "WBFM" == mode)
 | 
						|
        {
 | 
						|
          m = FM;
 | 
						|
        }
 | 
						|
      else if ("LSB" == mode)
 | 
						|
        {
 | 
						|
          m = LSB;
 | 
						|
        }
 | 
						|
      else if ("USB" == mode)
 | 
						|
        {
 | 
						|
          m = USB;
 | 
						|
        }
 | 
						|
      else if ("RTTY" == mode)
 | 
						|
        {
 | 
						|
          m = FSK;
 | 
						|
        }
 | 
						|
      else if ("RTTY-R" == mode)
 | 
						|
        {
 | 
						|
          m = FSK_R;
 | 
						|
        }
 | 
						|
      else if ("PKT" == mode || "DATA-L" == mode || "Data-L" == mode)
 | 
						|
        {
 | 
						|
          m = DIG_L;
 | 
						|
        }
 | 
						|
      else if ("PKT-R" == mode || "DATA-U" == mode || "Data-U" == mode)
 | 
						|
        {
 | 
						|
          m = DIG_U;
 | 
						|
        }
 | 
						|
      else
 | 
						|
        {
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
          qDebug () << "DXLabSuiteCommanderTransceiver::poll: unexpected mode name" << mode;
 | 
						|
#endif
 | 
						|
 | 
						|
          throw error {tr ("DX Lab Suite Commander sent an unrecognised mode: ") + mode};
 | 
						|
        }
 | 
						|
      update_mode (m);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
      qDebug () << "DXLabSuiteCommanderTransceiver::poll: unexpected response";
 | 
						|
#endif
 | 
						|
 | 
						|
      throw error {tr ("DX Lab Suite Commander didn't respond correctly polling mode")};
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void DXLabSuiteCommanderTransceiver::simple_command (QByteArray const& cmd, bool no_debug)
 | 
						|
{
 | 
						|
  Q_ASSERT (commander_);
 | 
						|
 | 
						|
  if (!no_debug)
 | 
						|
    {
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
      qDebug () << "DXLabSuiteCommanderTransceiver:simple_command(" << cmd << ')';
 | 
						|
#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 WSJT_TRACE_CAT
 | 
						|
      qDebug () << "DXLabSuiteCommanderTransceiver::simple_command failed:" << commander_->errorString ();
 | 
						|
#endif
 | 
						|
 | 
						|
      throw error {tr ("DX Lab Suite Commander send command failed\n") + commander_->errorString ()};
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
QByteArray DXLabSuiteCommanderTransceiver::command_with_reply (QByteArray const& cmd, bool no_debug)
 | 
						|
{
 | 
						|
  Q_ASSERT (commander_);
 | 
						|
 | 
						|
  if (QTcpSocket::ConnectedState != commander_->state ())
 | 
						|
    {
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
      qDebug () << "DXLabSuiteCommanderTransceiver::command_with_reply failed:" << commander_->errorString ();
 | 
						|
#endif
 | 
						|
 | 
						|
      throw error {tr ("DX Lab Suite Commander read reply failed\n") + commander_->errorString ()};
 | 
						|
    }
 | 
						|
 | 
						|
  commander_->write (cmd);
 | 
						|
  if (!commander_->waitForBytesWritten (socket_wait_time) || 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 ()};
 | 
						|
    }
 | 
						|
 | 
						|
  if (!commander_->waitForReadyRead (socket_wait_time))
 | 
						|
    {
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
      qDebug () << "DXLabSuiteCommanderTransceiver::command_with_reply failed:" << commander_->errorString ();
 | 
						|
#endif
 | 
						|
 | 
						|
      throw error {tr ("DX Lab Suite Commander read reply failed\n") + commander_->errorString ()};
 | 
						|
    }
 | 
						|
 | 
						|
  auto result = commander_->readAll ();
 | 
						|
 | 
						|
  if (!no_debug)
 | 
						|
    {
 | 
						|
#if WSJT_TRACE_CAT
 | 
						|
      qDebug () << "DXLabSuiteCommanderTransceiver:command_with_reply(" << cmd << ") ->" << result;
 | 
						|
#endif
 | 
						|
    }
 | 
						|
 | 
						|
  return result;
 | 
						|
}
 |