Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/app/scopes/flows/selected_data_source_scope.dart
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,11 @@ class SelectedDataSourceScope extends AutoRouter {
generalDataCubit: context.read(),
),
),
BlocProvider(
create: (context) => SteeringRackControlBloc(
dataSource: context.read(),
)..add(const SteeringRackControlEvent.get()),
),
BlocProvider(
create: (context) =>
LaunchAppCubit(appsService: context.read()),
Expand Down
73 changes: 49 additions & 24 deletions lib/data/services/data_source/demo_data_source.dart
Original file line number Diff line number Diff line change
Expand Up @@ -592,24 +592,16 @@ class DemoDataSource extends DataSource
},
unavailableForSubscriptionIds: {},
respondCallback: (id, version, manager, [package]) async {
final data = (package?.data).checkNotNull('Package data');
final requestType = data.first;
assert(
[
FunctionId.requestValue.value,
FunctionId.setValueWithParam.value,
].contains(requestType),
'Supported only "set" and "get" request types',
);
final functionId = package.functionId
..assertIsRequestValueOrSetValue();

await manager.updateCallback(
id,
SetUint8ResultBody(
success: !generateRandomErrors() || randomBool,
value: (generateRandomErrors() ||
requestType == FunctionId.requestValue.value)
value: (generateRandomErrors() || functionId.isRequestValue)
? SuspensionMode.random.id
: package?.data.last ?? 0,
: package.dataNotNull.last,
),
version,
);
Expand All @@ -619,28 +611,43 @@ class DemoDataSource extends DataSource
),
MainEcuMockResponseWrapper(
ids: {
const DataSourceParameterId.suspensionValue(),
const DataSourceParameterId.steeringRack(),
},
unavailableForSubscriptionIds: {},
respondCallback: (id, version, manager, [package]) async {
final data = (package?.data).checkNotNull('Package data');
final requestType = data.first;
assert(
[
FunctionId.requestValue.value,
FunctionId.setValueWithParam.value,
].contains(requestType),
'Supported only "set" and "get" request types',
final functionId = package.functionId
..assertIsRequestValueOrSetValue();

await manager.updateCallback(
id,
SetUint8ResultBody(
success: !generateRandomErrors() || randomBool,
value: (generateRandomErrors() || functionId.isRequestValue)
? SteeringRack.random.id
: package.dataNotNull.last,
),
version,
);

return const Result.value(null);
},
),
MainEcuMockResponseWrapper(
ids: {
const DataSourceParameterId.suspensionValue(),
},
unavailableForSubscriptionIds: {},
respondCallback: (id, version, manager, [package]) async {
final functionId = package.functionId
..assertIsRequestValueOrSetValue();

await manager.updateCallback(
id,
SetUint8ResultBody(
success: !generateRandomErrors() || randomBool,
value: (generateRandomErrors() ||
requestType == FunctionId.requestValue.value)
value: (generateRandomErrors() || functionId.isRequestValue)
? Random().nextInt(SuspensionMode.kMaxManualValue)
: package?.data.last ?? 0,
: package.dataNotNull.last,
),
version,
);
Expand Down Expand Up @@ -781,6 +788,24 @@ extension on int {
bool get toBool => this == 255;
}

extension on DataSourceOutgoingPackage? {
List<int> get dataNotNull => checkNotNull('Package').data;

FunctionId get functionId => FunctionId.fromValue(dataNotNull.first);
}

extension on FunctionId {
void assertIsRequestValueOrSetValue() {
assert(
[
FunctionId.requestValue,
FunctionId.setValueWithParam,
].contains(this),
'Supported only "set" and "get" request types',
);
}
}

@visibleForTesting
final class MainEcuMockManager {
const MainEcuMockManager({
Expand Down
127 changes: 127 additions & 0 deletions lib/domain/data_source/blocs/steering_rack_control_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:pixel_app_flutter/domain/data_source/data_source.dart';
import 'package:pixel_app_flutter/domain/data_source/extensions/stream.dart';
import 'package:pixel_app_flutter/domain/data_source/models/package/incoming/incoming_data_source_packages.dart';
import 'package:pixel_app_flutter/domain/data_source/models/package/outgoing/outgoing_data_source_packages.dart';
import 'package:pixel_app_flutter/domain/data_source/models/package_data/package_data.dart';
import 'package:re_seedwork/re_seedwork.dart';

part 'steering_rack_control_bloc.freezed.dart';

@freezed
class SteeringRackControlEvent with _$SteeringRackControlEvent {
const factory SteeringRackControlEvent.get() = _Get;
const factory SteeringRackControlEvent.set(SteeringRack steeringRack) = _Set;
}

typedef SteeringRackControlState
= AsyncData<SteeringRack, SteeringRackControlEvent>;

class SteeringRackControlBloc
extends Bloc<SteeringRackControlEvent, SteeringRackControlState> {
SteeringRackControlBloc({
required this.dataSource,
this.responseTimeout = const Duration(seconds: 2),
}) : super(const SteeringRackControlState.initial(SteeringRack.free)) {
on<_Get>(_onGet);
on<_Set>(_onSet);
}

Future<void> _onGet(
_Get event,
Emitter<SteeringRackControlState> emit,
) async {
emit(state.inLoading());

try {
await dataSource.packageStream
.waitForType<SteeringRackIncomingDataSourcePackage>(
action: () async {
final result = await dataSource.sendPackage(
OutgoingValueRequestPackage(
parameterId: const DataSourceParameterId.steeringRack(),
),
);

if (result.isError) {
emit(state.inFailure(event));
}
return result.isError;
},
onDone: (package) async {
emit(
package.dataModel.when(
success: (value) {
return AsyncData.success(SteeringRack.fromId(value));
},
error: () => state.inFailure(event),
),
);
},
timeout: responseTimeout,
);
} catch (e) {
emit(state.inFailure(event));

rethrow;
}
}

Future<void> _onSet(
_Set event,
Emitter<SteeringRackControlState> emit,
) async {
final beforePayload = state.payload;
emit(AsyncData.loading(event.steeringRack));

try {
await dataSource.packageStream
.waitForType<SteeringRackIncomingDataSourcePackage>(
action: () async {
final result = await dataSource.sendPackage(
OutgoingSetValuePackage(
parameterId: const DataSourceParameterId.steeringRack(),
setValueBody: SetUint8Body(value: event.steeringRack.id),
),
);

if (result.isError) {
emit(AsyncData.failure(beforePayload, event));
}
return result.isError;
},
onDone: (package) async {
emit(
package.dataModel.when(
success: (value) {
if (value == state.payload.id) {
return state.inSuccess();
}
return AsyncData.failure(
beforePayload,
event,
);
},
error: () => AsyncData.failure(
beforePayload,
event,
),
),
);
},
timeout: responseTimeout,
);
} catch (e) {
emit(AsyncData.failure(beforePayload, event));

rethrow;
}
}

@protected
final DataSource dataSource;

@protected
final Duration responseTimeout;
}
25 changes: 5 additions & 20 deletions lib/domain/data_source/blocs/suspension_control_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:pixel_app_flutter/domain/data_source/data_source.dart';
import 'package:pixel_app_flutter/domain/data_source/extensions/stream.dart';
import 'package:pixel_app_flutter/domain/data_source/models/package/incoming/incoming_data_source_packages.dart';
import 'package:pixel_app_flutter/domain/data_source/models/package/outgoing/outgoing_data_source_packages.dart';
import 'package:pixel_app_flutter/domain/data_source/models/package_data/package_data.dart';
Expand Down Expand Up @@ -50,7 +51,7 @@ class SuspensionControlBloc

try {
await dataSource.packageStream
.waitFor<SuspensionModeIncomingDataSourcePackage>(
.waitForType<SuspensionModeIncomingDataSourcePackage>(
action: () async {
final result = await dataSource.sendPackage(
OutgoingValueRequestPackage(
Expand Down Expand Up @@ -94,7 +95,7 @@ class SuspensionControlBloc

try {
await dataSource.packageStream
.waitFor<SuspensionManualValueIncomingDataSourcePackage>(
.waitForType<SuspensionManualValueIncomingDataSourcePackage>(
action: () async {
final result = await dataSource.sendPackage(
OutgoingValueRequestPackage(
Expand Down Expand Up @@ -135,7 +136,7 @@ class SuspensionControlBloc

try {
await dataSource.packageStream
.waitFor<SuspensionModeIncomingDataSourcePackage>(
.waitForType<SuspensionModeIncomingDataSourcePackage>(
action: () async {
final result = await dataSource.sendPackage(
OutgoingSetValuePackage(
Expand Down Expand Up @@ -190,7 +191,7 @@ class SuspensionControlBloc

try {
await dataSource.packageStream
.waitFor<SuspensionManualValueIncomingDataSourcePackage>(
.waitForType<SuspensionManualValueIncomingDataSourcePackage>(
action: () async {
final result = await dataSource.sendPackage(
OutgoingSetValuePackage(
Expand Down Expand Up @@ -242,19 +243,3 @@ class SuspensionControlBloc
}
}
}

extension on Stream<dynamic> {
Future<void> waitFor<T>({
required Future<bool> Function() action,
required Future<void> Function(T value) onDone,
required Duration timeout,
}) async {
final future = firstWhere((package) => package is T).timeout(timeout);

final stop = await action();

if (stop) return;

await onDone((await future) as T);
}
}
4 changes: 4 additions & 0 deletions lib/domain/data_source/data_source.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export 'blocs/lights_cubit.dart';
export 'blocs/motor_data_cubit.dart';
export 'blocs/outgoing_packages_cubit.dart';
export 'blocs/select_data_source_bloc.dart';
export 'blocs/steering_rack_control_bloc.dart';
export 'blocs/suspension_control_bloc.dart';
export 'blocs/toggle_state_error.dart';

Expand All @@ -27,9 +28,12 @@ export 'models/data_source_with_address.dart';
export 'models/developer_tools_parameters.dart';
export 'models/hardware_count.dart';
export 'models/int_with_status.dart';
export 'models/motor_gear.dart';
export 'models/motor_roll_direction.dart';
export 'models/package/data_source_package.dart';
export 'models/package_data/bytes_converter.dart';
export 'models/serial_number.dart';
export 'models/steering_rack.dart';
export 'models/suspension_mode.dart';
export 'models/usb_port_parameters.dart';

Expand Down
15 changes: 15 additions & 0 deletions lib/domain/data_source/extensions/stream.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
extension WaitForStreamExtension on Stream<dynamic> {
Future<void> waitForType<T>({
required Future<bool> Function() action,
required Future<void> Function(T value) onDone,
required Duration timeout,
}) async {
final future = firstWhere((package) => package is T).timeout(timeout);

final stop = await action();

if (stop) return;

await onDone((await future) as T);
}
}
9 changes: 9 additions & 0 deletions lib/domain/data_source/models/data_source_parameter_id.dart
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ abstract class DataSourceParameterId {
const factory DataSourceParameterId.transmission4() =
Transmission4ParameterId;

const factory DataSourceParameterId.steeringRack() = SteeringRackParameterId;

const factory DataSourceParameterId.motorTemperature1() =
MotorTemperature1ParameterId;
const factory DataSourceParameterId.motorTemperature2() =
Expand Down Expand Up @@ -269,6 +271,8 @@ abstract class DataSourceParameterId {
bool get isTransmission3 => this is Transmission3ParameterId;
bool get isTransmission4 => this is Transmission4ParameterId;

bool get isSteeringRack => this is SteeringRackParameterId;

bool get isMotorTemperature1 => this is MotorTemperature1ParameterId;
bool get isMotorTemperature2 => this is MotorTemperature2ParameterId;
bool get isMotorTemperature3 => this is MotorTemperature3ParameterId;
Expand Down Expand Up @@ -372,6 +376,7 @@ abstract class DataSourceParameterId {
DataSourceParameterId.transmission2(),
DataSourceParameterId.transmission3(),
DataSourceParameterId.transmission4(),
DataSourceParameterId.steeringRack(),
DataSourceParameterId.motorTemperature1(),
DataSourceParameterId.motorTemperature2(),
DataSourceParameterId.motorTemperature3(),
Expand Down Expand Up @@ -671,6 +676,10 @@ class Transmission4ParameterId extends DataSourceParameterId {
const Transmission4ParameterId() : super(0x0137);
}

class SteeringRackParameterId extends DataSourceParameterId {
const SteeringRackParameterId() : super(0x01A4);
}

class MotorTemperature1ParameterId extends DataSourceParameterId {
const MotorTemperature1ParameterId() : super(0x011A);
}
Expand Down
Loading