Skip to content

Commit bb270a5

Browse files
Alexandrradomir9720
authored andcommitted
add wheel steering mode change dialog
1 parent ebd5679 commit bb270a5

File tree

15 files changed

+507
-11
lines changed

15 files changed

+507
-11
lines changed

lib/app/scopes/flows/selected_data_source_scope.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,12 @@ class SelectedDataSourceScope extends AutoRouter {
198198
generalDataCubit: context.read(),
199199
),
200200
),
201+
BlocProvider(
202+
create: (context) => ChangeWheelSteeringBloc(
203+
dataSource: context.read(),
204+
generalDataCubit: context.read(),
205+
),
206+
),
201207
BlocProvider(
202208
create: (context) =>
203209
LaunchAppCubit(appsService: context.read()),
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import 'package:flutter_bloc/flutter_bloc.dart';
2+
import 'package:freezed_annotation/freezed_annotation.dart';
3+
import 'package:pixel_app_flutter/domain/data_source/data_source.dart';
4+
import 'package:pixel_app_flutter/domain/data_source/models/package/outgoing/outgoing_data_source_packages.dart';
5+
import 'package:pixel_app_flutter/domain/data_source/models/package_data/package_data.dart';
6+
import 'package:re_seedwork/re_seedwork.dart';
7+
8+
part 'change_wheel_steering_bloc.freezed.dart';
9+
10+
@freezed
11+
class ChangeWheelSteeringEvent extends EffectEvent with _$ChangeWheelSteeringEvent {
12+
const factory ChangeWheelSteeringEvent.change(WheelSteering newValue) = _Change;
13+
}
14+
15+
typedef ChangeWheelSteeringState = AsyncData<WheelSteering, Object>;
16+
17+
class ChangeWheelSteeringBloc extends Bloc<ChangeWheelSteeringEvent, ChangeWheelSteeringState>
18+
with BlocEventHandlerMixin {
19+
ChangeWheelSteeringBloc({
20+
required this.dataSource,
21+
required this.generalDataCubit,
22+
}) : super(const ChangeWheelSteeringState.initial(WheelSteering.free)) {
23+
on<_Change>(_onChange);
24+
}
25+
26+
@visibleForTesting
27+
static const List<DataSourceParameterId> kParameterIds = [
28+
DataSourceParameterId.wheelSteering(),
29+
];
30+
31+
@protected
32+
final DataSource dataSource;
33+
34+
@protected
35+
final GeneralDataCubit generalDataCubit;
36+
37+
Future<void> _onChange(
38+
_Change event,
39+
Emitter<AsyncData<WheelSteering, Object>> emit,
40+
) async {
41+
emit(AsyncData.loading(event.newValue));
42+
43+
try {
44+
final future = generalDataCubit.stream
45+
.firstWhere((element) => element.wheelSteering == event.newValue)
46+
.timeout(const Duration(seconds: 2));
47+
for (final parameterId in kParameterIds) {
48+
final res = await dataSource.sendPackage(
49+
OutgoingSetValuePackage(
50+
parameterId: parameterId,
51+
setValueBody: SetInt8Body(value: event.newValue.id),
52+
),
53+
);
54+
if (res.isError) {
55+
return emit(AsyncData.failure(generalDataCubit.state.wheelSteering));
56+
}
57+
}
58+
await future;
59+
60+
emit(AsyncData.success(event.newValue));
61+
} on Object catch (_) {
62+
emit(AsyncData.failure(generalDataCubit.state.wheelSteering));
63+
64+
rethrow;
65+
}
66+
}
67+
}

lib/domain/data_source/blocs/general_data_cubit.dart

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:pixel_app_flutter/domain/app/app.dart';
55
import 'package:pixel_app_flutter/domain/data_source/data_source.dart';
66
import 'package:pixel_app_flutter/domain/data_source/models/package/incoming/battery_percent.dart';
77
import 'package:pixel_app_flutter/domain/data_source/models/package/incoming/incoming_data_source_packages.dart';
8+
import 'package:pixel_app_flutter/domain/data_source/models/package/incoming/wheelSteering.dart';
89
import 'package:pixel_app_flutter/domain/data_source/models/package_data/package_data.dart';
910
import 'package:re_seedwork/re_seedwork.dart';
1011

@@ -15,6 +16,7 @@ typedef _IntValueModifier = (
1516

1617
extension _SequenceExt on Sequence<IntWithStatus> {
1718
static int avgFold(int a, int b) => a + b;
19+
1820
static int maxFold(int a, int b) => a > b ? a : b;
1921

2022
static _IntValueModifier avg =
@@ -50,6 +52,7 @@ final class GeneralDataState with EquatableMixin {
5052
required this.odometer,
5153
required this.speed,
5254
required this.gear,
55+
required this.wheelSteering,
5356
});
5457

5558
GeneralDataState.initial({
@@ -70,7 +73,8 @@ final class GeneralDataState with EquatableMixin {
7073
gear = Sequence.fill(
7174
hardwareCount.motors,
7275
MotorGear.unknown,
73-
);
76+
),
77+
wheelSteering = WheelSteering.free;
7478

7579
factory GeneralDataState.fromMap(Map<String, dynamic> map) {
7680
return GeneralDataState(
@@ -88,6 +92,7 @@ final class GeneralDataState with EquatableMixin {
8892
gear: Sequence.fromIterable(
8993
map.tryParseAndMapList('gear', MotorGear.fromId),
9094
),
95+
wheelSteering: map.parseAndMap('wheelSteering', WheelSteering.fromId),
9196
);
9297
}
9398

@@ -97,6 +102,7 @@ final class GeneralDataState with EquatableMixin {
97102
final Sequence<IntWithStatus> speed;
98103
final Sequence<MotorGear> gear;
99104
final Sequence<IntWithStatus> batteryPercent;
105+
final WheelSteering wheelSteering;
100106

101107
// TODO(Radomir): hardcoded temporarily because there is only one battery
102108
// at the moment, and the merged value(mean) is irrelevant
@@ -120,20 +126,16 @@ final class GeneralDataState with EquatableMixin {
120126
}
121127

122128
@override
123-
List<Object?> get props => [
124-
power,
125-
batteryPercent,
126-
odometer,
127-
speed,
128-
gear,
129-
];
129+
List<Object?> get props =>
130+
[power, batteryPercent, odometer, speed, gear, wheelSteering];
130131

131132
GeneralDataState copyWith({
132133
Sequence<IntWithStatus>? power,
133134
Sequence<IntWithStatus>? batteryPercent,
134135
IntWithStatus? odometer,
135136
Sequence<IntWithStatus>? speed,
136137
Sequence<MotorGear>? gear,
138+
WheelSteering? wheelSteering,
137139
}) {
138140
return GeneralDataState(
139141
hardwareCount: hardwareCount,
@@ -142,6 +144,7 @@ final class GeneralDataState with EquatableMixin {
142144
odometer: odometer ?? this.odometer,
143145
speed: speed ?? this.speed,
144146
gear: gear ?? this.gear,
147+
wheelSteering: wheelSteering ?? this.wheelSteering,
145148
);
146149
}
147150

@@ -153,6 +156,7 @@ final class GeneralDataState with EquatableMixin {
153156
'odometer': odometer.toMap(),
154157
'speed': [for (final e in speed) e.toMap()],
155158
'gear': [for (final e in gear) e.id],
159+
'wheelSteering': wheelSteering.id,
156160
};
157161
}
158162
}
@@ -216,6 +220,14 @@ class GeneralDataCubit extends Cubit<GeneralDataState> with ConsumerBlocMixin {
216220
odometer: IntWithStatus.fromBytesConvertible(model, km),
217221
),
218222
);
223+
})
224+
..voidOnModel<Uint8WithStatusBody,
225+
WheelSteeringIncomingDataSourcePackage>((model) {
226+
emit(
227+
state.copyWith(
228+
wheelSteering: WheelSteering.fromId(model.value) ,
229+
),
230+
);
219231
});
220232
});
221233
}
@@ -234,6 +246,7 @@ class GeneralDataCubit extends Cubit<GeneralDataState> with ConsumerBlocMixin {
234246
const DataSourceParameterId.batteryPercent2(),
235247
const DataSourceParameterId.batteryPower1(),
236248
const DataSourceParameterId.batteryPower2(),
249+
const DataSourceParameterId.wheelSteering(),
237250
};
238251

