Files
flutter_server_box/lib/data/model/server/cpu.dart
2024-04-08 21:24:00 +08:00

186 lines
4.9 KiB
Dart

import 'dart:collection';
import 'package:fl_chart/fl_chart.dart';
import 'package:toolbox/data/model/app/range.dart';
import 'package:toolbox/data/model/server/time_seq.dart';
import 'package:toolbox/data/res/status.dart';
const _kCap = 30;
class Cpus extends TimeSeq<List<SingleCoreCpu>> {
Cpus(super.init1, super.init2);
@override
void onUpdate() {
_coresCount = now.length;
_totalDelta = now[0].total - pre[0].total;
_user = _getUser();
_sys = _getSys();
_iowait = _getIowait();
_idle = _getIdle();
_updateSpots();
_updateRange();
}
double usedPercent({int coreIdx = 0}) {
if (now.length != pre.length) return 0;
final idleDelta = now[coreIdx].idle - pre[coreIdx].idle;
final totalDelta = now[coreIdx].total - pre[coreIdx].total;
final used = idleDelta / totalDelta;
return used.isNaN ? 0 : 100 - used * 100;
}
int _coresCount = 0;
int get coresCount => _coresCount;
int _totalDelta = 0;
int get totalDelta => _totalDelta;
double _user = 0;
double get user => _user;
double _getUser() {
if (now.length != pre.length) return 0;
final delta = now[0].user - pre[0].user;
final used = delta / totalDelta;
return used.isNaN ? 0 : used * 100;
}
double _sys = 0;
double get sys => _sys;
double _getSys() {
if (now.length != pre.length) return 0;
final delta = now[0].sys - pre[0].sys;
final used = delta / totalDelta;
return used.isNaN ? 0 : used * 100;
}
double _iowait = 0;
double get iowait => _iowait;
double _getIowait() {
if (now.length != pre.length) return 0;
final delta = now[0].iowait - pre[0].iowait;
final used = delta / totalDelta;
return used.isNaN ? 0 : used * 100;
}
double _idle = 0;
double get idle => _idle;
double _getIdle() => 100 - usedPercent();
/// [core1, core2]
/// core1: [FlSpot(0, 10), FlSpot(1, 20), FlSpot(2, 30)]
final _spots = <Fifo<FlSpot>>[];
List<Fifo<FlSpot>> get spots => _spots;
void _updateSpots() {
for (var i = 1; i < now.length; i++) {
if (i >= _spots.length) {
_spots.add(Fifo(capacity: _kCap));
} else {
final item = _spots[i];
final spot = FlSpot(item.count.toDouble(), usedPercent(coreIdx: i));
item.add(spot);
}
}
}
var _rangeX = Range<double>(0.0, _kCap.toDouble());
Range<double> get rangeX => _rangeX;
// var _rangeY = Range<double>(0.0, 100.0);
// Range<double> get rangeY => _rangeY;
void _updateRange() {
double? minX, maxX;
for (var i = 1; i < now.length; i++) {
final item = _spots[i];
if (item.isEmpty) continue;
final first = item.first.x;
final last = item.last.x;
if (minX == null || first < minX) minX = first;
if (maxX == null || last > maxX) maxX = last;
}
if (minX != null && maxX != null) _rangeX = Range(minX, maxX);
// double? minY, maxY;
// for (var i = 1; i < now.length; i++) {
// final item = _spots[i];
// if (item.isEmpty) continue;
// final first = item.first.y;
// final last = item.last.y;
// if (minY == null || first < minY) minY = first;
// if (maxY == null || last > maxY) maxY = last;
// }
// if (minY != null && maxY != null) _rangeY = Range(minY, maxY);
}
}
class SingleCoreCpu extends TimeSeqIface<SingleCoreCpu> {
final String id;
final int user;
final int sys;
final int nice;
final int idle;
final int iowait;
final int irq;
final int softirq;
SingleCoreCpu(
this.id,
this.user,
this.sys,
this.nice,
this.idle,
this.iowait,
this.irq,
this.softirq,
);
int get total => user + sys + nice + idle + iowait + irq + softirq;
@override
bool same(SingleCoreCpu other) => id == other.id;
static List<SingleCoreCpu> parse(String raw) {
final List<SingleCoreCpu> cpus = [];
for (var item in raw.split('\n')) {
if (item == '') break;
final id = item.split(' ').firstOrNull;
if (id == null) continue;
final matches = item.replaceFirst(id, '').trim().split(' ');
cpus.add(
SingleCoreCpu(
id,
int.parse(matches[0]),
int.parse(matches[1]),
int.parse(matches[2]),
int.parse(matches[3]),
int.parse(matches[4]),
int.parse(matches[5]),
int.parse(matches[6]),
),
);
}
return cpus;
}
}
final _bsdCpuPercentReg = RegExp(r'(\d+\.\d+)%');
/// TODO: Change this implementation to parse cpu status on BSD system
///
/// [raw]:
/// CPU usage: 14.70% user, 12.76% sys, 72.52% idle
Cpus parseBsdCpu(String raw) {
final percents = _bsdCpuPercentReg
.allMatches(raw)
.map((e) => double.parse(e.group(1) ?? '0') * 100)
.toList();
if (percents.length != 3) return InitStatus.cpus;
final init = InitStatus.cpus;
init.add([
SingleCoreCpu('cpu', percents[0].toInt(), 0, 0,
percents[2].toInt() + percents[1].toInt(), 0, 0, 0),
]);
return init;
}