import 'package:xml/xml.dart'; /// [ /// { /// "name": "GeForce RTX 3090", /// "temp": 40, /// "power": "30W / 350W", /// "memory": { /// "total": 24268, /// "used": 240, /// "unit": "MiB", /// "processes": [ /// { /// "pid": 1456, /// "name": "/usr/lib/xorg/Xorg", /// "memory": 40 /// }, /// ] /// }, /// } /// ] /// class NvidiaSmi { static List fromXml(String raw) { final xmlData = XmlDocument.parse(raw); final gpus = xmlData.findAllElements('gpu'); final result = List.generate(gpus.length, (index) { final gpu = gpus.elementAt(index); final name = gpu.findElements('product_name').firstOrNull?.innerText; final temp = gpu .findElements('temperature') .firstOrNull ?.findElements('gpu_temp') .firstOrNull ?.innerText; final power = gpu.findElements('gpu_power_readings').firstOrNull; final powerDraw = power?.findElements('power_draw').firstOrNull?.innerText; final powerLimit = power?.findElements('current_power_limit').firstOrNull?.innerText; final memory = gpu.findElements('fb_memory_usage').firstOrNull; final memoryUsed = memory?.findElements('used').firstOrNull?.innerText; final memoryTotal = memory?.findElements('total').firstOrNull?.innerText; final processes = gpu .findElements('processes') .firstOrNull ?.findElements('process_info'); final memoryProcesses = List.generate(processes?.length ?? 0, (index) { final process = processes?.elementAt(index); final pid = process?.findElements('pid').firstOrNull?.innerText; final name = process?.findElements('process_name').firstOrNull?.innerText; final memory = process?.findElements('used_memory').firstOrNull?.innerText; if (pid != null && name != null && memory != null) { return NvidiaSmiMemProcess( int.tryParse(pid) ?? 0, name, int.tryParse(memory.split(' ').firstOrNull ?? '0') ?? 0, ); } 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 NvidiaSmiItem( name: name, uuid: gpu.findElements('uuid').firstOrNull?.innerText ?? '', temp: int.tryParse(temp.split(' ').firstOrNull ?? '0') ?? 0, percent: int.tryParse(percent?.split(' ').firstOrNull ?? '0') ?? 0, power: '$powerDraw / $powerLimit', memory: NvidiaSmiMem( int.tryParse(memoryTotal?.split(' ').firstOrNull ?? '0') ?? 0, int.tryParse(memoryUsed?.split(' ').firstOrNull ?? '0') ?? 0, 'MiB', List.from(memoryProcesses), ), fanSpeed: int.tryParse(fanSpeed?.split(' ').firstOrNull ?? '0') ?? 0, ); } return null; }); result.removeWhere((element) => element == null); return List.from(result); } } class NvidiaSmiItem { final String uuid; final String name; final int temp; final String power; final NvidiaSmiMem memory; final int percent; final int fanSpeed; const NvidiaSmiItem({ required this.uuid, required this.name, required this.temp, required this.power, required this.memory, required this.percent, required this.fanSpeed, }); @override String toString() { return 'NvdiaSmiItem{name: $name, temp: $temp, power: $power, memory: $memory}'; } } class NvidiaSmiMem { final int total; final int used; final String unit; final List processes; const NvidiaSmiMem(this.total, this.used, this.unit, this.processes); @override String toString() { return 'NvdiaSmiMem{total: $total, used: $used, unit: $unit, processes: $processes}'; } } class NvidiaSmiMemProcess { final int pid; final String name; final int memory; const NvidiaSmiMemProcess(this.pid, this.name, this.memory); @override String toString() { return 'NvdiaSmiMemProcess{pid: $pid, name: $name, memory: $memory}'; } }