fix: sensors (#350)

This commit is contained in:
lollipopkit
2024-05-10 20:15:30 +08:00
parent ed5bcb17ed
commit f9efd6acfa
11 changed files with 118 additions and 222 deletions

View File

@@ -690,7 +690,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 891;
CURRENT_PROJECT_VERSION = 892;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -700,7 +700,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.891;
MARKETING_VERSION = 1.0.892;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -826,7 +826,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 891;
CURRENT_PROJECT_VERSION = 892;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -836,7 +836,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.891;
MARKETING_VERSION = 1.0.892;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -854,7 +854,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 891;
CURRENT_PROJECT_VERSION = 892;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -864,7 +864,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.891;
MARKETING_VERSION = 1.0.892;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -885,7 +885,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 891;
CURRENT_PROJECT_VERSION = 892;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -898,7 +898,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.891;
MARKETING_VERSION = 1.0.892;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
@@ -924,7 +924,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 891;
CURRENT_PROJECT_VERSION = 892;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -937,7 +937,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.891;
MARKETING_VERSION = 1.0.892;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -960,7 +960,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 891;
CURRENT_PROJECT_VERSION = 892;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -973,7 +973,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.891;
MARKETING_VERSION = 1.0.892;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -996,7 +996,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 891;
CURRENT_PROJECT_VERSION = 892;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES;
@@ -1008,7 +1008,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.891;
MARKETING_VERSION = 1.0.892;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
@@ -1037,7 +1037,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 891;
CURRENT_PROJECT_VERSION = 892;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES;
@@ -1049,7 +1049,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.891;
MARKETING_VERSION = 1.0.892;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
PRODUCT_NAME = ServerBox;
@@ -1075,7 +1075,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 891;
CURRENT_PROJECT_VERSION = 892;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES;
@@ -1087,7 +1087,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.891;
MARKETING_VERSION = 1.0.892;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
PRODUCT_NAME = ServerBox;

View File

@@ -1,4 +1,3 @@
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:toolbox/core/extension/context/dialog.dart';

View File

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

View File

@@ -1,6 +1,3 @@
import 'dart:convert';
import 'package:toolbox/core/extension/listx.dart';
import 'package:toolbox/data/res/logger.dart';
final class SensorAdaptor {
@@ -26,78 +23,52 @@ final class SensorAdaptor {
};
}
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;
final String val;
const SensorItem({
required this.device,
required this.adapter,
required this.props,
required this.val,
});
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') {
final eachSensorLines = <List<String>>[[]];
final lines = raw.split('\n');
var emptyLinesCount = 0;
for (var i = 0; i < lines.length; i++) {
final line = lines[i];
if (line.isEmpty) {
eachSensorLines.add([]);
emptyLinesCount++;
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) {
eachSensorLines.last.add(line);
}
if (emptyLinesCount + 1 != eachSensorLines.length) {
Loggers.app.warning('Empty lines count not match');
}
final sensors = <SensorItem>[];
for (final sensorLines in eachSensorLines) {
// At least 3 lines: [device, adapter, temp]
final len = sensorLines.length;
if (len < 3) continue;
final device = sensorLines.first;
final adapter =
SensorAdaptor.parse(sensorLines[1].split(':').last.trim());
final line = sensorLines[2];
final parts = line.split(':');
if (parts.length < 2) {
continue;
}
props[subKey] = SensorTemp(current: current, max: max, min: min);
final val = parts[1].trim();
sensors.add(SensorItem(device: device, adapter: adapter, val: val));
}
items.add(SensorItem(device: key, adapter: adapter, props: props));
} catch (e, s) {
Loggers.parse.warning(e, s);
continue;
}
}
return items;
return sensors;
}
}

View File

