diff --git a/README.md b/README.md index ada549bb..f1e90b62 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ A new Flutter project which provide a chart view to display server status data. - + @@ -25,7 +25,7 @@ A new Flutter project which provide a chart view to display server status data. - + diff --git a/lib/data/model/cpu_percent.dart b/lib/data/model/cpu_percent.dart new file mode 100644 index 00000000..9ffb00d6 --- /dev/null +++ b/lib/data/model/cpu_percent.dart @@ -0,0 +1,63 @@ +/// +/// Code generated by jsonToDartModel https://ashamp.github.io/jsonToDartModel/ +/// +class CpuStatus { +/* +{ + "user": 0, + "sys": 0, + "nice": 0, + "idel": 0, + "wa": 0, + "hi": 0, + "si": 0, + "st": 0 +} +*/ + late String id; + late double user; + late double sys; + late double nice; + late double idle; + late double iowait; + late double irq; + late double softirq; + + CpuStatus( + this.id, + this.user, + this.sys, + this.nice, + this.idle, + this.iowait, + this.irq, + this.softirq, + ); + CpuStatus.fromJson(Map json) { + id = json["id"]; + user = json["user"]?.toInt(); + sys = json["sys"]?.toInt(); + nice = json["nice"]?.toInt(); + idle = json["idle"]?.toInt(); + iowait = json["iowait"]?.toInt(); + irq = json["irq"]?.toInt(); + softirq = json["softirq"]?.toInt(); + } + Map toJson() { + final Map data = {}; + data["id"] = id; + data["user"] = user; + data["sys"] = sys; + data["nice"] = nice; + data["idle"] = idle; + data["iowait"] = iowait; + data["irq"] = irq; + data["softirq"] = softirq; + return data; + } + + double get calculateUsedPercent { + final used = idle / (user + sys + nice + iowait + irq + softirq + idle); + return used.isNaN ? 0 : used; + } +} diff --git a/lib/data/model/server_status.dart b/lib/data/model/server_status.dart index ed6e7bb4..88405d3a 100644 --- a/lib/data/model/server_status.dart +++ b/lib/data/model/server_status.dart @@ -1,3 +1,4 @@ +import 'package:toolbox/data/model/cpu_percent.dart'; import 'package:toolbox/data/model/disk_info.dart'; import 'package:toolbox/data/model/tcp_status.dart'; @@ -27,7 +28,7 @@ class ServerStatus { } */ - double? cpuPercent; + List? cpuPercent; List? memList; String? sysVer; String? uptime; @@ -42,7 +43,10 @@ class ServerStatus { this.disk, this.tcp}); ServerStatus.fromJson(Map json) { - cpuPercent = double.parse(json["cpuPercent"]); + cpuPercent = []; + for (var item in json["cpuPercent"]) { + cpuPercent!.add(CpuStatus.fromJson(item)); + } if (json["memList"] != null) { final v = json["memList"]; final arr0 = []; diff --git a/lib/data/provider/server.dart b/lib/data/provider/server.dart index 1355c818..7661a2b6 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server.dart @@ -4,6 +4,7 @@ import 'package:logging/logging.dart'; import 'package:ssh2/ssh2.dart'; import 'package:toolbox/core/extension/stringx.dart'; import 'package:toolbox/core/provider_base.dart'; +import 'package:toolbox/data/model/cpu_percent.dart'; import 'package:toolbox/data/model/server_connection_state.dart'; import 'package:toolbox/data/model/disk_info.dart'; import 'package:toolbox/data/model/server.dart'; @@ -20,8 +21,11 @@ class ServerProvider extends BusyProvider { final logger = Logger('ServerProvider'); + List get emptyCpuPercent => + [CpuStatus('cpu', 0, 0, 0, 0, 0, 0, 0)]; + ServerStatus get emptyStatus => ServerStatus( - cpuPercent: 0, + cpuPercent: emptyCpuPercent, memList: [100, 0], disk: [ DiskInfo( @@ -66,18 +70,15 @@ class ServerProvider extends BusyProvider { } return; } - try { - await Future.wait(_servers.map((s) async { - final idx = _servers.indexOf(s); - final status = await _getData(s.info, idx); - if (status != null) { - _servers[idx].status = status; - notifyListeners(); - } - })); - } catch (e) { - rethrow; - } + + await Future.wait(_servers.map((s) async { + final idx = _servers.indexOf(s); + final status = await _getData(s.info, idx); + if (status != null) { + _servers[idx].status = status; + notifyListeners(); + } + })); } Future startAutoRefresh() async { @@ -133,37 +134,42 @@ class ServerProvider extends BusyProvider { } } - try { - final cpu = await client.execute("top -bn1 | grep Cpu") ?? '0'; - final mem = await client.execute('free -m') ?? ''; - final sysVer = await client.execute('cat /etc/issue.net') ?? 'Unkown'; - final upTime = await client.execute('uptime') ?? 'Failed'; - final disk = await client.execute('df -h') ?? 'Failed'; - final tcp = await client.execute('cat /proc/net/snmp') ?? 'Failed'; + final cpu = await client.execute("cat /proc/stat | grep cpu") ?? ''; + final mem = await client.execute('free -m') ?? ''; + final sysVer = await client.execute('cat /etc/issue.net') ?? ''; + final upTime = await client.execute('uptime') ?? ''; + final disk = await client.execute('df -h') ?? ''; + final tcp = await client.execute('cat /proc/net/snmp') ?? ''; - return ServerStatus( - cpuPercent: _getCPU(cpu), - memList: _getMem(mem), - sysVer: sysVer.trim(), - disk: _getDisk(disk), - uptime: _getUpTime(upTime), - tcp: _getTcp(tcp)); - } catch (e) { - _servers[idx].connectionState = ServerConnectionState.failed; - notifyListeners(); - logger.warning(e); - return null; - } + return ServerStatus( + cpuPercent: _getCPU(cpu), + memList: _getMem(mem), + sysVer: sysVer.trim(), + disk: _getDisk(disk), + uptime: _getUpTime(upTime), + tcp: _getTcp(tcp)); } - double _getCPU(String raw) { - final match = RegExp('[0-9]*\\.[0-9] id,').firstMatch(raw); - if (match == null) { - return 0; + List _getCPU(String raw) { + final List cpus = []; + for (var item in raw.split('\n')) { + if (item == '') break; + final id = item.split(' ').first; + final matches = item.replaceFirst(id, '').trim().split(' '); + cpus.add(CpuStatus( + id, + double.parse(matches[0]), + double.parse(matches[1]), + double.parse(matches[2]), + double.parse(matches[3]), + double.parse(matches[4]), + double.parse(matches[5]), + double.parse(matches[6]))); } - return 100 - - double.parse( - raw.substring(match.start, match.end).replaceAll(' id,', '')); + if (cpus.isEmpty) { + return emptyCpuPercent; + } + return cpus; } String _getUpTime(String raw) { diff --git a/lib/view/page/server/detail.dart b/lib/view/page/server/detail.dart index 97413aec..8107174e 100644 --- a/lib/view/page/server/detail.dart +++ b/lib/view/page/server/detail.dart @@ -17,19 +17,19 @@ class _ServerDetailPageState extends State { @override Widget build(BuildContext context) { return Consumer(builder: (_, provider, __) { - return _buildMainPage(provider.servers.firstWhere((e) => e.client.id == widget.id)); + return _buildMainPage( + provider.servers.firstWhere((e) => e.client.id == widget.id)); }); } Widget _buildMainPage(ServerInfo si) { return Scaffold( - appBar: AppBar(title: Text(si.info.name ?? 'Server Detail'),), + appBar: AppBar( + title: Text(si.info.name ?? 'Server Detail'), + ), body: ListView( - children: [ - _buildCPUView(si.status), - _buildMemView(si.status) - ], - ), + children: [_buildCPUView(si.status), _buildMemView(si.status)], + ), ); } diff --git a/lib/view/page/server/tab.dart b/lib/view/page/server/tab.dart index c25934bf..7d69a817 100644 --- a/lib/view/page/server/tab.dart +++ b/lib/view/page/server/tab.dart @@ -136,7 +136,7 @@ class _ServerPageState extends State Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - _buildPercentCircle(ss.cpuPercent!, 'CPU'), + _buildPercentCircle(ss.cpuPercent!.first.calculateUsedPercent, 'CPU'), _buildPercentCircle( ss.memList![1]! / ss.memList![0]! * 100 + 0.01, 'Mem'), _buildIOData('Net', 'Conn:\n' + ss.tcp!.maxConn!.toString(), diff --git a/screenshots/IMG_3328.PNG b/screenshots/IMG_3328.PNG deleted file mode 100644 index 98c38a3a..00000000 Binary files a/screenshots/IMG_3328.PNG and /dev/null differ diff --git a/screenshots/IMG_3332.PNG b/screenshots/IMG_3332.PNG deleted file mode 100644 index 0c299a3f..00000000 Binary files a/screenshots/IMG_3332.PNG and /dev/null differ diff --git a/screenshots/IMG_3346.PNG b/screenshots/IMG_3346.PNG new file mode 100644 index 00000000..d4d081c0 Binary files /dev/null and b/screenshots/IMG_3346.PNG differ diff --git a/screenshots/IMG_3347.PNG b/screenshots/IMG_3347.PNG new file mode 100644 index 00000000..99124e6d Binary files /dev/null and b/screenshots/IMG_3347.PNG differ