| 737 | } |
| 738 | |
| 739 | void MainWindow::startFreeDvReporting(int sliceId) |
| 740 | { |
| 741 | #ifndef HAVE_WEBSOCKETS |
| 742 | // RADE without WebSockets: reporter client doesn't exist, no-op. (#2204) |
| 743 | Q_UNUSED(sliceId); |
| 744 | #else |
| 745 | if (!m_freedvClient) return; |
| 746 | |
| 747 | auto& cs = AppSettings::instance(); |
| 748 | |
| 749 | // Callsign: prefer radio-stored value if "Use radio" is set and it's populated. |
| 750 | QString callsign; |
| 751 | if (cs.value("FreeDvUseRadioCallsign", "True").toString() == "True" |
| 752 | && !m_radioModel.callsign().isEmpty()) { |
| 753 | callsign = m_radioModel.callsign(); |
| 754 | } else { |
| 755 | callsign = cs.value("FreeDvMyCallsign", "").toString().trimmed().toUpper(); |
| 756 | } |
| 757 | |
| 758 | // Grid: GPS (if hardware present, locked, and user prefers it), else user-saved. |
| 759 | QString grid; |
| 760 | if (cs.value("FreeDvUseGpsGrid", "True").toString() == "True" |
| 761 | && m_radioModel.hasGpsHardware() |
| 762 | && !m_radioModel.gpsGrid().isEmpty()) { |
| 763 | grid = m_radioModel.gpsGrid(); |
| 764 | } else { |
| 765 | grid = cs.value("FreeDvMyGrid", "").toString().trimmed().toUpper(); |
| 766 | } |
| 767 | |
| 768 | // Refuse to broadcast placeholder data to the public FreeDV Reporter |
| 769 | // map — the dialog already validates this when the user toggles the |
| 770 | // checkbox, but RADE auto-activation can hit this path without going |
| 771 | // through the toggle, so guard here too. |
| 772 | if (callsign.isEmpty() || grid.isEmpty()) { |
| 773 | qCWarning(lcDxCluster) |
| 774 | << "FreeDvReporting: refusing to enable — callsign or grid empty" |
| 775 | << "(callsign='" << callsign << "', grid='" << grid << "')"; |
| 776 | return; |
| 777 | } |
| 778 | |
| 779 | const QString message = cs.value("FreeDvMyMessage", "").toString(); |
| 780 | const QString swVer = QString("AetherSDR %1").arg(QCoreApplication::applicationVersion()); |
| 781 | const double freqMhz = m_radioModel.slice(sliceId) |
| 782 | ? m_radioModel.slice(sliceId)->frequency() : 0.0; |
| 783 | |
| 784 | // Auto-start the WebSocket connection if not already running — reporting is |
| 785 | // independent of the user's FreeDV spot subscription. |
| 786 | if (!m_freedvClient->isConnected()) |
| 787 | QMetaObject::invokeMethod(m_freedvClient, [this] { m_freedvClient->startConnection(); }); |
| 788 | |
| 789 | QMetaObject::invokeMethod(m_freedvClient, |
| 790 | [this, callsign, grid, message, swVer, freqMhz] { |
| 791 | m_freedvClient->enableReporting(callsign, grid, message, swVer, freqMhz); |
| 792 | }); |
| 793 | |
| 794 | // TX report: evaluate tune/ATU guard on the main thread so we never report |
| 795 | // a tune or ATU cycle as a voice transmission. |
| 796 | m_freedvMoxConn = connect(&m_radioModel.transmitModel(), &TransmitModel::moxChanged, |
nothing calls this directly
no test coverage detected