1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
|
#include "WSJTXMessageMapper.h"
#include "JS8_UI/mainwindow.h"
#include <QLoggingCategory>
#include <limits>
Q_LOGGING_CATEGORY(wsjtx_mapper_js8, "wsjtx.mapper.js8", QtWarningMsg)
/**
* @brief Construct a WSJT-X message mapper
*
* Sets up signal connections to handle incoming WSJT-X protocol messages
* and map them to JS8Call actions.
*
* @param client WSJT-X message client to send messages through
* @param main_window Main window instance for accessing JS8Call state
* @param parent Parent QObject
*/
WSJTXMessageMapper::WSJTXMessageMapper(WSJTXMessageClient *client,
MainWindow *main_window, QObject *parent)
: QObject{parent}, client_{client}, main_window_{main_window} {
connect(client_, &WSJTXMessageClient::reply, this,
&WSJTXMessageMapper::handleReply);
connect(client_, &WSJTXMessageClient::free_text, this,
&WSJTXMessageMapper::handleFreeText);
connect(client_, &WSJTXMessageClient::halt_tx, this,
&WSJTXMessageMapper::handleHaltTx);
connect(client_, &WSJTXMessageClient::location, this,
&WSJTXMessageMapper::handleLocation);
}
/**
* @brief Send a Status update message
*
* Maps JS8Call's status information to WSJT-X Status message format and
* sends it through the WSJT-X message client.
*
* @param dial_freq Dial frequency (Hz)
* @param offset Frequency offset (Hz)
* @param mode Operating mode string
* @param dx_call DX station callsign (selected station)
* @param de_call My callsign
* @param de_grid My grid square
* @param dx_grid DX station grid square
* @param tx_enabled Whether TX is enabled
* @param transmitting Whether currently transmitting
* @param decoding Whether currently decoding
* @param tx_message Current TX message text
*/
void WSJTXMessageMapper::sendStatusUpdate(
Radio::Frequency dial_freq, Radio::Frequency offset, QString const &mode,
QString const &dx_call, QString const &de_call, QString const &de_grid,
QString const &dx_grid, bool tx_enabled, bool transmitting, bool decoding,
QString const &tx_message) {
qCDebug(wsjtx_mapper_js8)
<< "WSJTXMessageMapper: sendStatusUpdate called"
<< "dial_freq:" << dial_freq << "offset:" << offset << "mode:" << mode
<< "dx_call:" << dx_call << "de_call:" << de_call
<< "de_grid:" << de_grid << "dx_grid:" << dx_grid
<< "tx_enabled:" << tx_enabled << "transmitting:" << transmitting
<< "decoding:" << decoding;
Radio::Frequency freq = dial_freq + offset;
QString submode = mode; // JS8Call submode
bool fast_mode = false; // Map from JS8Call speed
quint8 special_op_mode = 0; // NONE
quint32 frequency_tolerance = std::numeric_limits<quint32>::max();
quint32 tr_period = std::numeric_limits<quint32>::max();
QString configuration_name = "";
client_->status_update(
freq, mode, dx_call, "", mode, tx_enabled, transmitting, decoding,
static_cast<quint32>(offset), static_cast<quint32>(offset), de_call,
de_grid, dx_grid, false, submode, fast_mode, special_op_mode,
frequency_tolerance, tr_period, configuration_name, tx_message);
}
/**
* @brief Send a Decode message
*
* Maps JS8Call's decode information to WSJT-X Decode message format and
* sends it through the WSJT-X message client.
*
* @param is_new Whether this is a new decode
* @param time Decode time
* @param snr Signal-to-noise ratio (dB)
* @param delta_time Time offset from expected time (seconds)
* @param delta_frequency Frequency offset from nominal (Hz)
* @param mode Operating mode string
* @param message Decoded message text
* @param low_confidence Whether decode confidence is low
*/
void WSJTXMessageMapper::sendDecode(bool is_new, QTime time, qint32 snr,
float delta_time, quint32 delta_frequency,
QString const &mode, QString const &message,
bool low_confidence) {
qCDebug(wsjtx_mapper_js8)
<< "WSJTXMessageMapper: sendDecode called"
<< "is_new:" << is_new << "time:" << time.toString("hh:mm:ss")
<< "snr:" << snr << "delta_time:" << delta_time
<< "delta_frequency:" << delta_frequency << "mode:" << mode
<< "message:" << message << "low_confidence:" << low_confidence;
client_->decode(is_new, time, snr, delta_time, delta_frequency, mode,
message, low_confidence, false);
}
/**
* @brief Send a QSO Logged message
*
* Maps JS8Call's QSO log information to WSJT-X QSOLogged message format and
* sends it through the WSJT-X message client.
*
* @param time_off QSO end time
* @param dx_call DX station callsign
* @param dx_grid DX station grid square
* @param dial_frequency Dial frequency (Hz)
* @param mode Operating mode
* @param report_sent Report sent to DX station
* @param report_received Report received from DX station
* @param my_call My callsign
* @param my_grid My grid square
*/
void WSJTXMessageMapper::sendQSOLogged(
QDateTime time_off, QString const &dx_call, QString const &dx_grid,
Radio::Frequency dial_frequency, QString const &mode,
QString const &report_sent, QString const &report_received,
QString const &my_call, QString const &my_grid) {
qCDebug(wsjtx_mapper_js8)
<< "WSJTXMessageMapper: sendQSOLogged called"
<< "time_off:" << time_off.toString(Qt::ISODate)
<< "dx_call:" << dx_call << "dx_grid:" << dx_grid
<< "dial_frequency:" << dial_frequency << "mode:" << mode
<< "report_sent:" << report_sent
<< "report_received:" << report_received << "my_call:" << my_call
<< "my_grid:" << my_grid;
QDateTime time_on = time_off; // JS8Call doesn't track time_on separately
QString operator_call = "";
QString exchange_sent = "";
QString exchange_rcvd = "";
QString propmode = "";
client_->qso_logged(time_off, dx_call, dx_grid, dial_frequency, mode,
report_sent, report_received, "", "", "", time_on,
operator_call, my_call, my_grid, exchange_sent,
exchange_rcvd, propmode);
}
/**
* @brief Handle incoming Reply message from WSJT-X protocol
*
* Maps WSJT-X Reply message to JS8Call action. This would trigger a reply
* in JS8Call similar to double-clicking a decode.
*
* @param time Reply time (unused)
* @param snr Signal-to-noise ratio (unused)
* @param delta_time Time offset (unused)
* @param delta_frequency Frequency offset (unused)
* @param mode Operating mode (unused)
* @param message_text Reply message text (unused)
* @param low_confidence Whether decode confidence is low (unused)
* @param modifiers Message modifiers (unused)
*/
void WSJTXMessageMapper::handleReply(QTime /*time*/, qint32 /*snr*/,
float /*delta_time*/,
quint32 /*delta_frequency*/,
QString const & /*mode*/,
QString const & /*message_text*/,
bool /*low_confidence*/,
quint8 /*modifiers*/) {
// Map WSJT-X Reply to JS8Call action
// This would trigger a reply in JS8Call similar to double-clicking a decode
// Implementation depends on MainWindow API - for now, just send as network
// message
if (main_window_) {
// TODO: Map to appropriate JS8Call action
// main_window_->sendNetworkMessage("REPLY", message_text);
}
}
/**
* @brief Handle incoming Free Text message from WSJT-X protocol
*
* Maps WSJT-X Free Text message to JS8Call TX.SET_TEXT and optionally
* TX.SEND_MESSAGE network messages.
*
* @param text Free text to send
* @param send Whether to send immediately
*/
void WSJTXMessageMapper::handleFreeText(QString const &text, bool send) {
// Map to JS8Call TX.SET_TEXT message
if (main_window_) {
main_window_->sendNetworkMessage("TX.SET_TEXT", text);
if (send) {
main_window_->sendNetworkMessage("TX.SEND_MESSAGE", text);
}
}
}
/**
* @brief Handle incoming Halt TX message from WSJT-X protocol
*
* Maps WSJT-X Halt TX message to JS8Call TX halt action.
*
* @param auto_only If true, only halt auto sequences
*/
void WSJTXMessageMapper::handleHaltTx(bool auto_only) {
// Stop transmission
if (main_window_ && !auto_only) {
// TODO: Stop TX immediately
// main_window_->sendNetworkMessage("TX.HALT", "");
}
}
/**
* @brief Handle incoming Location message from WSJT-X protocol
*
* Maps WSJT-X Location message to JS8Call STATION.SET_GRID network message.
*
* @param location Grid square or location string
*/
void WSJTXMessageMapper::handleLocation(QString const &location) {
// Map to JS8Call STATION.SET_GRID
if (main_window_) {
main_window_->sendNetworkMessage("STATION.SET_GRID", location);
}
}
|