Skip to content

Commit

Permalink
fix: #1 , feat: refactor serial communicating
Browse files Browse the repository at this point in the history
  • Loading branch information
ShapeLayer committed Oct 23, 2024
1 parent e0dcedb commit 32cd1a9
Show file tree
Hide file tree
Showing 19 changed files with 845 additions and 202 deletions.
5 changes: 5 additions & 0 deletions configurator/lib/build_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ class BuildConfig {
static const serialParity = null;
static const serialFlowControl = null;

static const serialHandshakeRetryLimit = 1;
static const serialDefaultRetryLimit = 3;
static const serialHandshakeTimeout = 2;
static const serialDefaultTimeout = 3;

static KeyConfig defaultKeyConfig = KeyConfig(
EachKeyConfig(keycode: Keycode.esc, enabled: false),
EachKeyConfig(keycode: Keycode.enter, enabled: false),
Expand Down
106 changes: 61 additions & 45 deletions configurator/lib/components/device_selector.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'dart:async';

import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:configurator/models/error_serial_device.dart';
import 'package:configurator/models/list_dropdown_button_item.dart';
import 'package:configurator/models/notifying_events.dart';
import 'package:flutter/material.dart';
import 'package:flutter_libserialport/flutter_libserialport.dart';
Expand All @@ -20,7 +22,7 @@ class DeviceSelector extends StatefulWidget {
class _DeviceSelectorState extends State<DeviceSelector> {
List<SerialDescriptor> _serialDescriptors = [];
String? _selected;
SelectedDeviceState _selectedDeviceState = SelectedDeviceState.idle;
SerialDeviceState _serialDeviceState = SerialDeviceState.idle;

List<SerialDescriptor> _getAvailableDevices() {
List<SerialDescriptor> availableDevices = [];
Expand All @@ -39,63 +41,77 @@ class _DeviceSelectorState extends State<DeviceSelector> {

@override
void initState() {
super.initState();
_loadAvailableDevice();
}

void _showEventSnackBar(
BuildContext context, NotifyingEvents notifyingEvent) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
EventNotifier.eventNotifyingMessage(context, notifyingEvent))));
}

void _onSelected(IListDropdownButtonItem selected) {
// Phase 1: Invoke validation to check selected device is valid.
Globals.instance.currentSerialDevicePort = selected.toValue();

setState(() {
_serialDeviceState = SerialDeviceState.establishing;
});

Globals.instance
.requestHandshakeCurrentDevice()
.then((SerialDeviceState resultState) {
// Phase 2: Invoke handler on validation response.
if (resultState != SerialDeviceState.expired) {
if (mounted) {
setState(() {
_serialDeviceState = resultState;
});
}
}
if (resultState == SerialDeviceState.invalid && mounted) {
_showEventSnackBar(context,
NotifyingEvents.serialDeviceDoesNotResponseMayInvalidDevice);
}

// Phase 3: Invoke request to load configuration saved on device
_requestLoadSavedKeyConfiguration();
}).catchError((error) {
switch (error.runtimeType) {
case SerialPortNotInstantiatedWell _:
case SerialPortCannotOpen _:
case StreamControllerNotInstantiatedWell _:
case TimeoutException _:
if (mounted) {
_showEventSnackBar(
context, NotifyingEvents.serialDeviceDoesNotResponse);
}
}
});
}

/// generally [_onSelected] calls
/// Phase 3: Invoke request to load configuration saved on device
void _requestLoadSavedKeyConfiguration() {
Globals.instance.requestLoadSavedKeyConfiguration().then((value) {});
}

@override
Widget build(BuildContext context) {
return ListDropdownButton(
items: _serialDescriptors,
placeholder: const Text('(select)'),
placeholder:
Text(AppLocalizations.of(context)!.deviceSelectorPlaceholderText),
style: FilledButton.styleFrom(
backgroundColor:
SelectedDeviceStateUtils.getColor(_selectedDeviceState)),
backgroundColor: SerialDeviceStateUtils.getColor(_serialDeviceState)),
onOpenMenu: () {
setState(() {
_loadAvailableDevice();
});
},
onSelected: (selected) async {
Globals.instance.currentSerialDevicePort = selected.toValue();
setState(() {
_selectedDeviceState = SelectedDeviceState.establishing;
});
bool result = await Globals.instance.checkCurrentSerialDeviceIsValid();
setState(() {
_selectedDeviceState =
result ? SelectedDeviceState.valid : SelectedDeviceState.invalid;
});
if (!result) {
setState(() {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(EventNotifier.eventNotifyingMessage(
context,
NotifyingEvents
.serialDeviceDoesNotResponseMayInvalidDevice))));
});
return;
}

bool errorThrownDuringLoad = false;
try {
Globals.instance.loadCurrentSerialDeviceConfig();
} on SerialPortNotInstantiatedWell {
errorThrownDuringLoad = true;
} on SerialPortCannotOpen {
errorThrownDuringLoad = true;
} on StreamControllerNotInstantiatedWell {
errorThrownDuringLoad = true;
} on TimeoutException {
errorThrownDuringLoad = true;
}
if (errorThrownDuringLoad) {
setState(() {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(EventNotifier.eventNotifyingMessage(
context, NotifyingEvents.serialDeviceDoesNotResponse))));
});
}
},
onSelected: _onSelected,
);
}
}
74 changes: 4 additions & 70 deletions configurator/lib/components/key_config_list.dart
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
import 'package:configurator/components/key_config_list_item.dart';
import 'package:configurator/models/key_config_list_item_container.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:configurator/models/keycode.dart';
import 'package:configurator/globals.dart';
import 'package:configurator/widgets/section_title.dart';
import 'package:configurator/widgets/key_detect_field.dart';

