drone status pill in footer for fly mode implemented. footer layout and sizes homogenized
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:dmc_app/domain/telemetry/drone_status.dart';
|
||||
|
||||
void main() {
|
||||
group('computeDroneStatus - connectionQuality', () {
|
||||
test('gruen bei LQ >=70% und SNR >=0dB', () {
|
||||
final status = computeDroneStatus(
|
||||
armed: false,
|
||||
hasFix: true,
|
||||
numSat: 10,
|
||||
hdop: 1.0,
|
||||
linkQuality: 70,
|
||||
snrDb: 0,
|
||||
navMode: 0,
|
||||
);
|
||||
expect(status.connectionQuality, SignalLevel.green);
|
||||
});
|
||||
|
||||
test('gelb bei LQ >=70% aber SNR <0dB (Rauschen trotz guter LQ)', () {
|
||||
final status = computeDroneStatus(
|
||||
armed: false,
|
||||
hasFix: true,
|
||||
numSat: 10,
|
||||
hdop: 1.0,
|
||||
linkQuality: 90,
|
||||
snrDb: -1,
|
||||
navMode: 0,
|
||||
);
|
||||
expect(status.connectionQuality, SignalLevel.yellow);
|
||||
});
|
||||
|
||||
test('gelb bei LQ zwischen 50% und 70%', () {
|
||||
final status = computeDroneStatus(
|
||||
armed: false,
|
||||
hasFix: true,
|
||||
numSat: 10,
|
||||
hdop: 1.0,
|
||||
linkQuality: 60,
|
||||
snrDb: 5,
|
||||
navMode: 0,
|
||||
);
|
||||
expect(status.connectionQuality, SignalLevel.yellow);
|
||||
});
|
||||
|
||||
test('rot bei LQ <50%', () {
|
||||
final status = computeDroneStatus(
|
||||
armed: false,
|
||||
hasFix: true,
|
||||
numSat: 10,
|
||||
hdop: 1.0,
|
||||
linkQuality: 20,
|
||||
snrDb: 10,
|
||||
navMode: 0,
|
||||
);
|
||||
expect(status.connectionQuality, SignalLevel.red);
|
||||
});
|
||||
});
|
||||
|
||||
group('computeDroneStatus - positionQuality', () {
|
||||
test('gruen bei >=8 Satelliten und HDOP <2.0', () {
|
||||
final status = computeDroneStatus(
|
||||
armed: false,
|
||||
hasFix: true,
|
||||
numSat: 9,
|
||||
hdop: 1.5,
|
||||
linkQuality: 80,
|
||||
snrDb: 5,
|
||||
navMode: 0,
|
||||
);
|
||||
expect(status.positionQuality, SignalLevel.green);
|
||||
});
|
||||
|
||||
test('gelb bei >=6 Satelliten und HDOP <5.0, aber nicht gruen-Schwelle', () {
|
||||
final status = computeDroneStatus(
|
||||
armed: false,
|
||||
hasFix: true,
|
||||
numSat: 6,
|
||||
hdop: 3.0,
|
||||
linkQuality: 80,
|
||||
snrDb: 5,
|
||||
navMode: 0,
|
||||
);
|
||||
expect(status.positionQuality, SignalLevel.yellow);
|
||||
});
|
||||
|
||||
test('rot ohne GPS-Fix, unabhaengig von Satelliten/HDOP', () {
|
||||
final status = computeDroneStatus(
|
||||
armed: false,
|
||||
hasFix: false,
|
||||
numSat: 12,
|
||||
hdop: 0.5,
|
||||
linkQuality: 80,
|
||||
snrDb: 5,
|
||||
navMode: 0,
|
||||
);
|
||||
expect(status.positionQuality, SignalLevel.red);
|
||||
});
|
||||
|
||||
test('rot bei wenigen Satelliten trotz Fix', () {
|
||||
final status = computeDroneStatus(
|
||||
armed: false,
|
||||
hasFix: true,
|
||||
numSat: 3,
|
||||
hdop: 8.0,
|
||||
linkQuality: 80,
|
||||
snrDb: 5,
|
||||
navMode: 0,
|
||||
);
|
||||
expect(status.positionQuality, SignalLevel.red);
|
||||
});
|
||||
});
|
||||
|
||||
group('computeDroneStatus - state', () {
|
||||
test('error hat Vorrang, sobald navMode Emergency (15) ist', () {
|
||||
final status = computeDroneStatus(
|
||||
armed: true,
|
||||
hasFix: true,
|
||||
numSat: 10,
|
||||
hdop: 1.0,
|
||||
linkQuality: 80,
|
||||
snrDb: 5,
|
||||
navMode: 15,
|
||||
);
|
||||
expect(status.state, DroneState.error);
|
||||
});
|
||||
|
||||
test('waypoint, wenn armed und navMode Waypoint mission (3)', () {
|
||||
final status = computeDroneStatus(
|
||||
armed: true,
|
||||
hasFix: true,
|
||||
numSat: 10,
|
||||
hdop: 1.0,
|
||||
linkQuality: 80,
|
||||
snrDb: 5,
|
||||
navMode: 3,
|
||||
);
|
||||
expect(status.state, DroneState.waypoint);
|
||||
});
|
||||
|
||||
test('armed, wenn armed aber kein Waypoint-Modus (z.B. Hold)', () {
|
||||
final status = computeDroneStatus(
|
||||
armed: true,
|
||||
hasFix: true,
|
||||
numSat: 10,
|
||||
hdop: 1.0,
|
||||
linkQuality: 80,
|
||||
snrDb: 5,
|
||||
navMode: 1,
|
||||
);
|
||||
expect(status.state, DroneState.armed);
|
||||
});
|
||||
|
||||
test('ready, wenn nicht armed aber GPS-Fix vorhanden', () {
|
||||
final status = computeDroneStatus(
|
||||
armed: false,
|
||||
hasFix: true,
|
||||
numSat: 10,
|
||||
hdop: 1.0,
|
||||
linkQuality: 80,
|
||||
snrDb: 5,
|
||||
navMode: 0,
|
||||
);
|
||||
expect(status.state, DroneState.ready);
|
||||
});
|
||||
|
||||
test('idle, wenn nicht armed und kein GPS-Fix', () {
|
||||
final status = computeDroneStatus(
|
||||
armed: false,
|
||||
hasFix: false,
|
||||
numSat: 0,
|
||||
hdop: 99.99,
|
||||
linkQuality: 80,
|
||||
snrDb: 5,
|
||||
navMode: 0,
|
||||
);
|
||||
expect(status.state, DroneState.idle);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -33,6 +33,7 @@ Timer _startFakeFlightController(
|
||||
d.setInt32(6, 134050000, Endian.little); // lon 13.405
|
||||
d.setUint16(12, 500, Endian.little); // 5.00 m/s
|
||||
d.setUint16(14, 2700, Endian.little); // 270.0 deg
|
||||
d.setUint16(16, 150, Endian.little); // HDOP 1.50
|
||||
payload = d.buffer.asUint8List();
|
||||
case MspCommands.altitude:
|
||||
final d = ByteData(10);
|
||||
@@ -52,6 +53,7 @@ Timer _startFakeFlightController(
|
||||
case MspCommands.inavLinkStats:
|
||||
final d = ByteData(3);
|
||||
d.setUint8(1, 88); // Linkqualitaet %
|
||||
d.setInt8(2, 6); // SNR 6 dB
|
||||
payload = d.buffer.asUint8List();
|
||||
default:
|
||||
payload = Uint8List(0);
|
||||
@@ -88,6 +90,9 @@ void main() {
|
||||
expect(frame.headingDeg, closeTo(270.0, 1e-6));
|
||||
expect(frame.batteryPercent, 77);
|
||||
expect(frame.linkQuality, 88);
|
||||
expect(frame.snrDb, 6);
|
||||
expect(frame.hdop, closeTo(1.5, 1e-9));
|
||||
expect(frame.navMode, 3);
|
||||
expect(frame.flightMode, 'Waypoint mission (en route to WP)');
|
||||
// Fake-FC meldet activeWpNumber=3 (1-basiert) - als 0-basierter Index
|
||||
// in die App-eigene Wegpunktliste entspricht das Index 2.
|
||||
|
||||
@@ -6,10 +6,10 @@ import 'package:dmc_app/transport/msp/msp_telemetry_codec.dart';
|
||||
|
||||
void main() {
|
||||
group('parseMspRawGps', () {
|
||||
test('parst fixType, numSat, lat/lon (1e-7 deg) und Speed (cm/s)', () {
|
||||
test('parst fixType, numSat, lat/lon (1e-7 deg), Speed (cm/s) und HDOP', () {
|
||||
// fixType=2, numSat=9, lat=52.5200000 deg, lon=13.4050000 deg,
|
||||
// alt=100m (ungenutzt), groundSpeed=1234 cm/s, groundCourse=900 (0.1deg,
|
||||
// ungenutzt), hdop=120 (ungenutzt).
|
||||
// ungenutzt), hdop=120 (/100 = 1.2).
|
||||
final data = ByteData(18);
|
||||
data.setUint8(0, 2);
|
||||
data.setUint8(1, 9);
|
||||
@@ -29,6 +29,7 @@ void main() {
|
||||
expect(reading.lon, closeTo(13.405, 1e-9));
|
||||
expect(reading.speedMs, closeTo(12.34, 1e-9));
|
||||
expect(reading.headingDeg, closeTo(90.0, 1e-9));
|
||||
expect(reading.hdop, closeTo(1.2, 1e-9));
|
||||
});
|
||||
|
||||
test('fixType 0 bedeutet kein Fix', () {
|
||||
@@ -142,4 +143,20 @@ void main() {
|
||||
expect(parseMspLinkQuality(payload), 87);
|
||||
});
|
||||
});
|
||||
|
||||
group('parseMspLinkStatsSnr', () {
|
||||
test('liest positives SNR an Offset 2', () {
|
||||
final payload = Uint8List(3);
|
||||
payload[2] = 12;
|
||||
expect(parseMspLinkStatsSnr(payload), 12);
|
||||
});
|
||||
|
||||
test('liest negatives SNR (vorzeichenbehaftetes Byte) an Offset 2', () {
|
||||
// -5 dB als uint8 geschrieben (fc_msp.c: (uint8_t)rxLinkStatistics.
|
||||
// uplinkSNR) entspricht 251 (256-5).
|
||||
final payload = Uint8List(3);
|
||||
payload[2] = 251;
|
||||
expect(parseMspLinkStatsSnr(payload), -5);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user