MSP protocol implementation and settings menu
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:dmc_app/transport/loopback/loopback_transport.dart';
|
||||
import 'package:dmc_app/transport/msp/msp_client.dart';
|
||||
import 'package:dmc_app/transport/msp/msp_commands.dart';
|
||||
import 'package:dmc_app/transport/msp/msp_frame.dart';
|
||||
import 'package:dmc_app/transport/msp/msp_frame_decoder.dart';
|
||||
|
||||
MspFrame _decodeSingle(Uint8List bytes) =>
|
||||
MspFrameDecoder().addBytes(bytes).single;
|
||||
|
||||
void main() {
|
||||
late LoopbackTransport transport;
|
||||
|
||||
setUp(() async {
|
||||
transport = LoopbackTransport();
|
||||
await transport.connect();
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
transport.dispose();
|
||||
});
|
||||
|
||||
test('request() sendet einen MSPv2-Rahmen und liefert den Antwort-Payload',
|
||||
() async {
|
||||
final client = MspClient(transport);
|
||||
final future = client.request(MspCommands.altitude);
|
||||
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
expect(transport.sentData, hasLength(1));
|
||||
final sentFrame = _decodeSingle(transport.sentData.single);
|
||||
expect(sentFrame.direction, MspDirection.request);
|
||||
expect(sentFrame.function, MspCommands.altitude);
|
||||
|
||||
final payload = Uint8List.fromList([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||
transport.feed(
|
||||
encodeMspV2Frame(MspDirection.response, MspCommands.altitude, payload),
|
||||
);
|
||||
|
||||
expect(await future, payload);
|
||||
client.dispose();
|
||||
});
|
||||
|
||||
test('wirft nach Timeout + Wiederholungen MspRequestException und sendet '
|
||||
'jedes Mal erneut', () async {
|
||||
final client = MspClient(
|
||||
transport,
|
||||
requestTimeout: const Duration(milliseconds: 30),
|
||||
maxRetries: 2,
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
client.request(MspCommands.altitude),
|
||||
throwsA(isA<MspRequestException>()),
|
||||
);
|
||||
|
||||
// Erstversuch + 2 Wiederholungen = 3 gesendete Anfragen.
|
||||
expect(transport.sentData, hasLength(3));
|
||||
for (final sent in transport.sentData) {
|
||||
expect(_decodeSingle(sent).function, MspCommands.altitude);
|
||||
}
|
||||
client.dispose();
|
||||
});
|
||||
|
||||
test('Fehlerantwort (dir = \'!\') wirft sofort ohne weiteren Versuch',
|
||||
() async {
|
||||
final client = MspClient(
|
||||
transport,
|
||||
requestTimeout: const Duration(seconds: 5),
|
||||
maxRetries: 2,
|
||||
);
|
||||
|
||||
final future = client.request(MspCommands.altitude);
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
transport.feed(
|
||||
encodeMspV2Frame(MspDirection.error, MspCommands.altitude, Uint8List(0)),
|
||||
);
|
||||
|
||||
await expectLater(future, throwsA(isA<MspRequestException>()));
|
||||
expect(transport.sentData, hasLength(1));
|
||||
client.dispose();
|
||||
});
|
||||
|
||||
test('serialisiert ueberlappende Anfragen - immer nur eine offen', () async {
|
||||
final client = MspClient(transport);
|
||||
|
||||
final future1 = client.request(MspCommands.rawGps);
|
||||
final future2 = client.request(MspCommands.altitude);
|
||||
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
expect(transport.sentData, hasLength(1));
|
||||
expect(_decodeSingle(transport.sentData.single).function,
|
||||
MspCommands.rawGps);
|
||||
|
||||
transport.feed(encodeMspV2Frame(
|
||||
MspDirection.response,
|
||||
MspCommands.rawGps,
|
||||
Uint8List(18),
|
||||
));
|
||||
await future1;
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
|
||||
expect(transport.sentData, hasLength(2));
|
||||
expect(_decodeSingle(transport.sentData[1]).function,
|
||||
MspCommands.altitude);
|
||||
|
||||
transport.feed(encodeMspV2Frame(
|
||||
MspDirection.response,
|
||||
MspCommands.altitude,
|
||||
Uint8List(10),
|
||||
));
|
||||
await future2;
|
||||
|
||||
client.dispose();
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user