239252
@protected

lib/domain/data_source/data_source.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// blocs
22
export 'blocs/battery_data_cubit.dart';
33
export 'blocs/change_gear_bloc.dart';
4+
export 'blocs/change_wheel_steering_bloc.dart';
45
export 'blocs/data_source_authorization_cubit.dart';
56
export 'blocs/data_source_connect_bloc.dart';
67
export 'blocs/data_source_connection_status_cubit.dart';

lib/domain/data_source/models/data_source_parameter_id.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ abstract class DataSourceParameterId {
136136
const factory DataSourceParameterId.transmission4() =
137137
Transmission4ParameterId;
138138

139+
const factory DataSourceParameterId.wheelSteering() =
140+
WheelSteeringParameterId;
141+
139142
const factory DataSourceParameterId.motorTemperature1() =
140143
MotorTemperature1ParameterId;
141144
const factory DataSourceParameterId.motorTemperature2() =
@@ -269,6 +272,8 @@ abstract class DataSourceParameterId {
269272
bool get isTransmission3 => this is Transmission3ParameterId;
270273
bool get isTransmission4 => this is Transmission4ParameterId;
271274

275+
bool get isWheelSteering => this is WheelSteeringParameterId;
276+
272277
bool get isMotorTemperature1 => this is MotorTemperature1ParameterId;
273278
bool get isMotorTemperature2 => this is MotorTemperature2ParameterId;
274279
bool get isMotorTemperature3 => this is MotorTemperature3ParameterId;
@@ -372,6 +377,7 @@ abstract class DataSourceParameterId {
372377
DataSourceParameterId.transmission2(),
373378
DataSourceParameterId.transmission3(),
374379
DataSourceParameterId.transmission4(),
380+
DataSourceParameterId.wheelSteering(),
375381
DataSourceParameterId.motorTemperature1(),
376382
DataSourceParameterId.motorTemperature2(),
377383
DataSourceParameterId.motorTemperature3(),
@@ -671,6 +677,10 @@ class Transmission4ParameterId extends DataSourceParameterId {
671677
const Transmission4ParameterId() : super(0x0137);
672678
}
673679

680+
class WheelSteeringParameterId extends DataSourceParameterId {
681+
const WheelSteeringParameterId() : super(0x01A4);
682+
}
683+
674684
class MotorTemperature1ParameterId extends DataSourceParameterId {
675685
const MotorTemperature1ParameterId() : super(0x011A);
676686
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import 'package:pixel_app_flutter/domain/data_source/models/package/data_source_incoming_package.dart';
2+
3+
class WheelSteeringIncomingDataSourcePackage
4+
extends Uint8WithStatusIncomingDataSourcePackage {
5+
WheelSteeringIncomingDataSourcePackage(super.source);
6+
7+
@override
8+
bool get validParameterId => parameterId.isWheelSteering;
9+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import 'dart:math';
2+
3+
import 'package:pixel_app_flutter/domain/data_source/extensions/int.dart';
4+
import 'package:pixel_app_flutter/domain/data_source/models/package_data/package_data.dart';
5+
import 'package:pixel_app_flutter/domain/data_source/models/package_data/wrappers/bytes_convertible_with_status.dart';
6+
7+
enum WheelSteering {
8+
free(0x00),
9+
align(0x01),
10+
fastTurn(0x02),
11+
diagonal(0x03),
12+
blocked(0x04);
13+
14+
const WheelSteering(this.id);
15+
final int id;
16+
17+
static WheelSteering fromId(int id) {
18+
return WheelSteering.values.firstWhere(
19+
(element) => element.id == id,
20+
orElse: () => WheelSteering.free,
21+
);
22+
}
23+
24+
R when<R>({
25+
required R Function() free,
26+
required R Function() align,
27+
required R Function() fastTurn,
28+
required R Function() diagonal,
29+
required R Function() blocked,
30+
}) {
31+
return switch (this) {
32+
WheelSteering.free => free(),
33+
WheelSteering.align => align(),
34+
WheelSteering.fastTurn => fastTurn(),
35+
WheelSteering.diagonal => diagonal(),
36+
WheelSteering.blocked => blocked(),
37+
};
38+
}
39+
40+
static WheelSteering get random => values[Random().nextInt(values.length)];
41+
}
42+
43+
class WheelSteeringPacket extends IntBytesConvertibleWithStatus {
44+
WheelSteeringPacket({
45+
required this.wheelSteering,
46+
required super.status,
47+
}) : super(
48+
value: _toUint8(
49+
wheelSteering: wheelSteering,
50+
),
51+
);
52+
53+
factory WheelSteeringPacket.unknown() => WheelSteeringPacket(
54+
wheelSteering: WheelSteering.free,
55+
status: PeriodicValueStatus.normal,
56+
);
57+
58+
WheelSteeringPacket.fromId({
59+
required this.wheelSteering,
60+
required super.id,
61+
}) : super.fromId(
62+
value: _toUint8(
63+
wheelSteering: wheelSteering,
64+
),
65+
);
66+
67+
factory WheelSteeringPacket.builder(int functionId, int value) {
68+
final bytes = value.toBytesUint8;
69+
70+
return WheelSteeringPacket.fromId(
71+
id: functionId,
72+
wheelSteering: WheelSteering.fromId(bytes[0]),
73+
);
74+
}
75+
76+
final WheelSteering wheelSteering;
77+
78+
static int _toUint8({
79+
required WheelSteering wheelSteering,
80+
}) {
81+
return [
82+
wheelSteering.id,
83+
].toIntFromUint8;
84+
}
85+
86+
@override
87+
List<Object?> get props => [
88+
...super.props,
89+
wheelSteering,
90+
];
91+
92+
static Uint8WithStatusBytesConverter<WheelSteeringPacket> get converter =>
93+
const Uint8WithStatusBytesConverter(WheelSteeringPacket.builder);
94+
95+
@override
96+
BytesConverter<WheelSteeringPacket> get bytesConverter => converter;
97+
}

lib/domain/data_source/models/package_data/package_data.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export 'implementations/two_uint16_with_status_body.dart';
2525
export 'implementations/uint16_with_status_body.dart';
2626
export 'implementations/uint32_with_status_body.dart';
2727
export 'implementations/motor_gear_and_roll.dart';
28+
export 'implementations/wheel_steering.dart';
2829
export 'implementations/int16_with_status_body.dart';
2930
export 'implementations/set_int8_body.dart';
3031
export 'implementations/set_uint8_body.dart';

lib/l10n/arb/app_en.arb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@
290290
"boostGearShort": "B",
291291
"unknownGearShort": "U",
292292
"errorSwitchingGearMessage": "Error switching the gear",
293+
"errorChangeWheelSteeringMessage": "Error switching wheels steering mode",
293294
"stopBeforeSwitchingGearMessage": "To switch the gear, you must first stop",
294295
"reverseMotorRollDirectionShort": "R",
295296
"unknownMotorRollDirectionShort": "U",

lib/l10n/arb/app_ru.arb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@
290290
"boostGearShort": "B",
291291
"unknownGearShort": "U",
292292
"errorSwitchingGearMessage": "Ошибка переключения передачи",
293+
"errorChangeWheelSteeringMessage": "Ошибка переключения режима поворота",
293294
"stopBeforeSwitchingGearMessage": "Для переключения передачи нужно сначала остановиться",
294295
"reverseMotorRollDirectionShort": "R",
295296
"unknownMotorRollDirectionShort": "U",

0 commit comments

Comments
 (0)