diff --git a/lib/data/model/server/nvdia.dart b/lib/data/model/server/nvdia.dart index 5b599649..58d4f4b4 100644 --- a/lib/data/model/server/nvdia.dart +++ b/lib/data/model/server/nvdia.dart @@ -66,21 +66,31 @@ class NvdiaSmi { return null; }); memoryProcesses.removeWhere((element) => element == null); + final percent = gpu + .findElements('utilization') + .firstOrNull + ?.findElements('gpu_util') + .firstOrNull + ?.innerText; + final fanSpeed = gpu.findElements('fan_speed').firstOrNull?.innerText; if (name != null && temp != null && powerDraw != null && powerLimit != null && memory != null) { return NvdiaSmiItem( - name, - int.parse(temp.split(' ').firstOrNull ?? '0'), - '$powerDraw / $powerLimit', - NvdiaSmiMem( + name: name, + uuid: gpu.findElements('uuid').firstOrNull?.innerText ?? '', + temp: int.parse(temp.split(' ').firstOrNull ?? '0'), + percent: int.parse(percent?.split(' ').firstOrNull ?? '0'), + power: '$powerDraw / $powerLimit', + memory: NvdiaSmiMem( int.parse(memoryTotal?.split(' ').firstOrNull ?? '0'), int.parse(memoryUsed?.split(' ').firstOrNull ?? '0'), 'MiB', List.from(memoryProcesses), ), + fanSpeed: int.parse(fanSpeed?.split(' ').firstOrNull ?? '0'), ); } return null; @@ -91,12 +101,23 @@ class NvdiaSmi { } class NvdiaSmiItem { + final String uuid; final String name; final int temp; final String power; final NvdiaSmiMem memory; + final int percent; + final int fanSpeed; - const NvdiaSmiItem(this.name, this.temp, this.power, this.memory); + const NvdiaSmiItem({ + required this.uuid, + required this.name, + required this.temp, + required this.power, + required this.memory, + required this.percent, + required this.fanSpeed, + }); @override String toString() { diff --git a/lib/view/page/server/detail.dart b/lib/view/page/server/detail.dart index 40ad329c..64352385 100644 --- a/lib/view/page/server/detail.dart +++ b/lib/view/page/server/detail.dart @@ -327,43 +327,53 @@ class _ServerDetailPageState extends State } return ListTile( title: Text(item.name, style: UIs.textSize13), - leading: Text( - '${item.temp}°C', - style: UIs.textSize11Grey, - textScaler: _textFactor, - ), subtitle: Text( - '${item.power} - ${mem.used} / ${mem.total} ${mem.unit}', + '${item.power} - ${item.temp} °C\n${mem.used} / ${mem.total} ${mem.unit} - ${item.fanSpeed} RPM', style: UIs.textSize11Grey, textScaler: _textFactor, ), - trailing: InkWell( - onTap: () { - final height = () { - if (processes.length > 5) { - return 5 * 47.0; - } - return processes.length * 47.0; - }(); - context.showRoundDialog( - title: Text(item.name), - child: SizedBox( - width: double.maxFinite, - height: height, - child: ListView.builder( - itemCount: processes.length, - itemBuilder: (_, idx) => _buildGpuProcessItem(processes[idx]), - ), + contentPadding: const EdgeInsets.only(left: 17, right: 17), + trailing: SizedBox( + width: 67, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + '${item.percent}%', + style: UIs.textSize11Grey, + textScaler: _textFactor, ), - actions: [ - TextButton( - onPressed: () => context.pop(), - child: Text(l10n.close), - ) - ], - ); - }, - child: const Icon(Icons.info_outline, size: 17), + IconButton( + onPressed: () { + final height = () { + if (processes.length > 5) { + return 5 * 47.0; + } + return processes.length * 47.0; + }(); + context.showRoundDialog( + title: Text(item.name), + child: SizedBox( + width: double.maxFinite, + height: height, + child: ListView.builder( + itemCount: processes.length, + itemBuilder: (_, idx) => + _buildGpuProcessItem(processes[idx]), + ), + ), + actions: [ + TextButton( + onPressed: () => context.pop(), + child: Text(l10n.close), + ) + ], + ); + }, + icon: const Icon(Icons.info_outline, size: 17), + ), + ], + ), ), ); } @@ -393,6 +403,7 @@ class _ServerDetailPageState extends State mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ + UIs.height13, Text('Memory: ${process.memory} MiB'), UIs.height13, Text('Process: ${process.name}')