@@ -19,14 +19,13 @@ extension ServerX on Server {
final preferTempDev = spi.custom?.preferTempDev;
if (preferTempDev != null) {
final preferTemp = status.sensors
.firstWhereOrNull(
(e) => e.device == preferTempDev,
)
?.props
.values
.firstOrNull
?.current;
if (preferTemp != null) return preferTemp;
.firstWhereOrNull((e) => e.device == preferTempDev)
?.val
.split(' ')
.firstOrNull;
if (preferTemp != null) {
return double.tryParse(preferTemp.replaceFirst('°C', ''));
}
}
// Last priority
final temp = status.temps.first;

View File

@@ -279,7 +279,6 @@ class ServerProvider extends ChangeNotifier {
final wol = spi.wolCfg;
if (wol != null) {
/// TODO: test it
try {
await wol.wake();
} catch (e) {

View File

@@ -2,9 +2,9 @@
class BuildData {
static const String name = "ServerBox";
static const int build = 891;
static const int build = 892;
static const String engine = "3.19.6";
static const String buildAt = "2024-05-10 11:30:47";
static const String buildAt = "2024-05-10 12:55:39";
static const int modifications = 3;
static const int script = 46;
}

View File

@@ -245,7 +245,7 @@ class SettingStore extends PersistentStore {
/// Compatiablity for Chinese Android.
/// Set it to true, if you use Safe Keyboard on Chinese Android
late final cnKeyboardComp = property('cnKeyboardComp', false);
// late final cnKeyboardComp = property('cnKeyboardComp', false);
late final lastVer = property('lastVer', 0);

View File

@@ -755,34 +755,23 @@ class _ServerDetailPageState extends State<ServerDetailPage>
}
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,
if (si.val.isEmpty) return UIs.placeholder;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 17, vertical: 7),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(key, style: UIs.text13),
Text(text, style: UIs.text13Grey),
Row(
children: [
Text(si.device, style: UIs.text15Bold),
const Spacer(),
Text(si.adapter.raw, style: UIs.text13Grey),
],
),
Text(si.val, style: UIs.text13Grey),
],
),
);
}

View File

@@ -471,7 +471,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 891;
CURRENT_PROJECT_VERSION = 892;
DEVELOPMENT_TEAM = BA88US33G6;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Server Box";
@@ -481,7 +481,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0.891;
MARKETING_VERSION = 1.0.892;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "Server Box";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -608,7 +608,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 891;
CURRENT_PROJECT_VERSION = 892;
DEVELOPMENT_TEAM = BA88US33G6;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Server Box";
@@ -618,7 +618,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0.891;
MARKETING_VERSION = 1.0.892;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "Server Box";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -638,7 +638,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "3rd Party Mac Developer Application";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 891;
CURRENT_PROJECT_VERSION = 892;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=macosx*]" = BA88US33G6;
INFOPLIST_FILE = Runner/Info.plist;
@@ -649,7 +649,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0.891;
MARKETING_VERSION = 1.0.892;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "Server Box";
PROVISIONING_PROFILE_SPECIFIER = "";

View File

@@ -1,80 +1,34 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:toolbox/data/model/server/sensors.dart';
const _sensorsRaw = '''
coretemp-isa-0000
Adapter: ISA adapter
Package id 0: +56.0°C (high = +105.0°C, crit = +105.0°C)
Core 0: +45.0°C (high = +105.0°C, crit = +105.0°C)
Core 1: +45.0°C (high = +105.0°C, crit = +105.0°C)
Core 2: +45.0°C (high = +105.0°C, crit = +105.0°C)
Core 3: +44.0°C (high = +105.0°C, crit = +105.0°C)
acpitz-acpi-0
Adapter: ACPI interface
temp1: +27.8°C (crit = +119.0°C)
iwlwifi_1-virtual-0
Adapter: Virtual device
temp1: +56.0°C
nvme-pci-0400
Adapter: PCI adapter
Composite: +45.9°C (low = -273.1°C, high = +83.8°C)
(crit = +84.8°C)
Sensor 1: +45.9°C (low = -273.1°C, high = +65261.8°C)
Sensor 2: +47.9°C (low = -273.1°C, high = +65261.8°C)
''';
void main() {
test('parse sensors', () {
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
}
}
}
''';
final sensors = SensorItem.parse(sensorsRaw);
final sensors = SensorItem.parse(_sensorsRaw);
expect(sensors.map((e) => e.device), [
'coretemp-isa-0000',
'acpitz-acpi-0',
@@ -88,27 +42,12 @@ ERROR: Can't get value of subfeature temp1_input: Can't read
SensorAdaptor.pci,
]);
expect(
sensors.map((e) => e.props),
sensors.map((e) => e.val),
[
{
'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),
},
'+56.0°C (high = +105.0°C, crit = +105.0°C)',
'+27.8°C (crit = +119.0°C)',
'+56.0°C',
'+45.9°C (low = -273.1°C, high = +83.8°C)',
],
);
});