Skip to content

Commit d044c8f

Browse files
committed
make prop_public compile again
1 parent fd7c0fc commit d044c8f

34 files changed

Lines changed: 1276 additions & 110 deletions
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//INFO: This is a stub - contact me if you need the full implementation.
2+
//
3+
// The full implementation decodes the Zwift Click/Play pairing pages and
4+
// drives the periodic RESET recovery. This stub keeps the static surface so
5+
// the app compiles.
6+
7+
import 'dart:async';
8+
9+
import 'package:flutter/foundation.dart';
10+
import 'package:universal_ble/universal_ble.dart';
11+
12+
class ClickLogic {
13+
static final _resettingDevices = <String>{};
14+
15+
static bool isResetting(String deviceId) => _resettingDevices.contains(deviceId);
16+
17+
static void clearResetting(String deviceId) => _resettingDevices.remove(deviceId);
18+
19+
/// Invoked right before a RESET command is sent.
20+
static void Function(String deviceId)? onResetSent;
21+
22+
static void processData(Uint8List bytes, {required String deviceId, required List<BleService> services}) {}
23+
24+
static Future<void> setupHandshake(List<BleService> services, String deviceId, {required bool isRight}) async {}
25+
26+
static void resetTimer() {}
27+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//INFO: This is a stub - contact me if you need the full implementation.
2+
//
3+
// The full implementation parses the SRAM AXS advertising "device record".
4+
// Values below are FAKE placeholders; [parse] is stubbed.
5+
6+
import 'dart:typed_data';
7+
8+
/// A SRAM AXS component identified from its advertising "device record".
9+
class SramDeviceInfo {
10+
const SramDeviceInfo({required this.serial, this.model, this.deviceType});
11+
12+
final int serial;
13+
final int? model;
14+
final int? deviceType;
15+
16+
int? get effectiveType => deviceType;
17+
18+
/// Stubbed classification.
19+
bool get isRearDerailleur => false;
20+
}
21+
22+
/// Parses the advertising "device record" that identifies a SRAM AXS
23+
/// component before connecting.
24+
class SramAdvertisement {
25+
SramAdvertisement._();
26+
27+
// FAKE placeholder service UUIDs.
28+
static const int serviceUuid16 = 0x0000;
29+
static const String serviceUuid128 = '00000000-0000-0000-0000-000000000000';
30+
31+
/// Stubbed: returns null.
32+
static SramDeviceInfo? parse(Uint8List record) => null;
33+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//INFO: This is a stub - contact me if you need the full implementation.
2+
//
3+
// The full implementation runs the SRAM `srambond` Diffie–Hellman handshake.
4+
5+
import 'dart:typed_data';
6+
7+
class SramBondException implements Exception {
8+
SramBondException(this.message);
9+
final String message;
10+
@override
11+
String toString() => 'SramBondException: $message';
12+
}
13+
14+
/// The `srambond` V1 finite-field Diffie–Hellman handshake. The handshake
15+
/// itself is stubbed; the BigInt ↔ 16-byte helpers are kept.
16+
class SramBond {
17+
SramBond._();
18+
19+
static Uint8List bigIntTo16(BigInt v) {
20+
final out = Uint8List(16);
21+
var t = v;
22+
for (var i = 15; i >= 0; i--) {
23+
out[i] = (t & BigInt.from(0xff)).toInt();
24+
t = t >> 8;
25+
}
26+
return out;
27+
}
28+
29+
static BigInt bigIntFrom(Uint8List bytes) {
30+
var v = BigInt.zero;
31+
for (final b in bytes) {
32+
v = (v << 8) | BigInt.from(b);
33+
}
34+
return v;
35+
}
36+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//INFO: This is a stub - contact me if you need the full implementation.
2+
//
3+
// All values below are FAKE placeholders. The real SRAM AXS protocol
4+
// constants (UUIDs, DH group parameters, protobuf field numbers) live in the
5+
// full package.
6+
7+
import 'dart:typed_data';
8+
9+
class SramAxs {
10+
SramAxs._();
11+
12+
static const String _base = '-0000-0000-0000-000000000000';
13+
14+
static const String bondService = '00000000$_base';
15+
static const String bondChar = '00000001$_base';
16+
static const String tokenChar = '00000002$_base';
17+
static const String controlTriggerChar = '00000003$_base';
18+
static const String gearChar = '00000004$_base';
19+
static const String componentEventChar = '00000005$_base';
20+
21+
static const int dhG = 0;
22+
static final BigInt dhN = BigInt.zero;
23+
24+
static final Uint8List bondInitToken = Uint8List(16);
25+
26+
static const int bondAck = 0x00;
27+
28+
static const int fieldToken = 0;
29+
static const int fieldControllerDeviceType = 0;
30+
static const int fieldButtonMask = 0;
31+
static const int fieldGear = 0;
32+
static const int fieldCassette = 0;
33+
static const int fieldTriggerDeviceType = 0;
34+
static const int fieldTriggerButtonMask = 0;
35+
static const int fieldTrigger = 0;
36+
37+
static const int paddleMask = 1;
38+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//INFO: This is a stub - contact me if you need the full implementation.
2+
//
3+
// The full implementation is the SRAM AES-EAX authenticated cipher. All
4+
// bodies here are stubbed — no cryptographic logic is exposed.
5+
6+
import 'dart:typed_data';
7+
8+
class SramEax {
9+
SramEax._();
10+
11+
static bool isFrame(Uint8List frame) => false;
12+
13+
static Uint8List? decrypt(Uint8List key, Uint8List frame) => null;
14+
15+
static Uint8List encrypt(Uint8List key, Uint8List plaintext, Uint8List nonce) => Uint8List(0);
16+
17+
static Uint8List randomNonce() => Uint8List(0);
18+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//INFO: This is a stub - contact me if you need the full implementation.
2+
//
3+
// The full implementation owns the SRAM session key, decrypts button events
4+
// and reads/writes the on-device reaction config. This stub keeps the public
5+
// surface so the app compiles.
6+
7+
import 'dart:typed_data';
8+
9+
import 'sram_axs_transport.dart';
10+
11+
/// A single decoded press: which controller (serial + device_type) and which
12+
/// button (mask). Any field may be null in degraded operation.
13+
class SramPress {
14+
const SramPress({this.controllerSerial, this.buttonMask, this.deviceType});
15+
final int? controllerSerial;
16+
final int? buttonMask;
17+
18+
/// The pressing controller's device_type (0 = left shifter, 1 = right, …).
19+
final int? deviceType;
20+
}
21+
22+
/// Per-device façade over the SRAM protocol units.
23+
class SramAxsLogic {
24+
SramAxsLogic(this.transport);
25+
26+
final SramTransport transport;
27+
28+
Uint8List? _key;
29+
30+
Uint8List? get sessionKey => _key;
31+
bool get isBonded => _key != null;
32+
33+
void seedKey(Uint8List? key) => _key = key;
34+
35+
Future<Uint8List> bond() => throw UnimplementedError();
36+
37+
Future<void> ensureBonded() async {}
38+
39+
void onComponentEvent(Uint8List plaintext) {}
40+
41+
Future<SramPress> handleTrigger() async => const SramPress();
42+
43+
Future<Map<String, SramReactionTrigger>> backupConfig() async => {};
44+
45+
Future<void> disableShifting() async {}
46+
47+
Future<void> restoreConfig(Map<String, SramReactionTrigger> saved) async {}
48+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//INFO: This is a stub - contact me if you need the full implementation.
2+
//
3+
// The full implementation encodes/decodes the SRAM reaction-config protobuf.
4+
// All bodies here are stubbed.
5+
6+
import 'dart:typed_data';
7+
8+
class SramProtobuf {
9+
SramProtobuf._();
10+
11+
static Map<int, int> parseVarints(Uint8List data) => const {};
12+
13+
static (List<int>, List<int>) parseReactionConfig(Uint8List data) => (const [], const []);
14+
15+
static Uint8List encodeReactionConfig(List<int> deviceTypes, List<int> buttonMasks, int token) => Uint8List(0);
16+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//INFO: This is a stub - contact me if you need the full implementation.
2+
3+
import 'dart:async';
4+
import 'dart:typed_data';
5+
6+
/// BLE seam for the SRAM protocol code. The app supplies a `universal_ble`
7+
/// backed implementation; tests supply a fake.
8+
abstract class SramTransport {
9+
Future<void> subscribe(String characteristic);
10+
Future<void> write(String characteristic, Uint8List data, {bool withoutResponse = false});
11+
Future<Uint8List> read(String characteristic);
12+
13+
/// Notifications delivered on [characteristic] after [subscribe].
14+
Stream<Uint8List> notifications(String characteristic);
15+
16+
/// UUIDs of characteristics that are both readable and writable.
17+
List<String> readWriteCharacteristics();
18+
}
19+
20+
/// Buffers notification fragments and hands back exactly `count` bytes per
21+
/// [take]. Stubbed.
22+
class SramByteInbox {
23+
void add(Uint8List data) {}
24+
25+
Future<Uint8List> take(int count) => throw UnimplementedError();
26+
}
27+
28+
/// One reaction-config slot's trigger: parallel device-type / button-mask lists.
29+
class SramReactionTrigger {
30+
const SramReactionTrigger(this.deviceTypes, this.buttonMasks);
31+
32+
final List<int> deviceTypes;
33+
final List<int> buttonMasks;
34+
35+
Map<String, dynamic> toJson() => {'device_types': deviceTypes, 'button_masks': buttonMasks};
36+
37+
factory SramReactionTrigger.fromJson(Map<String, dynamic> json) => SramReactionTrigger(
38+
(json['device_types'] as List).cast<int>(),
39+
(json['button_masks'] as List).cast<int>(),
40+
);
41+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//INFO: This is a stub - contact me if you need the full implementation.
2+
//
3+
// The full implementation maps a shifter's (deviceType, model) to its buttons
4+
// and their human names. This stub returns generic placeholders.
5+
6+
class SramShifterButtons {
7+
SramShifterButtons._();
8+
9+
/// Stubbed: a single paddle.
10+
static List<int> masksFor(int? deviceType, int? model) => const [1];
11+
12+
/// Stubbed: generic label.
13+
static String nameFor(int? deviceType, int? model, int mask) => 'Button 0x${mask.toRadixString(16)}';
14+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//INFO: This is a stub - contact me if you need the full implementation.
2+
//
3+
// The full implementation drives a real DirCon (Direct Connect) TCP client.
4+
// This stub keeps the [TrainerTransport] surface so the app compiles.
5+
6+
import 'dart:async';
7+
import 'dart:typed_data';
8+
9+
import 'package:prop/transports/trainer_transport.dart';
10+
import 'package:universal_ble/universal_ble.dart';
11+
12+
/// [TrainerTransport] over a DirCon TCP connection.
13+
class DirconTrainerTransport extends TrainerTransport {
14+
DirconTrainerTransport({required String id, required this.host, required this.port}) : _id = id;
15+
16+
final String _id;
17+
final String host;
18+
final int port;
19+
20+
@override
21+
String get id => _id;
22+
23+
@override
24+
Future<void> connect() => throw UnimplementedError();
25+
26+
@override
27+
Future<List<BleService>> discoverServices() => throw UnimplementedError();
28+
29+
@override
30+
Future<Uint8List> read(String service, String characteristic) => throw UnimplementedError();
31+
32+
@override
33+
Future<void> write(String service, String characteristic, Uint8List bytes, {bool withoutResponse = false}) =>
34+
throw UnimplementedError();
35+
36+
@override
37+
Future<void> subscribe(String service, String characteristic, {required bool indicate}) =>
38+
throw UnimplementedError();
39+
40+
@override
41+
Stream<({String characteristic, Uint8List value})> get notifications => const Stream.empty();
42+
43+
@override
44+
Future<void> disconnect() async {}
45+
}

0 commit comments

Comments
 (0)