| 142 | // ── Direct TGXL connection (port 9010) ────────────────────────────────────── |
| 143 | |
| 144 | void TunerModel::setDirectConnection(TgxlConnection* conn) |
| 145 | { |
| 146 | if (m_directConn == conn) return; |
| 147 | if (m_directConn) { |
| 148 | disconnect(m_directConn, nullptr, this, nullptr); |
| 149 | } |
| 150 | m_directConn = conn; |
| 151 | if (m_directConn) { |
| 152 | connect(m_directConn, &TgxlConnection::connected, this, [this]() { |
| 153 | qCDebug(lcTuner) << "TunerModel: direct TGXL connection established"; |
| 154 | bool wasPres = isPresent(); |
| 155 | m_directPresence = true; |
| 156 | if (!wasPres) |
| 157 | emit presenceChanged(true); |
| 158 | emit directConnectionChanged(true); |
| 159 | }); |
| 160 | connect(m_directConn, &TgxlConnection::disconnected, this, [this]() { |
| 161 | qCDebug(lcTuner) << "TunerModel: direct TGXL connection lost"; |
| 162 | m_directPresence = false; |
| 163 | if (!isPresent()) |
| 164 | emit presenceChanged(false); |
| 165 | emit directConnectionChanged(false); |
| 166 | }); |
| 167 | // Update relay values from direct state pushes |
| 168 | connect(m_directConn, &TgxlConnection::stateUpdated, this, |
| 169 | [this](const QMap<QString, QString>& kvs) { |
| 170 | bool changed = false; |
| 171 | if (kvs.contains("relayC1")) { |
| 172 | int v = kvs.value("relayC1").toInt(); |
| 173 | if (m_relayC1 != v) { m_relayC1 = v; changed = true; } |
| 174 | } |
| 175 | if (kvs.contains("relayL")) { |
| 176 | int v = kvs.value("relayL").toInt(); |
| 177 | if (m_relayL != v) { m_relayL = v; changed = true; } |
| 178 | } |
| 179 | if (kvs.contains("relayC2")) { |
| 180 | int v = kvs.value("relayC2").toInt(); |
| 181 | if (m_relayC2 != v) { m_relayC2 = v; changed = true; } |
| 182 | } |
| 183 | if (kvs.contains("antA")) { |
| 184 | int v = kvs.value("antA").toInt(); |
| 185 | if (m_antennaA != v) { m_antennaA = v; changed = true; emit antennaAChanged(v); } |
| 186 | } |
| 187 | if (changed) emit stateChanged(); |
| 188 | // Forward power and SWR from direct TGXL connection (#625) |
| 189 | // TGXL reports fwd in dBm and swr as return loss (negative dB). |
| 190 | // Convert to watts and SWR ratio for the gauge. |
| 191 | // Always emit when meter fields are present — suppressing identical |
| 192 | // values caused meter-freeze when SWR settled to exactly 1.0 (#1530). |
| 193 | bool meters = false; |
| 194 | if (kvs.contains("fwd")) { |
| 195 | float dBm = kvs.value("fwd").toFloat(); |
| 196 | float watts = std::pow(10.0f, dBm / 10.0f) / 1000.0f; |
| 197 | m_fwdPower = watts; |
| 198 | meters = true; |
| 199 | } |
| 200 | if (kvs.contains("swr")) { |
| 201 | float rl = kvs.value("swr").toFloat(); // return loss in dB (negative from TGXL) |
no test coverage detected