feat(color,cpn): Updates to the model telemetry page, sensor ID consistency (#3401)

* Add 'Show Instance ID' button to telemetry page to show/hide sensor instance number (default is hidden).
Fix issues with page refresh when all sensors deleted.
Select closest sensor when a single sensor is deleted.
On change, only refresh the sensor list instead of the whole page.
The 'showInstanceIds' property is saved to the model file.
Update Companion to save/load 'showInstanceIds' in model YAML file. Add checkbox to telemetry edit page.

* Update all radio specific files.

* Keep focus on 'Discover/Stop' button when searching for new sensors.
Start sensor ID index at 1 to match B&W radios.
Keep focus on changed parameter when editing sensor, don't rebuild entire parameter list on change.

* Display actual 'instance' ID instead of 'instance' + 1.

* Fix incorrect ID when reloading simulator data.

* Fix incorrect ID when reloading simulator data on B&W radios.
This commit is contained in:
philmoz
2023-04-17 18:44:44 +10:00
committed by GitHub
parent 7bf6dbba0f
commit 6985d3f24b
49 changed files with 559 additions and 345 deletions
@@ -811,6 +811,7 @@ Node convert<ModelData>::encode(const ModelData& rhs)
node["trimInc"] = rhs.trimInc;
node["displayTrims"] = rhs.trimsDisplay;
node["ignoreSensorIds"] = (int)rhs.frsky.ignoreSensorIds;
node["showInstanceIds"] = (int)rhs.showInstanceIds;
node["disableThrottleWarning"] = (int)rhs.disableThrottleWarning;
node["enableCustomThrottleWarning"] = (int)rhs.enableCustomThrottleWarning;
node["customThrottleWarningPosition"] = (int)rhs.customThrottleWarningPosition;
@@ -1058,6 +1059,7 @@ bool convert<ModelData>::decode(const Node& node, ModelData& rhs)
node["trimInc"] >> rhs.trimInc;
node["displayTrims"] >> rhs.trimsDisplay;
node["ignoreSensorIds"] >> rhs.frsky.ignoreSensorIds;
node["showInstanceIds"] >> rhs.showInstanceIds;
node["disableThrottleWarning"] >> rhs.disableThrottleWarning;
node["enableCustomThrottleWarning"] >> rhs.enableCustomThrottleWarning;
node["customThrottleWarningPosition"] >> rhs.customThrottleWarningPosition;
@@ -49,12 +49,7 @@ Node convert<SensorData>::encode(const SensorData& rhs)
node["id1"]["id"] = rhs.id;
node["subId"] = rhs.subid;
unsigned int instance = rhs.instance;
if (instance != 0) {
instance =
((instance - 1) & 0x1F) | (rhs.rxIdx << 5) | (rhs.moduleIdx << 7);
}
node["id2"]["instance"] = instance;
node["id2"]["instance"] = rhs.instance;
cfg["custom"]["ratio"] = rhs.ratio;
cfg["custom"]["offset"] = rhs.offset;
} else {
@@ -132,7 +127,6 @@ bool convert<SensorData>::decode(const Node& node, SensorData& rhs)
if (rhs.type == SensorData::TELEM_TYPE_CUSTOM) {
rhs.rxIdx = (rhs.instance >> 5) & 0x03; // 2 bits Rx idx
rhs.moduleIdx = (rhs.instance >> 7) & 0x1; // 1 bit module idx
rhs.instance = (rhs.instance & 0x1F) + 1; // 5 bits instance
}
node["label"] >> rhs.label;
+1
View File
@@ -171,6 +171,7 @@ class ModelData {
FrSkyData frsky;
unsigned int rssiSource;
RSSIAlarmData rssiAlarms;
bool showInstanceIds;
char bitmap[CPN_MAX_BITMAP_LEN + 1];
+1
View File
@@ -516,6 +516,7 @@ void TelemetryPanel::setup()
}
ui->telemetryProtocol->setCurrentIndex(model->telemetryProtocol);
ui->ignoreSensorIds->setField(model->frsky.ignoreSensorIds, this);
ui->showInstanceIds->setField(model->showInstanceIds, this);
ui->disableTelemetryAlarms->setField(model->rssiAlarms.disabled);
ui->rssiAlarmWarningSB->setRange(0, 127);
+8 -1
View File
@@ -963,7 +963,7 @@
<property name="flat">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="sensorsLayout" columnstretch="0">
<layout class="QGridLayout" name="sensorsLayout" columnstretch="0,0">
<property name="leftMargin">
<number>4</number>
</property>
@@ -996,6 +996,13 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="AutoCheckBox" name="showInstanceIds">
<property name="text">
<string>Show Instance IDs</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
+1
View File
@@ -820,6 +820,7 @@ QString MultiModelPrinter::printTelemetry()
}
ROWLABELCOMPARECELL(tr("Multi sensors"), 0, modelPrinter->printIgnoreSensorIds(!model->frsky.ignoreSensorIds), 0);
ROWLABELCOMPARECELL(tr("Show Instance IDs"), 0, modelPrinter->printIgnoreSensorIds(!model->showInstanceIds), 0);
// Various
columns.appendTableEnd();
+28 -28
View File
@@ -126,7 +126,7 @@ void TelemetrySimulator::stopTelemetry()
return;
uint8_t buffer[FRSKY_SPORT_PACKET_SIZE] = {0};
generateSportPacket(buffer, id - 1, DATA_FRAME, RSSI_ID, 0);
generateSportPacket(buffer, id, DATA_FRAME, RSSI_ID, 0);
emit telemetryDataChanged(QByteArray((char *)buffer, FRSKY_SPORT_PACKET_SIZE));
}
@@ -261,7 +261,7 @@ void TelemetrySimulator::onReplayRateChanged(int value)
}
}
#define SET_INSTANCE(control, id, def) ui->control->setText(QString::number(simulator->getSensorInstance(id, ((def) & 0x1F) + 1)))
#define SET_INSTANCE(control, id, def) ui->control->setText(QString::number(simulator->getSensorInstance(id, ((def) & 0x1F))))
void TelemetrySimulator::setupDataFields()
{
@@ -359,78 +359,78 @@ void TelemetrySimulator::generateTelemetryFrame()
case 1:
if (ui->rxbt->text().length()) {
generateSportPacket(buffer, ui->rxbt_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, BATT_ID, LIMIT<uint32_t>(0, ui->rxbt->value() * 255.0 / ui->rxbt_ratio->value(), 0xFFFFFFFF));
generateSportPacket(buffer, ui->rxbt_inst->text().toInt(&ok, 0), DATA_FRAME, BATT_ID, LIMIT<uint32_t>(0, ui->rxbt->value() * 255.0 / ui->rxbt_ratio->value(), 0xFFFFFFFF));
}
break;
case 2:
if (ui->Rssi->text().length())
generateSportPacket(buffer, ui->rssi_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, RSSI_ID, LIMIT<uint32_t>(0, ui->Rssi->text().toInt(&ok, 0), 0xFF));
generateSportPacket(buffer, ui->rssi_inst->text().toInt(&ok, 0), DATA_FRAME, RSSI_ID, LIMIT<uint32_t>(0, ui->Rssi->text().toInt(&ok, 0), 0xFF));
break;
case 3:
if (ui->Swr->text().length())
generateSportPacket(buffer, ui->swr_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, RAS_ID, LIMIT<uint32_t>(0, ui->Swr->text().toInt(&ok, 0), 0xFFFF));
generateSportPacket(buffer, ui->swr_inst->text().toInt(&ok, 0), DATA_FRAME, RAS_ID, LIMIT<uint32_t>(0, ui->Swr->text().toInt(&ok, 0), 0xFFFF));
break;
case 4:
if (ui->A1->value() > 0)
generateSportPacket(buffer, ui->a1_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ADC1_ID, LIMIT<uint32_t>(0, ui->A1->value() * 255.0 / ui->A1_ratio->value(), 0xFF));
generateSportPacket(buffer, ui->a1_inst->text().toInt(&ok, 0), DATA_FRAME, ADC1_ID, LIMIT<uint32_t>(0, ui->A1->value() * 255.0 / ui->A1_ratio->value(), 0xFF));
break;
case 5:
if (ui->A2->value() > 0)
generateSportPacket(buffer, ui->a2_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ADC2_ID, LIMIT<uint32_t>(0, ui->A2->value() * 255.0 / ui->A2_ratio->value(), 0xFF));
generateSportPacket(buffer, ui->a2_inst->text().toInt(&ok, 0), DATA_FRAME, ADC2_ID, LIMIT<uint32_t>(0, ui->A2->value() * 255.0 / ui->A2_ratio->value(), 0xFF));
break;
case 6:
if (ui->A3->value() != 0)
generateSportPacket(buffer, ui->a3_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, A3_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->A3->value() * 100.0, 0x7FFFFFFF));
generateSportPacket(buffer, ui->a3_inst->text().toInt(&ok, 0), DATA_FRAME, A3_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->A3->value() * 100.0, 0x7FFFFFFF));
break;
case 7:
if (ui->A4->value() != 0)
generateSportPacket(buffer, ui->a4_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, A4_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->A4->value() * 100.0, 0x7FFFFFFF));
generateSportPacket(buffer, ui->a4_inst->text().toInt(&ok, 0), DATA_FRAME, A4_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->A4->value() * 100.0, 0x7FFFFFFF));
break;
case 8:
if (ui->T1->value() != 0)
generateSportPacket(buffer, ui->t1_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, T1_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->T1->value(), 0x7FFFFFFF));
generateSportPacket(buffer, ui->t1_inst->text().toInt(&ok, 0), DATA_FRAME, T1_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->T1->value(), 0x7FFFFFFF));
break;
case 9:
if (ui->T2->value() != 0)
generateSportPacket(buffer, ui->t2_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, T2_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->T2->value(), 0x7FFFFFFF));
generateSportPacket(buffer, ui->t2_inst->text().toInt(&ok, 0), DATA_FRAME, T2_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->T2->value(), 0x7FFFFFFF));
break;
case 10:
if (ui->rpm->value() > 0)
generateSportPacket(buffer, ui->rpm_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, RPM_FIRST_ID, LIMIT<uint32_t>(0, ui->rpm->value(), 0x7FFFFFFF));
generateSportPacket(buffer, ui->rpm_inst->text().toInt(&ok, 0), DATA_FRAME, RPM_FIRST_ID, LIMIT<uint32_t>(0, ui->rpm->value(), 0x7FFFFFFF));
break;
case 11:
if (ui->fuel->value() > 0)
generateSportPacket(buffer, ui->fuel_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, FUEL_FIRST_ID, LIMIT<uint32_t>(0, ui->fuel->value(), 0xFFFF));
generateSportPacket(buffer, ui->fuel_inst->text().toInt(&ok, 0), DATA_FRAME, FUEL_FIRST_ID, LIMIT<uint32_t>(0, ui->fuel->value(), 0xFFFF));
break;
case 12:
if (ui->vspeed->value() != 0)
generateSportPacket(buffer, ui->vvspd_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, VARIO_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->vspeed->value() * 100.0, 0x7FFFFFFF));
generateSportPacket(buffer, ui->vvspd_inst->text().toInt(&ok, 0), DATA_FRAME, VARIO_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->vspeed->value() * 100.0, 0x7FFFFFFF));
break;
case 13:
if (ui->valt->value() != 0)
generateSportPacket(buffer, ui->valt_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ALT_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->valt->value() * 100.0, 0x7FFFFFFF));
generateSportPacket(buffer, ui->valt_inst->text().toInt(&ok, 0), DATA_FRAME, ALT_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->valt->value() * 100.0, 0x7FFFFFFF));
break;
case 14:
if (ui->vfas->value() != 0)
generateSportPacket(buffer, ui->fasv_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, VFAS_FIRST_ID, LIMIT<uint32_t>(0, ui->vfas->value() * 100.0, 0xFFFFFFFF));
generateSportPacket(buffer, ui->fasv_inst->text().toInt(&ok, 0), DATA_FRAME, VFAS_FIRST_ID, LIMIT<uint32_t>(0, ui->vfas->value() * 100.0, 0xFFFFFFFF));
break;
case 15:
if (ui->curr->value() != 0)
generateSportPacket(buffer, ui->fasc_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, CURR_FIRST_ID, LIMIT<uint32_t>(0, ui->curr->value() * 10.0, 0xFFFFFFFF));
generateSportPacket(buffer, ui->fasc_inst->text().toInt(&ok, 0), DATA_FRAME, CURR_FIRST_ID, LIMIT<uint32_t>(0, ui->curr->value() * 10.0, 0xFFFFFFFF));
break;
case 16:
@@ -444,7 +444,7 @@ void TelemetrySimulator::generateTelemetryFrame()
cellValues[5] = ui->cell6->value();
cellValues[6] = ui->cell7->value();
cellValues[7] = ui->cell8->value();
generateSportPacket(buffer, ui->cells_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, CELLS_FIRST_ID, flvss->setAllCells_GetNextPair(cellValues));
generateSportPacket(buffer, ui->cells_inst->text().toInt(&ok, 0), DATA_FRAME, CELLS_FIRST_ID, flvss->setAllCells_GetNextPair(cellValues));
}
else {
cellValues[0] = 0;
@@ -454,62 +454,62 @@ void TelemetrySimulator::generateTelemetryFrame()
case 17:
if (ui->aspeed->value() > 0)
generateSportPacket(buffer, ui->aspd_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, AIR_SPEED_FIRST_ID, LIMIT<uint32_t>(0, ui->aspeed->value() * 5.39957, 0xFFFFFFFF));
generateSportPacket(buffer, ui->aspd_inst->text().toInt(&ok, 0), DATA_FRAME, AIR_SPEED_FIRST_ID, LIMIT<uint32_t>(0, ui->aspeed->value() * 5.39957, 0xFFFFFFFF));
break;
case 18:
if (ui->gps_alt->value() != 0) {
gps->setGPSAltitude(ui->gps_alt->value());
generateSportPacket(buffer, ui->gpsa_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, GPS_ALT_FIRST_ID, gps->getNextPacketData(GPS_ALT_FIRST_ID));
generateSportPacket(buffer, ui->gpsa_inst->text().toInt(&ok, 0), DATA_FRAME, GPS_ALT_FIRST_ID, gps->getNextPacketData(GPS_ALT_FIRST_ID));
}
break;
case 19:
if (ui->gps_speed->value() > 0) {
gps->setGPSSpeedKMH(ui->gps_speed->value());
generateSportPacket(buffer, ui->gpss_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, GPS_SPEED_FIRST_ID, gps->getNextPacketData(GPS_SPEED_FIRST_ID));
generateSportPacket(buffer, ui->gpss_inst->text().toInt(&ok, 0), DATA_FRAME, GPS_SPEED_FIRST_ID, gps->getNextPacketData(GPS_SPEED_FIRST_ID));
}
break;
case 20:
if (ui->gps_course->value() != 0) {
gps->setGPSCourse(ui->gps_course->value());
generateSportPacket(buffer, ui->gpsc_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, GPS_COURS_FIRST_ID, gps->getNextPacketData(GPS_COURS_FIRST_ID));
generateSportPacket(buffer, ui->gpsc_inst->text().toInt(&ok, 0), DATA_FRAME, GPS_COURS_FIRST_ID, gps->getNextPacketData(GPS_COURS_FIRST_ID));
}
break;
case 21:
if (ui->gps_time->text().length()) {
gps->setGPSDateTime(ui->gps_time->text());
generateSportPacket(buffer, ui->gpst_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, GPS_TIME_DATE_FIRST_ID, gps->getNextPacketData(GPS_TIME_DATE_FIRST_ID));
generateSportPacket(buffer, ui->gpst_inst->text().toInt(&ok, 0), DATA_FRAME, GPS_TIME_DATE_FIRST_ID, gps->getNextPacketData(GPS_TIME_DATE_FIRST_ID));
}
break;
case 22:
if (ui->gps_latlon->text().length()) {
gps->setGPSLatLon(ui->gps_latlon->text());
generateSportPacket(buffer, ui->gpsll_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, GPS_LONG_LATI_FIRST_ID, gps->getNextPacketData(GPS_LONG_LATI_FIRST_ID));
generateSportPacket(buffer, ui->gpsll_inst->text().toInt(&ok, 0), DATA_FRAME, GPS_LONG_LATI_FIRST_ID, gps->getNextPacketData(GPS_LONG_LATI_FIRST_ID));
}
break;
case 23:
if (ui->accx->value() != 0)
generateSportPacket(buffer, ui->accx_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ACCX_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accx->value() * 100.0, 0x7FFFFFFF));
generateSportPacket(buffer, ui->accx_inst->text().toInt(&ok, 0), DATA_FRAME, ACCX_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accx->value() * 100.0, 0x7FFFFFFF));
break;
case 24:
if (ui->accy->value() != 0)
generateSportPacket(buffer, ui->accy_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ACCY_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accy->value() * 100.0, 0x7FFFFFFF));
generateSportPacket(buffer, ui->accy_inst->text().toInt(&ok, 0), DATA_FRAME, ACCY_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accy->value() * 100.0, 0x7FFFFFFF));
break;
case 25:
if (ui->accz->value() != 0)
generateSportPacket(buffer, ui->accz_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ACCZ_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accz->value() * 100.0, 0x7FFFFFFF));
generateSportPacket(buffer, ui->accz_inst->text().toInt(&ok, 0), DATA_FRAME, ACCZ_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accz->value() * 100.0, 0x7FFFFFFF));
break;
case 26:
if (ui->fuel_qty->value() > 0)
generateSportPacket(buffer, ui->fuel_qty_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, FUEL_QTY_FIRST_ID, LIMIT<uint32_t>(0, ui->fuel_qty->value() * 100.0, 0xFFFFFF));
generateSportPacket(buffer, ui->fuel_qty_inst->text().toInt(&ok, 0), DATA_FRAME, FUEL_QTY_FIRST_ID, LIMIT<uint32_t>(0, ui->fuel_qty->value() * 100.0, 0xFFFFFF));
break;
default: