From 0b42f7e9c55c4c36ec6675df67686246e69d5e8a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 7 Nov 2025 18:11:18 +0000 Subject: [PATCH 2/4] Fix Elite Square button detection logic and add tests Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com> --- lib/bluetooth/devices/elite/elite_square.dart | 8 +- test/elite_square_test.dart | 146 ++++++++++++++++++ 2 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 test/elite_square_test.dart diff --git a/lib/bluetooth/devices/elite/elite_square.dart b/lib/bluetooth/devices/elite/elite_square.dart index faccf40..0e6d9bf 100644 --- a/lib/bluetooth/devices/elite/elite_square.dart +++ b/lib/bluetooth/devices/elite/elite_square.dart @@ -40,11 +40,11 @@ class EliteSquare extends BluetoothDevice { actionStreamInternal.add(LogNotification('Received $fullValue - vs $currentValue (last: $_lastValue)')); if (_lastValue != null) { - final currentRelevantPart = fullValue.length >= 19 - ? fullValue.substring(6, fullValue.length - 13) + final currentRelevantPart = fullValue.length >= 14 + ? fullValue.substring(6, 14) : fullValue.substring(6); - final lastRelevantPart = _lastValue!.length >= 19 - ? _lastValue!.substring(6, _lastValue!.length - 13) + final lastRelevantPart = _lastValue!.length >= 14 + ? _lastValue!.substring(6, 14) : _lastValue!.substring(6); if (currentRelevantPart != lastRelevantPart) { diff --git a/test/elite_square_test.dart b/test/elite_square_test.dart new file mode 100644 index 0000000..4e7b28c --- /dev/null +++ b/test/elite_square_test.dart @@ -0,0 +1,146 @@ +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('Elite Square Button Detection Tests', () { + test('Should extract correct button code from hex string', () { + // Test button code extraction + String extractButtonCode(String hexValue) { + if (hexValue.length >= 14) { + return hexValue.substring(6, 14); + } + return hexValue; + } + + // Test with actual dump data + expect(extractButtonCode('030153000000020318f40101'), equals('00000002')); + expect(extractButtonCode('030153000000010318f40101'), equals('00000001')); + expect(extractButtonCode('030153000004000318f40101'), equals('00000400')); + expect(extractButtonCode('030153000001000318f40101'), equals('00000100')); + expect(extractButtonCode('030153000008000318f40101'), equals('00000800')); + expect(extractButtonCode('030153000002000318f40101'), equals('00000200')); + expect(extractButtonCode('030153000000000318f40101'), equals('00000000')); + }); + + test('Should detect button changes correctly', () { + // Test that relevant part extraction is consistent with button code extraction + String extractRelevantPart(String fullValue) { + return fullValue.length >= 14 + ? fullValue.substring(6, 14) + : fullValue.substring(6); + } + + final idleState = '030153000000000318f40101'; + final buttonPressed = '030153000000020318f40101'; + + final idleRelevant = extractRelevantPart(idleState); + final pressedRelevant = extractRelevantPart(buttonPressed); + + expect(idleRelevant, equals('00000000')); + expect(pressedRelevant, equals('00000002')); + expect(idleRelevant != pressedRelevant, isTrue); + }); + + test('Should handle button release correctly', () { + String extractRelevantPart(String fullValue) { + return fullValue.length >= 14 + ? fullValue.substring(6, 14) + : fullValue.substring(6); + } + + // Simulate button press and release + final states = [ + '030153000000000318f40101', // idle + '030153000000020318f40101', // button pressed + '030153000000000318f40101', // button released (back to idle) + ]; + + final parts = states.map(extractRelevantPart).toList(); + + expect(parts[0], equals('00000000')); // idle + expect(parts[1], equals('00000002')); // pressed + expect(parts[2], equals('00000000')); // released + + // Verify state transitions + expect(parts[0] != parts[1], isTrue); // idle -> pressed + expect(parts[1] != parts[2], isTrue); // pressed -> released + expect(parts[0] == parts[2], isTrue); // back to idle + }); + + test('Should handle all button codes from mapping', () { + // Test all button codes from the mapping + final buttonCodes = { + "00000200": "up", + "00000100": "left", + "00000800": "down", + "00000400": "right", + "00002000": "x", + "00001000": "square", + "00008000": "campagnoloLeft", + "00004000": "leftBrake", + "00000002": "leftShift1", + "00000001": "leftShift2", + "02000000": "y", + "01000000": "a", + "08000000": "b", + "04000000": "z", + "20000000": "circle", + "10000000": "triangle", + "80000000": "campagnoloRight", + "40000000": "rightBrake", + "00020000": "rightShift1", + "00010000": "rightShift2", + }; + + // Verify all button codes are 8 characters + for (final code in buttonCodes.keys) { + expect(code.length, equals(8), reason: 'Button code $code should be 8 characters'); + } + }); + + test('Should convert bytes to hex correctly', () { + String bytesToHex(List bytes) { + return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(); + } + + // Test with sample data from the dump + // 030153000000020318f40101 = [0x03, 0x01, 0x53, 0x00, 0x00, 0x00, 0x02, 0x03, 0x18, 0xf4, 0x01, 0x01] + final bytes = [0x03, 0x01, 0x53, 0x00, 0x00, 0x00, 0x02, 0x03, 0x18, 0xf4, 0x01, 0x01]; + final hex = bytesToHex(bytes); + + expect(hex, equals('030153000000020318f40101')); + }); + + test('Should handle edge cases', () { + String extractRelevantPart(String fullValue) { + return fullValue.length >= 14 + ? fullValue.substring(6, 14) + : fullValue.substring(6); + } + + // Test with short strings + expect(extractRelevantPart('0123456789'), equals('6789')); + expect(extractRelevantPart('012345'), equals('')); + + // Test with exact length + expect(extractRelevantPart('01234567890123'), equals('67890123')); + }); + }); + + group('Elite Square Protocol Tests', () { + test('Should recognize button press pattern', () { + // According to the dump, the pattern is: + // Base: 030153000000000318f40101 + // Byte positions 6-13 (8 chars) change to indicate button + + final baseHex = '030153000000000318f40101'; + final buttonHex = '030153000000020318f40101'; + + // Extract the button part (positions 6-14) + final baseButton = baseHex.substring(6, 14); + final pressedButton = buttonHex.substring(6, 14); + + expect(baseButton, equals('00000000')); + expect(pressedButton, equals('00000002')); + }); + }); +} From 66c548fa7539906c92cae74fea6b382e318b6303 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 7 Nov 2025 18:13:21 +0000 Subject: [PATCH 3/4] Refactor tests to reduce code duplication Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com> --- test/elite_square_test.dart | 47 ++++++++++++++----------------------- 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/test/elite_square_test.dart b/test/elite_square_test.dart index 4e7b28c..9c8ad04 100644 --- a/test/elite_square_test.dart +++ b/test/elite_square_test.dart @@ -1,16 +1,26 @@ import 'package:flutter_test/flutter_test.dart'; +// Helper functions matching the Elite Square implementation +String extractButtonCode(String hexValue) { + if (hexValue.length >= 14) { + return hexValue.substring(6, 14); + } + return hexValue; +} + +String extractRelevantPart(String fullValue) { + return fullValue.length >= 14 + ? fullValue.substring(6, 14) + : fullValue.substring(6); +} + +String bytesToHex(List bytes) { + return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(); +} + void main() { group('Elite Square Button Detection Tests', () { test('Should extract correct button code from hex string', () { - // Test button code extraction - String extractButtonCode(String hexValue) { - if (hexValue.length >= 14) { - return hexValue.substring(6, 14); - } - return hexValue; - } - // Test with actual dump data expect(extractButtonCode('030153000000020318f40101'), equals('00000002')); expect(extractButtonCode('030153000000010318f40101'), equals('00000001')); @@ -23,11 +33,6 @@ void main() { test('Should detect button changes correctly', () { // Test that relevant part extraction is consistent with button code extraction - String extractRelevantPart(String fullValue) { - return fullValue.length >= 14 - ? fullValue.substring(6, 14) - : fullValue.substring(6); - } final idleState = '030153000000000318f40101'; final buttonPressed = '030153000000020318f40101'; @@ -41,12 +46,6 @@ void main() { }); test('Should handle button release correctly', () { - String extractRelevantPart(String fullValue) { - return fullValue.length >= 14 - ? fullValue.substring(6, 14) - : fullValue.substring(6); - } - // Simulate button press and release final states = [ '030153000000000318f40101', // idle @@ -98,10 +97,6 @@ void main() { }); test('Should convert bytes to hex correctly', () { - String bytesToHex(List bytes) { - return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(); - } - // Test with sample data from the dump // 030153000000020318f40101 = [0x03, 0x01, 0x53, 0x00, 0x00, 0x00, 0x02, 0x03, 0x18, 0xf4, 0x01, 0x01] final bytes = [0x03, 0x01, 0x53, 0x00, 0x00, 0x00, 0x02, 0x03, 0x18, 0xf4, 0x01, 0x01]; @@ -111,12 +106,6 @@ void main() { }); test('Should handle edge cases', () { - String extractRelevantPart(String fullValue) { - return fullValue.length >= 14 - ? fullValue.substring(6, 14) - : fullValue.substring(6); - } - // Test with short strings expect(extractRelevantPart('0123456789'), equals('6789')); expect(extractRelevantPart('012345'), equals('')); From 723f741bcace71c2aa684295bc184d417d00370d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 7 Nov 2025 18:15:27 +0000 Subject: [PATCH 4/4] Improve test code quality and fix edge cases Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com> --- test/elite_square_test.dart | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/test/elite_square_test.dart b/test/elite_square_test.dart index 9c8ad04..732fc9c 100644 --- a/test/elite_square_test.dart +++ b/test/elite_square_test.dart @@ -1,17 +1,12 @@ import 'package:flutter_test/flutter_test.dart'; -// Helper functions matching the Elite Square implementation +// Helper function matching the Elite Square implementation +// Extracts the 8-character button code from positions 6-14 of the hex string String extractButtonCode(String hexValue) { if (hexValue.length >= 14) { return hexValue.substring(6, 14); } - return hexValue; -} - -String extractRelevantPart(String fullValue) { - return fullValue.length >= 14 - ? fullValue.substring(6, 14) - : fullValue.substring(6); + return hexValue.substring(6); } String bytesToHex(List bytes) { @@ -32,17 +27,16 @@ void main() { }); test('Should detect button changes correctly', () { - // Test that relevant part extraction is consistent with button code extraction - + // Test that button code extraction is consistent for comparison final idleState = '030153000000000318f40101'; final buttonPressed = '030153000000020318f40101'; - final idleRelevant = extractRelevantPart(idleState); - final pressedRelevant = extractRelevantPart(buttonPressed); + final idleCode = extractButtonCode(idleState); + final pressedCode = extractButtonCode(buttonPressed); - expect(idleRelevant, equals('00000000')); - expect(pressedRelevant, equals('00000002')); - expect(idleRelevant != pressedRelevant, isTrue); + expect(idleCode, equals('00000000')); + expect(pressedCode, equals('00000002')); + expect(idleCode != pressedCode, isTrue); }); test('Should handle button release correctly', () { @@ -53,7 +47,7 @@ void main() { '030153000000000318f40101', // button released (back to idle) ]; - final parts = states.map(extractRelevantPart).toList(); + final parts = states.map(extractButtonCode).toList(); expect(parts[0], equals('00000000')); // idle expect(parts[1], equals('00000002')); // pressed @@ -107,11 +101,14 @@ void main() { test('Should handle edge cases', () { // Test with short strings - expect(extractRelevantPart('0123456789'), equals('6789')); - expect(extractRelevantPart('012345'), equals('')); + expect(extractButtonCode('0123456789'), equals('6789')); + expect(extractButtonCode('01234567'), equals('67')); - // Test with exact length - expect(extractRelevantPart('01234567890123'), equals('67890123')); + // Test with exact length (14 chars extracts positions 6-14) + expect(extractButtonCode('01234567890123'), equals('67890123')); + + // Test strings shorter than 14 extract from position 6 to end + expect(extractButtonCode('0123456789ABC'), equals('6789ABC')); }); });