new: sensors view (#285)

This commit is contained in:
lollipopkit
2024-02-23 12:33:42 +08:00
parent fad3f41e58
commit 1f586a2c31
23 changed files with 348 additions and 34 deletions

View File

@@ -1294,6 +1294,12 @@ abstract class S {
/// **'s'** /// **'s'**
String get second; String get second;
/// No description provided for @sensors.
///
/// In en, this message translates to:
/// **'Sensor'**
String get sensors;
/// No description provided for @sequence. /// No description provided for @sequence.
/// ///
/// In en, this message translates to: /// In en, this message translates to:

View File

@@ -627,6 +627,9 @@ class SDe extends S {
@override @override
String get second => 's'; String get second => 's';
@override
String get sensors => 'Sensor';
@override @override
String get sequence => 'Sequenz'; String get sequence => 'Sequenz';

View File

@@ -627,6 +627,9 @@ class SEn extends S {
@override @override
String get second => 's'; String get second => 's';
@override
String get sensors => 'Sensor';
@override @override
String get sequence => 'Sequence'; String get sequence => 'Sequence';

View File

@@ -627,6 +627,9 @@ class SFr extends S {
@override @override
String get second => 's'; String get second => 's';
@override
String get sensors => 'Capteur';
@override @override
String get sequence => 'Séquence'; String get sequence => 'Séquence';

View File

@@ -627,6 +627,9 @@ class SId extends S {
@override @override
String get second => 'S'; String get second => 'S';
@override
String get sensors => 'Sensor';
@override @override
String get sequence => 'Urutan'; String get sequence => 'Urutan';

View File

@@ -627,6 +627,9 @@ class SZh extends S {
@override @override
String get second => ''; String get second => '';
@override
String get sensors => '传感器';
@override @override
String get sequence => '顺序'; String get sequence => '顺序';
@@ -1505,6 +1508,9 @@ class SZhTw extends SZh {
@override @override
String get second => ''; String get second => '';
@override
String get sensors => '传感器';
@override @override
String get sequence => '順序'; String get sequence => '順序';

View File

@@ -586,7 +586,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 771; CURRENT_PROJECT_VERSION = 775;
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -596,7 +596,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.771; MARKETING_VERSION = 1.0.775;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -720,7 +720,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 771; CURRENT_PROJECT_VERSION = 775;
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -730,7 +730,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.771; MARKETING_VERSION = 1.0.775;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -748,7 +748,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 771; CURRENT_PROJECT_VERSION = 775;
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -758,7 +758,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.771; MARKETING_VERSION = 1.0.775;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -779,7 +779,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 771; CURRENT_PROJECT_VERSION = 775;
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@@ -792,7 +792,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.0.771; MARKETING_VERSION = 1.0.775;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
@@ -818,7 +818,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 771; CURRENT_PROJECT_VERSION = 775;
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@@ -831,7 +831,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.0.771; MARKETING_VERSION = 1.0.775;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@@ -854,7 +854,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 771; CURRENT_PROJECT_VERSION = 775;
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@@ -867,7 +867,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.0.771; MARKETING_VERSION = 1.0.775;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@@ -890,7 +890,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 771; CURRENT_PROJECT_VERSION = 775;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
@@ -902,7 +902,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.771; MARKETING_VERSION = 1.0.775;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
@@ -931,7 +931,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 771; CURRENT_PROJECT_VERSION = 775;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
@@ -943,7 +943,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.771; MARKETING_VERSION = 1.0.775;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
PRODUCT_NAME = ServerBox; PRODUCT_NAME = ServerBox;
@@ -969,7 +969,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 771; CURRENT_PROJECT_VERSION = 775;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
@@ -981,7 +981,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.771; MARKETING_VERSION = 1.0.775;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
PRODUCT_NAME = ServerBox; PRODUCT_NAME = ServerBox;

View File

@@ -258,5 +258,11 @@ class PropertyListenable<T> extends ValueListenable<T> {
} }
@override @override
T get value => box.get(key, defaultValue: defaultValue); T get value {
final val = box.get(key, defaultValue: defaultValue);
if (val == null || val is! T) {
return defaultValue!;
}
return val;
}
} }

View File

@@ -200,6 +200,7 @@ enum StatusCmdType {
diskio, diskio,
battery, battery,
nvidia, nvidia,
sensors,
; ;
} }
@@ -220,6 +221,7 @@ const _statusCmds = [
'cat /proc/diskstats', 'cat /proc/diskstats',
'for f in /sys/class/power_supply/*/uevent; do cat "\$f"; echo; done', 'for f in /sys/class/power_supply/*/uevent; do cat "\$f"; echo; done',
'nvidia-smi -q -x', 'nvidia-smi -q -x',
'sensors -j',
]; ];
enum BSDStatusCmdType { enum BSDStatusCmdType {

View File

@@ -0,0 +1,175 @@
import 'dart:convert';
import 'package:toolbox/core/extension/listx.dart';
import 'package:toolbox/data/res/logger.dart';
final class SensorAdaptor {
final String raw;
const SensorAdaptor(this.raw);
static const acpiRaw = 'ACPI interface';
static const pciRaw = 'PCI adapter';
static const virtualRaw = 'Virtual device';
static const isaRaw = 'ISA adapter';
static const acpi = SensorAdaptor(acpiRaw);
static const pci = SensorAdaptor(pciRaw);
static const virtual = SensorAdaptor(virtualRaw);
static const isa = SensorAdaptor(isaRaw);
static SensorAdaptor parse(String raw) => switch (raw) {
acpiRaw => acpi,
pciRaw => pci,
virtualRaw => virtual,
isaRaw => isa,
_ => SensorAdaptor(raw),
};
}
final class SensorTemp {
final double? current;
final double? max;
final double? min;
const SensorTemp({this.current, this.max, this.min});
@override
String toString() {
return 'SensorTemp{current: $current, max: $max, min: $min}';
}
@override
operator ==(Object other) {
if (identical(this, other)) return true;
return other is SensorTemp &&
other.current == current &&
other.max == max &&
other.min == min;
}
@override
int get hashCode => current.hashCode ^ max.hashCode ^ min.hashCode;
}
final class SensorItem {
final String device;
final SensorAdaptor adapter;
final Map<String, SensorTemp> props;
const SensorItem({
required this.device,
required this.adapter,
required this.props,
});
static List<SensorItem> parse(String raw) {
final rmErrRaw = raw.split('\n')
..removeWhere((element) => element.contains('ERROR:'));
final map = json.decode(rmErrRaw.join('\n')) as Map<String, dynamic>;
final items = <SensorItem>[];
for (final key in map.keys) {
try {
final adapter = SensorAdaptor.parse(map[key]['Adapter'] as String);
final props = <String, SensorTemp>{};
for (final subKey in map[key].keys) {
if (subKey == 'Adapter') {
continue;
}
final subMap = map[key][subKey] as Map<String, dynamic>;
final currentKey =
subMap.keys.toList().firstWhereOrNull((e) => e.endsWith('input'));
final current = subMap[currentKey] as double?;
final maxKey = subMap.keys
.toList()
.firstWhereOrNull((e) => e.endsWith('max') || e.endsWith('crit'));
final max = subMap[maxKey] as double?;
final minKey =
subMap.keys.toList().firstWhereOrNull((e) => e.endsWith('min'));
final min = subMap[minKey] as double?;
if (current == null && max == null && min == null) {
continue;
}
props[subKey] = SensorTemp(current: current, max: max, min: min);
}
items.add(SensorItem(device: key, adapter: adapter, props: props));
} catch (e, s) {
Loggers.parse.warning(e, s);
continue;
}
}
return items;
}
static const sensorsRaw = '''
{
"coretemp-isa-0000":{
"Adapter": "ISA adapter",
"Package id 0":{
"temp1_input": 51.000,
"temp1_max": 105.000,
"temp1_crit": 105.000,
"temp1_crit_alarm": 0.000
},
"Core 0":{
"temp2_input": 40.000,
"temp2_max": 105.000,
"temp2_crit": 105.000,
"temp2_crit_alarm": 0.000
},
"Core 1":{
"temp3_input": 40.000,
"temp3_max": 105.000,
"temp3_crit": 105.000,
"temp3_crit_alarm": 0.000
},
"Core 2":{
"temp4_input": 40.000,
"temp4_max": 105.000,
"temp4_crit": 105.000,
"temp4_crit_alarm": 0.000
},
"Core 3":{
"temp5_input": 40.000,
"temp5_max": 105.000,
"temp5_crit": 105.000,
"temp5_crit_alarm": 0.000
}
},
"acpitz-acpi-0":{
"Adapter": "ACPI interface",
"temp1":{
"temp1_input": 27.800,
"temp1_crit": 119.000
}
},
"iwlwifi_1-virtual-0":{
"Adapter": "Virtual device",
"temp1":{
ERROR: Can't get value of subfeature temp1_input: Can't read
}
},
"nvme-pci-0400":{
"Adapter": "PCI adapter",
"Composite":{
"temp1_input": 35.850,
"temp1_max": 83.850,
"temp1_min": -273.150,
"temp1_crit": 84.850,
"temp1_alarm": 0.000
},
"Sensor 1":{
"temp2_input": 35.850,
"temp2_max": 65261.850,
"temp2_min": -273.150
},
"Sensor 2":{
"temp3_input": 37.850,
"temp3_max": 65261.850,
"temp3_min": -273.150
}
}
}
''';
}

View File

@@ -7,6 +7,7 @@ import 'package:toolbox/data/model/server/disk.dart';
import 'package:toolbox/data/model/server/memory.dart'; import 'package:toolbox/data/model/server/memory.dart';
import 'package:toolbox/data/model/server/net_speed.dart'; import 'package:toolbox/data/model/server/net_speed.dart';
import 'package:toolbox/data/model/server/nvdia.dart'; import 'package:toolbox/data/model/server/nvdia.dart';
import 'package:toolbox/data/model/server/sensors.dart';
import 'package:toolbox/data/model/server/server_private_info.dart'; import 'package:toolbox/data/model/server/server_private_info.dart';
import 'package:toolbox/data/model/server/system.dart'; import 'package:toolbox/data/model/server/system.dart';
import 'package:toolbox/data/model/server/temp.dart'; import 'package:toolbox/data/model/server/temp.dart';
@@ -55,6 +56,7 @@ class ServerStatus {
List<NvidiaSmiItem>? nvidia; List<NvidiaSmiItem>? nvidia;
final List<Battery> batteries = []; final List<Battery> batteries = [];
final Map<StatusCmdType, String> more = {}; final Map<StatusCmdType, String> more = {};
final List<SensorItem> sensors = [];
ServerStatus({ ServerStatus({
required this.cpu, required this.cpu,

View File

@@ -1,5 +1,6 @@
import 'package:toolbox/data/model/server/battery.dart'; import 'package:toolbox/data/model/server/battery.dart';
import 'package:toolbox/data/model/server/nvdia.dart'; import 'package:toolbox/data/model/server/nvdia.dart';
import 'package:toolbox/data/model/server/sensors.dart';
import 'package:toolbox/data/model/server/server.dart'; import 'package:toolbox/data/model/server/server.dart';
import 'package:toolbox/data/model/server/system.dart'; import 'package:toolbox/data/model/server/system.dart';
import 'package:toolbox/data/res/logger.dart'; import 'package:toolbox/data/res/logger.dart';
@@ -143,6 +144,16 @@ Future<ServerStatus> _getLinuxStatus(ServerStatusUpdateReq req) async {
Loggers.parse.warning(e, s); Loggers.parse.warning(e, s);
} }
try {
final sensors = SensorItem.parse(StatusCmdType.sensors.find(segments));
if (sensors.isNotEmpty) {
req.ss.sensors.clear();
req.ss.sensors.addAll(sensors);
}
} catch (e, s) {
Loggers.parse.warning(e, s);
}
return req.ss; return req.ss;
} }

View File

@@ -2,9 +2,9 @@
class BuildData { class BuildData {
static const String name = "ServerBox"; static const String name = "ServerBox";
static const int build = 773; static const int build = 775;
static const String engine = "3.19.1"; static const String engine = "3.19.0";
static const String buildAt = "2024-02-22 11:55:07"; static const String buildAt = "2024-02-23 09:28:28";
static const int modifications = 8; static const int modifications = 2;
static const int script = 38; static const int script = 38;
} }

View File

@@ -12,6 +12,7 @@ abstract final class Defaults {
'gpu', 'gpu',
'disk', 'disk',
'net', 'net',
'sensor',
'temp', 'temp',
'battery' 'battery'
]; ];

View File

@@ -199,6 +199,7 @@
"save": "Speichern", "save": "Speichern",
"saved": "Gerettet", "saved": "Gerettet",
"second": "s", "second": "s",
"sensors": "Sensor",
"sequence": "Sequenz", "sequence": "Sequenz",
"server": "Server", "server": "Server",
"serverDetailOrder": "Reihenfolge der Widgets auf der Detailseite", "serverDetailOrder": "Reihenfolge der Widgets auf der Detailseite",

View File

@@ -199,6 +199,7 @@
"save": "Save", "save": "Save",
"saved": "Saved", "saved": "Saved",
"second": "s", "second": "s",
"sensors": "Sensor",
"sequence": "Sequence", "sequence": "Sequence",
"server": "Server", "server": "Server",
"serverDetailOrder": "Detail page widget order", "serverDetailOrder": "Detail page widget order",

View File

@@ -199,6 +199,7 @@
"save": "Enregistrer", "save": "Enregistrer",
"saved": "Enregistré", "saved": "Enregistré",
"second": "s", "second": "s",
"sensors": "Capteur",
"sequence": "Séquence", "sequence": "Séquence",
"server": "Serveur", "server": "Serveur",
"serverDetailOrder": "Ordre des widgets de la page de détails", "serverDetailOrder": "Ordre des widgets de la page de détails",

View File

@@ -199,6 +199,7 @@
"save": "Menyimpan", "save": "Menyimpan",
"saved": "Diselamatkan", "saved": "Diselamatkan",
"second": "S", "second": "S",
"sensors": "Sensor",
"sequence": "Urutan", "sequence": "Urutan",
"server": "Server", "server": "Server",
"serverDetailOrder": "Detail pesanan widget halaman", "serverDetailOrder": "Detail pesanan widget halaman",

View File

@@ -199,6 +199,7 @@
"save": "保存", "save": "保存",
"saved": "已保存", "saved": "已保存",
"second": "秒", "second": "秒",
"sensors": "传感器",
"sequence": "顺序", "sequence": "顺序",
"server": "服务器", "server": "服务器",
"serverDetailOrder": "详情页部件顺序", "serverDetailOrder": "详情页部件顺序",

View File

@@ -199,6 +199,7 @@
"save": "保存", "save": "保存",
"saved": "已保存", "saved": "已保存",
"second": "秒", "second": "秒",
"sensors": "传感器",
"sequence": "順序", "sequence": "順序",
"server": "服務器", "server": "服務器",
"serverDetailOrder": "詳情頁部件順序", "serverDetailOrder": "詳情頁部件順序",

View File

@@ -10,6 +10,7 @@ import 'package:toolbox/data/model/server/cpu.dart';
import 'package:toolbox/data/model/server/disk.dart'; import 'package:toolbox/data/model/server/disk.dart';
import 'package:toolbox/data/model/server/net_speed.dart'; import 'package:toolbox/data/model/server/net_speed.dart';
import 'package:toolbox/data/model/server/nvdia.dart'; import 'package:toolbox/data/model/server/nvdia.dart';
import 'package:toolbox/data/model/server/sensors.dart';
import 'package:toolbox/data/model/server/server_private_info.dart'; import 'package:toolbox/data/model/server/server_private_info.dart';
import 'package:toolbox/data/model/server/system.dart'; import 'package:toolbox/data/model/server/system.dart';
import 'package:toolbox/data/res/store.dart'; import 'package:toolbox/data/res/store.dart';
@@ -47,6 +48,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
_buildGpuView, _buildGpuView,
_buildDiskView, _buildDiskView,
_buildNetView, _buildNetView,
_buildSensors,
_buildTemperature, _buildTemperature,
_buildBatteries, _buildBatteries,
], ],
@@ -316,7 +318,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
} }
Widget _buildGpuView(ServerStatus ss) { Widget _buildGpuView(ServerStatus ss) {
if (ss.nvidia == null) return UIs.placeholder; if (ss.nvidia == null || ss.nvidia?.isEmpty == true) return UIs.placeholder;
final children = ss.nvidia?.map((e) => _buildGpuItem(e)).toList() ?? []; final children = ss.nvidia?.map((e) => _buildGpuItem(e)).toList() ?? [];
return CardX( return CardX(
child: ExpandTile( child: ExpandTile(
@@ -331,10 +333,6 @@ class _ServerDetailPageState extends State<ServerDetailPage>
Widget _buildGpuItem(NvidiaSmiItem item) { Widget _buildGpuItem(NvidiaSmiItem item) {
final mem = item.memory; final mem = item.memory;
final processes = mem.processes; final processes = mem.processes;
final children = <Widget>[];
if (processes.isNotEmpty) {
children.addAll(processes.map((e) => _buildGpuProcessItem(e)));
}
return ListTile( return ListTile(
title: Text(item.name, style: UIs.text13), title: Text(item.name, style: UIs.text13),
leading: Text( leading: Text(
@@ -664,6 +662,51 @@ class _ServerDetailPageState extends State<ServerDetailPage>
); );
} }
Widget _buildSensors(ServerStatus ss) {
if (ss.sensors.isEmpty) return UIs.placeholder;
return CardX(
child: ExpandTile(
title: Text(l10n.sensors),
leading: const Icon(Icons.thermostat, size: 17),
childrenPadding: const EdgeInsets.only(bottom: 7),
initiallyExpanded: _getInitExpand(ss.sensors.length, 3),
children: ss.sensors.map(_buildSensorItem).toList(),
),
);
}
Widget _buildSensorItem(SensorItem si) {
if (si.props.isEmpty) return UIs.placeholder;
return ListTile(
title: Text(si.device, style: UIs.text15),
subtitle: Column(
children: si.props.keys
.map((e) => _buildSensorDetailItem(e, si.props[e]))
.toList(),
),
);
}
Widget _buildSensorDetailItem(String key, SensorTemp? st) {
if (st == null) return UIs.placeholder;
final text = () {
final current = st.current?.toStringAsFixed(1);
final max = st.max?.toStringAsFixed(1);
final min = st.min?.toStringAsFixed(1);
final currentText = current == null ? '' : '$current°C';
final maxText = max == null ? '' : ' | ${l10n.max}:$max';
final minText = min == null ? '' : ' | ${l10n.min}:$min';
return '$currentText$maxText$minText';
}();
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(key, style: UIs.text13),
Text(text, style: UIs.text13Grey),
],
);
}
Widget _buildAnimatedText(Key key, String text, TextStyle style) { Widget _buildAnimatedText(Key key, String text, TextStyle style) {
return AnimatedSwitcher( return AnimatedSwitcher(
duration: const Duration(milliseconds: 277), duration: const Duration(milliseconds: 277),

View File

@@ -439,7 +439,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 771; CURRENT_PROJECT_VERSION = 775;
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Server Box"; INFOPLIST_KEY_CFBundleDisplayName = "Server Box";
@@ -449,7 +449,7 @@
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 10.15; MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0.771; MARKETING_VERSION = 1.0.775;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "Server Box"; PRODUCT_NAME = "Server Box";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -574,7 +574,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 771; CURRENT_PROJECT_VERSION = 775;
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Server Box"; INFOPLIST_KEY_CFBundleDisplayName = "Server Box";
@@ -584,7 +584,7 @@
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 10.15; MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0.771; MARKETING_VERSION = 1.0.775;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "Server Box"; PRODUCT_NAME = "Server Box";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@@ -604,7 +604,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "3rd Party Mac Developer Application"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "3rd Party Mac Developer Application";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 771; CURRENT_PROJECT_VERSION = 775;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=macosx*]" = BA88US33G6; "DEVELOPMENT_TEAM[sdk=macosx*]" = BA88US33G6;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@@ -615,7 +615,7 @@
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 10.15; MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0.771; MARKETING_VERSION = 1.0.775;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "Server Box"; PRODUCT_NAME = "Server Box";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";

44
test/sensors_test.dart Normal file
View File

@@ -0,0 +1,44 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:toolbox/data/model/server/sensors.dart';
void main() {
test('parse sensors', () {
final sensors = SensorItem.parse(SensorItem.sensorsRaw);
expect(sensors.map((e) => e.device), [
'coretemp-isa-0000',
'acpitz-acpi-0',
'iwlwifi_1-virtual-0',
'nvme-pci-0400',
]);
expect(sensors.map((e) => e.adapter), [
SensorAdaptor.isa,
SensorAdaptor.acpi,
SensorAdaptor.virtual,
SensorAdaptor.pci,
]);
expect(
sensors.map((e) => e.props),
[
{
'Package id 0': const SensorTemp(current: 51, max: 105),
'Core 0': const SensorTemp(current: 40, max: 105),
'Core 1': const SensorTemp(current: 40, max: 105),
'Core 2': const SensorTemp(current: 40, max: 105),
'Core 3': const SensorTemp(current: 40, max: 105),
},
{
'temp1': const SensorTemp(current: 27.8, max: 119),
},
{},
{
'Composite':
const SensorTemp(current: 35.85, max: 83.85, min: -273.15),
'Sensor 1':
const SensorTemp(current: 35.85, max: 65261.85, min: -273.15),
'Sensor 2':
const SensorTemp(current: 37.85, max: 65261.85, min: -273.15),
},
],
);
});
}