class KeyConfigListItemContainer {
KeyConfigListItemContainer(
{required this.name,
this.enabled = false,
this.key = Keycode.undefined,
this.onActivateChange,
this.onKeyChange,});
String name;
bool enabled;
Keycode key;
final Null Function(bool)? onActivateChange;
final Null Function(Keycode)? onKeyChange;
}

class KeyConfigList extends StatefulWidget {
const KeyConfigList({super.key, this.onKeyConfigUpdated});
final Null Function()? onKeyConfigUpdated;
Expand All @@ -31,9 +19,11 @@ class _KeyConfigListState extends State<KeyConfigList> {
void _onChangeHandlerCommons() {
widget.onKeyConfigUpdated?.call();
}

void _onActivateChangeHandler(bool enabled) {
_onChangeHandlerCommons();
}

void _onKeyChangeHandler(Keycode keycode) {
/**
* Todo:
Expand Down Expand Up @@ -436,59 +426,3 @@ class _KeyConfigListState extends State<KeyConfigList> {
);
}
}

class KeyConfigListItem extends StatefulWidget {
final KeyConfigListItemContainer container;
const KeyConfigListItem({super.key, required this.container});

@override
State<KeyConfigListItem> createState() => _KeyConfigListItemState();
}

class _KeyConfigListItemState extends State<KeyConfigListItem> {
@override
Widget build(BuildContext context) {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
widget.container.name,
style: TextStyle(fontSize: 12),
),
Transform.scale(
scale: .6,
child: Switch(
onChanged: (value) {
setState(() {
widget.container.onActivateChange?.call(value);
widget.container.enabled = value;
});
},
value: widget.container.enabled)),
]),
Transform.scale(
scale: .8,
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
height: widget.container.enabled ? 60.0 : 0.0,
alignment: Alignment.centerLeft,
child: widget.container.enabled
? Container(
color: Colors.blue[100], // Optional background color
child: KeyDetectField(
nowKey: widget.container.key,
callbackFunc: (Keycode code) {
widget.container.onKeyChange?.call(code);
widget.container.key = code;
},
),
)
: const SizedBox.shrink(),
),
),
],
);
}
}
66 changes: 66 additions & 0 deletions configurator/lib/components/key_config_list_item.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import 'package:configurator/models/key_config_list_item_container.dart';
import 'package:configurator/models/keycode.dart';
import 'package:configurator/widgets/key_detect_field.dart';
import 'package:flutter/material.dart';

class KeyConfigListItem extends StatefulWidget {
final KeyConfigListItemContainer container;
const KeyConfigListItem({super.key, required this.container});

@override
State<KeyConfigListItem> createState() => _KeyConfigListItemState();
}

class _KeyConfigListItemState extends State<KeyConfigListItem> {
@override
void initState() {
super.initState();
widget.container.onInit?.call();
}

@override
Widget build(BuildContext context) {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
widget.container.name,
style: TextStyle(fontSize: 12),
),
Transform.scale(
scale: .6,
child: Switch(
onChanged: (value) {
setState(() {
widget.container.onActivateChange?.call(value);
widget.container.enabled = value;
});
},
value: widget.container.enabled)),
]),
Transform.scale(
scale: .8,
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
height: widget.container.enabled ? 60.0 : 0.0,
alignment: Alignment.centerLeft,
child: widget.container.enabled
? Container(
color: Colors.blueGrey[50], // Optional background color
child: KeyDetectField(
nowKey: widget.container.key,
onChange: (Keycode code) {
widget.container.onKeyChange?.call(code);
widget.container.key = code;
},
),
)
: const SizedBox.shrink(),
),
),
],
);
}
}
Loading

0 comments on commit 32cd1a9

Please sign in to comment.