diff --git a/lib/data/model/app/shell_func.dart b/lib/data/model/app/shell_func.dart index 9a37f019..1f9cd424 100644 --- a/lib/data/model/app/shell_func.dart +++ b/lib/data/model/app/shell_func.dart @@ -192,6 +192,7 @@ enum StatusCmdType { 'for f in /sys/class/power_supply/*/uevent; do cat "\$f"; echo; done'), nvidia._('nvidia-smi -q -x'), sensors._('sensors'), + cpuBrand._('cat /proc/cpuinfo | grep "model name"'), ; final String cmd; @@ -210,6 +211,7 @@ enum BSDStatusCmdType { mem._('top -l 1 | grep PhysMem'), //temp, host._('hostname'), + cpuBrand._('sysctl -n machdep.cpu.brand_string'), ; final String cmd; diff --git a/lib/data/model/server/cpu.dart b/lib/data/model/server/cpu.dart index 50454b12..1b2c4324 100644 --- a/lib/data/model/server/cpu.dart +++ b/lib/data/model/server/cpu.dart @@ -4,11 +4,14 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:server_box/data/model/server/time_seq.dart'; import 'package:server_box/data/res/status.dart'; +/// Capacity of the FIFO queue const _kCap = 30; class Cpus extends TimeSeq> { Cpus(super.init1, super.init2); + final Map brand = {}; + @override void onUpdate() { _coresCount = now.length; @@ -175,6 +178,22 @@ class SingleCpuCore extends TimeSeqIface { } } +final class CpuBrand { + static Map parse(String raw) { + final lines = raw.split('\n'); + // {brand: count} + final brands = {}; + for (var line in lines) { + if (line.contains('model name')) { + final model = line.split(':').last.trim(); + final count = brands[model] ?? 0; + brands[model] = count + 1; + } + } + return brands; + } +} + final _bsdCpuPercentReg = RegExp(r'(\d+\.\d+)%'); /// TODO: Change this implementation to parse cpu status on BSD system diff --git a/lib/data/model/server/server_status_update_req.dart b/lib/data/model/server/server_status_update_req.dart index 0cd9592c..3b9e5a3f 100644 --- a/lib/data/model/server/server_status_update_req.dart +++ b/lib/data/model/server/server_status_update_req.dart @@ -71,6 +71,9 @@ Future _getLinuxStatus(ServerStatusUpdateReq req) async { try { final cpus = SingleCpuCore.parse(StatusCmdType.cpu.find(segments)); req.ss.cpu.update(cpus); + final brand = CpuBrand.parse(StatusCmdType.cpuBrand.find(segments)); + req.ss.cpu.brand.clear(); + req.ss.cpu.brand.addAll(brand); } catch (e, s) { Loggers.app.warning(e, s); } diff --git a/lib/view/page/server/detail/view.dart b/lib/view/page/server/detail/view.dart index c66fab5e..cd32836b 100644 --- a/lib/view/page/server/detail/view.dart +++ b/lib/view/page/server/detail/view.dart @@ -198,6 +198,29 @@ class _ServerDetailPageState extends State ]); } + final List children = Stores.setting.cpuViewAsProgress.fetch() + ? _buildCPUProgress(ss.cpu) + : [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 17, vertical: 13), + child: SizedBox( + height: 137, + width: _media.size.width - 26 - 34, + child: _buildLineChart( + ss.cpu.spots, + //ss.cpu.rangeX, + tooltipPrefix: 'CPU', + ), + ), + ), + ]; + + if (ss.cpu.brand.isNotEmpty) { + children.add(Column( + children: ss.cpu.brand.entries.map(_buildCpuModelItem).toList(), + ).paddingOnly(top: 13)); + } + return CardX( child: ExpandTile( title: Align( @@ -214,27 +237,21 @@ class _ServerDetailPageState extends State mainAxisSize: MainAxisSize.min, children: details, ), - children: Stores.setting.cpuViewAsProgress.fetch() - ? _buildCPUProgress(ss.cpu) - : [ - Padding( - padding: - const EdgeInsets.symmetric(horizontal: 17, vertical: 13), - child: SizedBox( - height: 137, - width: _media.size.width - 26 - 34, - child: _buildLineChart( - ss.cpu.spots, - //ss.cpu.rangeX, - tooltipPrefix: 'CPU', - ), - ), - ), - ], + children: children, ), ); } + Widget _buildCpuModelItem(MapEntry e) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(e.key, style: UIs.text13), + Text('x ${e.value}', style: UIs.text13Grey), + ], + ).paddingSymmetric(horizontal: 17); + } + Widget _buildDetailPercent(double percent, String timeType) { return Column( mainAxisSize: MainAxisSize.min,