Skip to content

Commit 147436f

Browse files
authored
Add base station to logs status (#223)
1 parent e4d4a33 commit 147436f

File tree

2 files changed

+154
-99
lines changed

2 files changed

+154
-99
lines changed

lib/src/models/data/logs.dart

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ class LogsModel extends Model {
4040
/// The most recent [maxLogCount] received for [Device.SUBSYSTEMS]
4141
final ListQueue<BurtLog> autonomyLogs = ListQueue();
4242

43+
/// The most recent [maxLogCount] of messages from the base station
44+
final ListQueue<BurtLog> baseStationLogs = ListQueue();
45+
4346
/// The most recent [maxLogCount] of messages from the dashboard
4447
final ListQueue<BurtLog> dashboardLogs = ListQueue();
4548

@@ -67,6 +70,7 @@ class LogsModel extends Model {
6770
Device.SUBSYSTEMS => subsystemLogs,
6871
Device.VIDEO => videoLogs,
6972
Device.AUTONOMY => autonomyLogs,
73+
Device.BASE_STATION => baseStationLogs,
7074
Device.DASHBOARD => dashboardLogs,
7175
null => allLogs,
7276
_ => null,
@@ -87,12 +91,34 @@ class LogsModel extends Model {
8791
notifyListeners();
8892

8993
// Show important messages to the footer.
90-
if (display) { // Prevents showing dashboard messages that have already been shown
94+
if (display) {
95+
// Prevents showing dashboard messages that have already been shown
9196
switch (log.level) {
92-
case BurtLogLevel.critical: models.home.setMessage(severity: Severity.critical, text: log.title, permanent: true, logMessage: false);
93-
case BurtLogLevel.warning: models.home.setMessage(severity: Severity.warning, text: log.title, logMessage: false);
94-
case BurtLogLevel.error: models.home.setMessage(severity: Severity.error, text: log.title, logMessage: false);
95-
case BurtLogLevel.info: models.home.setMessage(severity: Severity.info, text: "${log.device.humanName}: ${log.title}", logMessage: false);
97+
case BurtLogLevel.critical:
98+
models.home.setMessage(
99+
severity: Severity.critical,
100+
text: log.title,
101+
permanent: true,
102+
logMessage: false,
103+
);
104+
case BurtLogLevel.warning:
105+
models.home.setMessage(
106+
severity: Severity.warning,
107+
text: log.title,
108+
logMessage: false,
109+
);
110+
case BurtLogLevel.error:
111+
models.home.setMessage(
112+
severity: Severity.error,
113+
text: log.title,
114+
logMessage: false,
115+
);
116+
case BurtLogLevel.info:
117+
models.home.setMessage(
118+
severity: Severity.info,
119+
text: "${log.device.humanName}: ${log.title}",
120+
logMessage: false,
121+
);
96122
case BurtLogLevel.debug:
97123
case BurtLogLevel.trace:
98124
case BurtLogLevel.BURT_LOG_LEVEL_UNDEFINED:
@@ -120,6 +146,7 @@ class LogsModel extends Model {
120146
subsystemLogs.clear();
121147
videoLogs.clear();
122148
autonomyLogs.clear();
149+
baseStationLogs.clear();
123150
dashboardLogs.clear();
124151
deviceSeverity.clear();
125152
models.home.clear(clearErrors: true);

lib/src/pages/logs.dart

Lines changed: 122 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -36,38 +36,37 @@ class DeviceStatuses extends ReusableReactiveWidget<LogsViewModel> {
3636
);
3737
}
3838

39-
static const _devices = [Device.SUBSYSTEMS, Device.VIDEO, Device.AUTONOMY];
40-
4139
@override
4240
Widget build(BuildContext context, LogsViewModel model) => Row(
4341
mainAxisAlignment: MainAxisAlignment.center,
4442
children: [
45-
for (final device in _devices)
43+
for (final socket in models.sockets.sockets)
4644
SizedBox(
4745
width: 250,
4846
child: Card(
4947
child: Column(
5048
children: [
5149
ListTile(
52-
onTap: () => model.resetDevice(device),
50+
onTap: () => model.resetDevice(socket.device),
5351
leading: const Icon(Icons.restart_alt),
54-
title: Text("Reset ${device.humanName}"),
52+
title: Text("Reset ${socket.device.humanName}"),
5553
subtitle: const Text("The device will reboot"),
5654
),
5755
Padding(
5856
padding: const EdgeInsets.all(4),
5957
child: Row(
6058
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
6159
children: [
62-
Icon(Icons.circle, color: getStatusColor(device)),
60+
Icon(Icons.circle, color: getStatusColor(socket.device)),
6361
NetworkStatusIcon(
64-
device: device,
62+
device: socket.device,
6563
tooltip: "Ping Device",
66-
onPressed: Platform.isWindows
67-
? () => model.ping(device)
68-
: null,
64+
onPressed:
65+
Platform.isWindows
66+
? () => model.ping(socket.device)
67+
: null,
6968
),
70-
sshButton(device) ?? Container(),
69+
sshButton(socket.device) ?? Container(),
7170
],
7271
),
7372
),
@@ -97,8 +96,18 @@ class LogsOptions extends ReusableReactiveWidget<LogsOptionsViewModel> {
9796
initialSelection: model.deviceFilter,
9897
onSelected: model.setDeviceFilter,
9998
dropdownMenuEntries: [
100-
for (final device in [Device.SUBSYSTEMS, Device.VIDEO, Device.AUTONOMY, Device.DASHBOARD, null])
101-
DropdownMenuEntry(label: device?.humanName ?? "All", value: device),
99+
for (final device in [
100+
Device.SUBSYSTEMS,
101+
Device.VIDEO,
102+
Device.AUTONOMY,
103+
Device.BASE_STATION,
104+
Device.DASHBOARD,
105+
null,
106+
])
107+
DropdownMenuEntry(
108+
label: device?.humanName ?? "All",
109+
value: device,
110+
),
102111
],
103112
),
104113
const SizedBox(width: 8),
@@ -134,74 +143,87 @@ class LogsOptions extends ReusableReactiveWidget<LogsOptionsViewModel> {
134143

135144
/// Returns a list of widgets that are used as the header or footer actions for the log page
136145
List<Widget> getLogsActions(BuildContext context, LogsViewModel model) => [
137-
IconButton(
138-
icon: const Icon(Icons.help, color: Colors.white),
139-
tooltip: "Help",
140-
onPressed: () => showDialog<void>(
146+
IconButton(
147+
icon: const Icon(Icons.help, color: Colors.white),
148+
tooltip: "Help",
149+
onPressed:
150+
() => showDialog<void>(
141151
context: context,
142-
builder: (context) => AlertDialog(
143-
scrollable: true,
144-
title: const Text("Logs Help"),
145-
content: Column(
146-
mainAxisSize: MainAxisSize.min,
147-
children: [
148-
const Text(
149-
"This page contains all logs received by the dashboard.\nSelecting a level means that only messages of that level or higher will be shown.",
150-
textAlign: TextAlign.center,
151-
),
152-
const SizedBox(height: 4),
153-
ListTile(
154-
leading: criticalWidget,
155-
title: const Text("Critical"),
156-
subtitle: const Text("The rover is in a broken state and may shutdown"),),
157-
const ListTile(
158-
leading: errorWidget,
159-
title: Text("Error"),
160-
subtitle: Text("Something you tried didn't work, but the rover can still function"),
161-
),
162-
const ListTile(
163-
leading: warningWidget,
164-
title: Text("Warning"),
165-
subtitle: Text("Something may have gone wrong, you should check it out"),
166-
),
167-
ListTile(
168-
leading: infoWidget,
169-
title: const Text("Info"),
170-
subtitle: const Text("The rover is functioning normally"),
171-
),
172-
const ListTile(
173-
leading: debugWidget,
174-
title: Text("Debug"),
175-
subtitle: Text("Extra information that shows what the rover's thinking"),
176-
),
177-
const ListTile(
178-
leading: traceWidget,
179-
title: Text("Trace"),
180-
subtitle: Text("Values from the code to debug specific issues"),
152+
builder:
153+
(context) => AlertDialog(
154+
scrollable: true,
155+
title: const Text("Logs Help"),
156+
content: Column(
157+
mainAxisSize: MainAxisSize.min,
158+
children: [
159+
const Text(
160+
"This page contains all logs received by the dashboard.\nSelecting a level means that only messages of that level or higher will be shown.",
161+
textAlign: TextAlign.center,
162+
),
163+
const SizedBox(height: 4),
164+
ListTile(
165+
leading: criticalWidget,
166+
title: const Text("Critical"),
167+
subtitle: const Text(
168+
"The rover is in a broken state and may shutdown",
169+
),
170+
),
171+
const ListTile(
172+
leading: errorWidget,
173+
title: Text("Error"),
174+
subtitle: Text(
175+
"Something you tried didn't work, but the rover can still function",
176+
),
177+
),
178+
const ListTile(
179+
leading: warningWidget,
180+
title: Text("Warning"),
181+
subtitle: Text(
182+
"Something may have gone wrong, you should check it out",
183+
),
184+
),
185+
ListTile(
186+
leading: infoWidget,
187+
title: const Text("Info"),
188+
subtitle: const Text("The rover is functioning normally"),
189+
),
190+
const ListTile(
191+
leading: debugWidget,
192+
title: Text("Debug"),
193+
subtitle: Text(
194+
"Extra information that shows what the rover's thinking",
195+
),
196+
),
197+
const ListTile(
198+
leading: traceWidget,
199+
title: Text("Trace"),
200+
subtitle: Text(
201+
"Values from the code to debug specific issues",
202+
),
203+
),
204+
const SizedBox(height: 12),
205+
],
181206
),
182-
const SizedBox(height: 12),
183-
],
184-
),
185-
actions: [
186-
ElevatedButton(
187-
onPressed: () => Navigator.of(context).pop(),
188-
child: const Text("Close"),
207+
actions: [
208+
ElevatedButton(
209+
onPressed: () => Navigator.of(context).pop(),
210+
child: const Text("Close"),
211+
),
212+
],
189213
),
190-
],
191-
),
192214
),
193-
),
194-
IconButton(
195-
icon: const Icon(Icons.vertical_align_bottom, color: Colors.white),
196-
onPressed: model.jumpToBottom,
197-
tooltip: "Jump to Bottom",
198-
),
199-
IconButton(
200-
icon: const Icon(Icons.delete_forever, color: Colors.white),
201-
onPressed: models.logs.clear,
202-
tooltip: "Clear Logs",
203-
),
204-
];
215+
),
216+
IconButton(
217+
icon: const Icon(Icons.vertical_align_bottom, color: Colors.white),
218+
onPressed: model.jumpToBottom,
219+
tooltip: "Jump to Bottom",
220+
),
221+
IconButton(
222+
icon: const Icon(Icons.delete_forever, color: Colors.white),
223+
onPressed: models.logs.clear,
224+
tooltip: "Clear Logs",
225+
),
226+
];
205227

206228
/// The logs page, containing the [LogsOptions] and [LogsBody] widgets.
207229
///
@@ -220,14 +242,16 @@ class LogsState extends State<LogsPage> {
220242

221243
@override
222244
Widget build(BuildContext context) => Scaffold(
223-
body: Column(children: [
224-
const SizedBox(height: 12),
225-
DeviceStatuses(model),
226-
const SizedBox(height: 12),
227-
LogsOptions(model.options),
228-
const Divider(),
229-
Expanded(child: LogsBody(model)),
230-
],),
245+
body: Column(
246+
children: [
247+
const SizedBox(height: 12),
248+
DeviceStatuses(model),
249+
const SizedBox(height: 12),
250+
LogsOptions(model.options),
251+
const Divider(),
252+
Expanded(child: LogsBody(model)),
253+
],
254+
),
231255
appBar: AppBar(
232256
title: const Text("Logs"),
233257
actions: getLogsActions(context, model),
@@ -244,14 +268,15 @@ class LogsBody extends ReusableReactiveWidget<LogsViewModel> {
244268
const LogsBody(super.model);
245269

246270
@override
247-
Widget build(BuildContext context, LogsViewModel model) => model.logs.isEmpty
248-
? const Center(child: Text("No logs yet"))
249-
: ListView.builder(
250-
itemCount: model.logs.length,
251-
controller: model.scrollController,
252-
reverse: true,
253-
itemBuilder: (context, index) => LogWidget(model.logs[index]),
254-
);
271+
Widget build(BuildContext context, LogsViewModel model) =>
272+
model.logs.isEmpty
273+
? const Center(child: Text("No logs yet"))
274+
: ListView.builder(
275+
itemCount: model.logs.length,
276+
controller: model.scrollController,
277+
reverse: true,
278+
itemBuilder: (context, index) => LogWidget(model.logs[index]),
279+
);
255280
}
256281

257282
/// The icon to show for logs with [BurtLogLevel.critical].
@@ -289,6 +314,9 @@ class LogWidget extends StatelessWidget {
289314
Widget build(BuildContext context) => ListTile(
290315
leading: icon,
291316
title: Text(log.title),
292-
subtitle: log.body.isEmpty ? Text(log.device.humanName) : Text("${log.device.humanName}\n${log.body}".trim()),
317+
subtitle:
318+
log.body.isEmpty
319+
? Text(log.device.humanName)
320+
: Text("${log.device.humanName}\n${log.body}".trim()),
293321
);
294322
}

0 commit comments

Comments
 (0)