Skip to content

Commit eb36c91

Browse files
authored
Merge branch 'main' into pslab_delay
2 parents e1a4f4a + ad6712a commit eb36c91

5 files changed

Lines changed: 175 additions & 62 deletions

File tree

‎lib/l10n/app_en.arb‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,8 @@
565565
"distanceUnitLabel": "mm",
566566
"legacyFirmwareAlertTitle": "Legacy Firmware Detected",
567567
"legacyFirmwareAlertMessage": "We have detected that your PSLab device is running legacy firmware. Please note that support for this firmware has ended. For the best experience and continued support, please update your device to the latest firmware version.",
568+
"unresponsiveDeviceAlertTitle": "PSLab Not Responding",
569+
"unresponsiveDeviceAlertMessage": "A device was detected, but it did not respond like a PSLab. Check that it is running PSLab firmware, then reconnect it.",
568570
"holdPositionForPressure": "Hold position steady for stable pressure reading",
569571
"moveToHigherAltitude": "Move to a higher altitude or floor",
570572
"moveToLowerAltitude": "Move to a lower altitude or floor",

‎lib/providers/board_state_provider.dart‎

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class BoardStateProvider extends ChangeNotifier {
3333

3434
final ValueNotifier<String?> legacyFirmwareNotifier = ValueNotifier(null);
3535

36+
final ValueNotifier<bool> unresponsiveDeviceNotifier = ValueNotifier(false);
37+
3638
static const EventChannel _androidUsbEventChannel =
3739
EventChannel('io.pslab/usb_events');
3840
Timer? _desktopHotplugTimer;
@@ -99,12 +101,14 @@ class BoardStateProvider extends ChangeNotifier {
99101
final comms =
100102
ScienceLabCommon.communicationHandler as PSLabCommunicationHandler;
101103
List<String> ports = rust_api.getAvailablePorts();
104+
bool anyPortFailedHandshake = false;
102105

103106
for (String port in ports) {
107+
bool portOpened = false;
104108
try {
105109
logger.d("Testing port $port for PSLab handshake...");
106110
comms.targetPortName = port;
107-
bool portOpened = await scienceLabCommon.openDevice();
111+
portOpened = await scienceLabCommon.openDevice();
108112

109113
if (portOpened) {
110114
await setPSLabVersionIDs();
@@ -119,18 +123,25 @@ class BoardStateProvider extends ChangeNotifier {
119123
} else {
120124
logger.w(
121125
"Device on $port failed handshake. Closing and moving to next port...");
126+
anyPortFailedHandshake = true;
122127
comms.close();
123128
_resetConnectionState();
124129
}
125130
}
126131
} catch (e) {
127132
logger.w("Exception while testing $port: $e");
133+
if (portOpened && !pslabIsConnected) {
134+
anyPortFailedHandshake = true;
135+
}
128136
comms.close();
129137
_resetConnectionState();
130138
}
131139
}
132140

133141
comms.targetPortName = null;
142+
if (anyPortFailedHandshake) {
143+
_reportUnresponsiveDevice();
144+
}
134145
return false;
135146
}
136147

@@ -200,12 +211,18 @@ class BoardStateProvider extends ChangeNotifier {
200211
}
201212

202213
Future<void> _validateHandshake() async {
203-
await setPSLabVersionIDs();
214+
try {
215+
await setPSLabVersionIDs();
216+
} catch (e) {
217+
logger.w("Version handshake threw: $e");
218+
pslabVersion = 0;
219+
}
204220

205221
if (pslabVersion == 0 || pslabVersionID == 'Not Connected') {
206222
logger.w(
207223
"Port opened, but device failed the Version Handshake. Rejecting generic device.");
208224
_resetConnectionState();
225+
_reportUnresponsiveDevice();
209226
} else {
210227
logger.i("Handshake successful: $pslabVersionID");
211228
pslabIsConnected = true;
@@ -214,6 +231,11 @@ class BoardStateProvider extends ChangeNotifier {
214231
notifyListeners();
215232
}
216233

234+
void _reportUnresponsiveDevice() {
235+
unresponsiveDeviceNotifier.value = false;
236+
unresponsiveDeviceNotifier.value = true;
237+
}
238+
217239
void _resetConnectionState() {
218240
scienceLabCommon.setConnected(false);
219241
pslabIsConnected = false;

‎lib/view/instruments_screen.dart‎

Lines changed: 67 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class _InstrumentsScreenState extends State<InstrumentsScreen> {
2828
String _searchQuery = '';
2929
AppLocalizations get appLocalizations => getIt.get<AppLocalizations>();
3030
late List<_InstrumentData> _instrumentDatas;
31+
bool _unresponsiveAlertQueued = false;
3132

3233
void _onItemTapped(int index) {
3334
_InstrumentData instrument = _instrumentDatas[index];
@@ -88,34 +89,75 @@ class _InstrumentsScreenState extends State<InstrumentsScreen> {
8889
_filteredIndices = indices;
8990
}
9091

92+
void _onLegacyFirmware() {
93+
if (getIt.get<BoardStateProvider>().legacyFirmwareNotifier.value ==
94+
"LegacyFirmwareDetected") {
95+
_showWarningDialog(appLocalizations.legacyFirmwareAlertTitle,
96+
appLocalizations.legacyFirmwareAlertMessage);
97+
}
98+
}
99+
100+
void _onUnresponsiveDevice() {
101+
final notifier = getIt.get<BoardStateProvider>().unresponsiveDeviceNotifier;
102+
if (!notifier.value || _unresponsiveAlertQueued) return;
103+
_unresponsiveAlertQueued = true;
104+
_showWarningDialog(appLocalizations.unresponsiveDeviceAlertTitle,
105+
appLocalizations.unresponsiveDeviceAlertMessage,
106+
onShown: () => notifier.value = false,
107+
onDismissed: () => _unresponsiveAlertQueued = false);
108+
}
109+
110+
void _showWarningDialog(String title, String message,
111+
{VoidCallback? onShown, VoidCallback? onDismissed}) {
112+
WidgetsBinding.instance.addPostFrameCallback((_) {
113+
if (!mounted) return;
114+
onShown?.call();
115+
showDialog<void>(
116+
context: context,
117+
builder: (BuildContext context) {
118+
return AlertDialog(
119+
icon: const Icon(Icons.warning),
120+
title: Text(title),
121+
content: Text(message),
122+
actions: <Widget>[
123+
TextButton(
124+
onPressed: () {
125+
Navigator.of(context).pop();
126+
},
127+
child: Text(appLocalizations.ok),
128+
),
129+
],
130+
);
131+
},
132+
).whenComplete(() => onDismissed?.call());
133+
});
134+
}
135+
136+
@override
137+
void dispose() {
138+
getIt
139+
.get<BoardStateProvider>()
140+
.legacyFirmwareNotifier
141+
.removeListener(_onLegacyFirmware);
142+
getIt
143+
.get<BoardStateProvider>()
144+
.unresponsiveDeviceNotifier
145+
.removeListener(_onUnresponsiveDevice);
146+
super.dispose();
147+
}
148+
91149
@override
92150
void initState() {
93151
super.initState();
94-
getIt.get<BoardStateProvider>().legacyFirmwareNotifier.addListener(() {
95-
if (getIt.get<BoardStateProvider>().legacyFirmwareNotifier.value ==
96-
"LegacyFirmwareDetected") {
97-
WidgetsBinding.instance.addPostFrameCallback((_) {
98-
showDialog<void>(
99-
context: context,
100-
builder: (BuildContext context) {
101-
return AlertDialog(
102-
icon: const Icon(Icons.warning),
103-
title: Text(appLocalizations.legacyFirmwareAlertTitle),
104-
content: Text(appLocalizations.legacyFirmwareAlertMessage),
105-
actions: <Widget>[
106-
TextButton(
107-
onPressed: () {
108-
Navigator.of(context).pop();
109-
},
110-
child: Text(appLocalizations.ok),
111-
),
112-
],
113-
);
114-
},
115-
);
116-
});
117-
}
118-
});
152+
getIt
153+
.get<BoardStateProvider>()
154+
.legacyFirmwareNotifier
155+
.addListener(_onLegacyFirmware);
156+
getIt
157+
.get<BoardStateProvider>()
158+
.unresponsiveDeviceNotifier
159+
.addListener(_onUnresponsiveDevice);
160+
_onUnresponsiveDevice();
119161

120162
_instrumentDatas = [
121163
_InstrumentData(appLocalizations.oscilloscope,

‎lib/view/widgets/digital_waveform_controls.dart‎

Lines changed: 68 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,16 @@ class _DigitalWaveformControlsState extends State<DigitalWaveformControls> {
4646
borderRadius: BorderRadius.circular(6),
4747
),
4848
),
49-
child: Text(
50-
appLocalizations.sqr1.toUpperCase(),
51-
style: TextStyle(
52-
color: Colors.white,
53-
fontSize: 14,
49+
child: Semantics(
50+
selected:
51+
waveGeneratorStateProvider.selectedDigitalWave ==
52+
WaveConst.sqr1,
53+
child: Text(
54+
appLocalizations.sqr1.toUpperCase(),
55+
style: TextStyle(
56+
color: Colors.white,
57+
fontSize: 14,
58+
),
5459
),
5560
),
5661
onPressed: () => {
@@ -74,11 +79,16 @@ class _DigitalWaveformControlsState extends State<DigitalWaveformControls> {
7479
borderRadius: BorderRadius.circular(6),
7580
),
7681
),
77-
child: Text(
78-
appLocalizations.sqr2.toUpperCase(),
79-
style: TextStyle(
80-
color: Colors.white,
81-
fontSize: 14,
82+
child: Semantics(
83+
selected:
84+
waveGeneratorStateProvider.selectedDigitalWave ==
85+
WaveConst.sqr2,
86+
child: Text(
87+
appLocalizations.sqr2.toUpperCase(),
88+
style: TextStyle(
89+
color: Colors.white,
90+
fontSize: 14,
91+
),
8292
),
8393
),
8494
onPressed: () => {
@@ -102,11 +112,16 @@ class _DigitalWaveformControlsState extends State<DigitalWaveformControls> {
102112
borderRadius: BorderRadius.circular(6),
103113
),
104114
),
105-
child: Text(
106-
appLocalizations.sqr3.toUpperCase(),
107-
style: TextStyle(
108-
color: Colors.white,
109-
fontSize: 14,
115+
child: Semantics(
116+
selected:
117+
waveGeneratorStateProvider.selectedDigitalWave ==
118+
WaveConst.sqr3,
119+
child: Text(
120+
appLocalizations.sqr3.toUpperCase(),
121+
style: TextStyle(
122+
color: Colors.white,
123+
fontSize: 14,
124+
),
110125
),
111126
),
112127
onPressed: () => {
@@ -130,11 +145,16 @@ class _DigitalWaveformControlsState extends State<DigitalWaveformControls> {
130145
borderRadius: BorderRadius.circular(6),
131146
),
132147
),
133-
child: Text(
134-
appLocalizations.sqr4.toUpperCase(),
135-
style: TextStyle(
136-
color: Colors.white,
137-
fontSize: 14,
148+
child: Semantics(
149+
selected:
150+
waveGeneratorStateProvider.selectedDigitalWave ==
151+
WaveConst.sqr4,
152+
child: Text(
153+
appLocalizations.sqr4.toUpperCase(),
154+
style: TextStyle(
155+
color: Colors.white,
156+
fontSize: 14,
157+
),
138158
),
139159
),
140160
onPressed: () => {
@@ -167,11 +187,15 @@ class _DigitalWaveformControlsState extends State<DigitalWaveformControls> {
167187
borderRadius: BorderRadius.circular(6),
168188
),
169189
),
170-
child: Text(
171-
appLocalizations.freq,
172-
style: TextStyle(
173-
color: Colors.white,
174-
fontSize: 14,
190+
child: Semantics(
191+
selected: waveGeneratorStateProvider.propSelected ==
192+
WaveConst.frequency,
193+
child: Text(
194+
appLocalizations.freq,
195+
style: TextStyle(
196+
color: Colors.white,
197+
fontSize: 14,
198+
),
175199
),
176200
),
177201
onPressed: () => {
@@ -198,11 +222,16 @@ class _DigitalWaveformControlsState extends State<DigitalWaveformControls> {
198222
borderRadius: BorderRadius.circular(6),
199223
),
200224
),
201-
child: Text(
202-
appLocalizations.phase,
203-
style: TextStyle(
204-
color: Colors.white,
205-
fontSize: 14,
225+
child: Semantics(
226+
selected:
227+
waveGeneratorStateProvider.propSelected ==
228+
WaveConst.phase,
229+
child: Text(
230+
appLocalizations.phase,
231+
style: TextStyle(
232+
color: Colors.white,
233+
fontSize: 14,
234+
),
206235
),
207236
),
208237
onPressed: () => {
@@ -228,11 +257,15 @@ class _DigitalWaveformControlsState extends State<DigitalWaveformControls> {
228257
borderRadius: BorderRadius.circular(6),
229258
),
230259
),
231-
child: Text(
232-
appLocalizations.duty,
233-
style: TextStyle(
234-
color: Colors.white,
235-
fontSize: 14,
260+
child: Semantics(
261+
selected: waveGeneratorStateProvider.propSelected ==
262+
WaveConst.duty,
263+
child: Text(
264+
appLocalizations.duty,
265+
style: TextStyle(
266+
color: Colors.white,
267+
fontSize: 14,
268+
),
236269
),
237270
),
238271
onPressed: () => {

0 commit comments

Comments
 (0)