Fix flipper zero
This commit is contained in:
@@ -29,6 +29,8 @@ class CANStatsPage(InfoPage):
|
|||||||
|
|
||||||
def get_lines(self) -> list[str]:
|
def get_lines(self) -> list[str]:
|
||||||
"""Get statistics lines for display."""
|
"""Get statistics lines for display."""
|
||||||
|
# Force refresh to get fresh data
|
||||||
|
self._provider.refresh()
|
||||||
data = self._provider.get_data()
|
data = self._provider.get_data()
|
||||||
|
|
||||||
lines = [
|
lines = [
|
||||||
|
|||||||
@@ -29,10 +29,12 @@ class SystemInfoPage(InfoPage):
|
|||||||
|
|
||||||
def get_lines(self) -> list[str]:
|
def get_lines(self) -> list[str]:
|
||||||
"""Get system info lines for display."""
|
"""Get system info lines for display."""
|
||||||
|
# Force refresh to get fresh data
|
||||||
|
self._provider.refresh()
|
||||||
data = self._provider.get_data()
|
data = self._provider.get_data()
|
||||||
|
|
||||||
lines = [
|
lines = [
|
||||||
f"CPU Temp: {data.cpu_temp:.1f}C {self._get_temp_indicator(data.cpu_temp)}",
|
f"CPU: {data.cpu_temp:.1f}C {self._get_temp_indicator(data.cpu_temp)}",
|
||||||
f"Power: {data.power_watts:.2f}W",
|
f"Power: {data.power_watts:.2f}W",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ class UPSStatusPage(InfoPage):
|
|||||||
self._provider.get_last_error() or "Check I2C connection"
|
self._provider.get_last_error() or "Check I2C connection"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Force refresh to get fresh data
|
||||||
|
self._provider.refresh()
|
||||||
data = self._provider.get_data()
|
data = self._provider.get_data()
|
||||||
|
|
||||||
# Battery bar visualization
|
# Battery bar visualization
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ from dataclasses import dataclass
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from flipper.providers.base import BaseProvider
|
from flipper.providers.base import BaseProvider
|
||||||
|
from logger import get_logger
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -50,16 +53,31 @@ class SystemProvider(BaseProvider):
|
|||||||
Float value or None on error
|
Float value or None on error
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
output = subprocess.check_output(args).decode("utf-8")
|
output = subprocess.check_output(args, stderr=subprocess.DEVNULL).decode("utf-8")
|
||||||
value_str = output.split("=")[1].strip().rstrip(strip_chars)
|
value_str = output.split("=")[1].strip().rstrip(strip_chars)
|
||||||
return float(value_str)
|
return float(value_str)
|
||||||
except Exception:
|
except Exception as e:
|
||||||
|
logger.debug(f"Failed to read metric {args}: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _read_cpu_temp(self) -> float:
|
def _read_cpu_temp(self) -> float:
|
||||||
"""Read CPU temperature in Celsius."""
|
"""Read CPU temperature in Celsius."""
|
||||||
|
# Try vcgencmd first
|
||||||
result = self._read_metric(["vcgencmd", "measure_temp"], "'C")
|
result = self._read_metric(["vcgencmd", "measure_temp"], "'C")
|
||||||
return result if result is not None else 0.0
|
if result is not None:
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Fallback to sysfs thermal zone
|
||||||
|
try:
|
||||||
|
thermal_path = Path("/sys/class/thermal/thermal_zone0/temp")
|
||||||
|
if thermal_path.exists():
|
||||||
|
with open(thermal_path, "r") as f:
|
||||||
|
temp_millicelsius = int(f.read().strip())
|
||||||
|
return temp_millicelsius / 1000.0
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(f"Failed to read sysfs temp: {e}")
|
||||||
|
|
||||||
|
return 0.0
|
||||||
|
|
||||||
def _read_cpu_volts(self) -> float:
|
def _read_cpu_volts(self) -> float:
|
||||||
"""Read CPU core voltage."""
|
"""Read CPU core voltage."""
|
||||||
@@ -149,19 +167,32 @@ class SystemProvider(BaseProvider):
|
|||||||
def refresh(self) -> bool:
|
def refresh(self) -> bool:
|
||||||
"""Refresh system metrics."""
|
"""Refresh system metrics."""
|
||||||
try:
|
try:
|
||||||
|
cpu_temp = self._read_cpu_temp()
|
||||||
|
cpu_volts = self._read_cpu_volts()
|
||||||
|
cpu_amps = self._read_cpu_amps()
|
||||||
|
power_watts = self._read_power_watts()
|
||||||
|
fan_rpm = self._read_fan_rpm()
|
||||||
|
input_voltage = self._read_input_voltage()
|
||||||
|
|
||||||
self._data = SystemData(
|
self._data = SystemData(
|
||||||
cpu_temp=self._read_cpu_temp(),
|
cpu_temp=cpu_temp,
|
||||||
cpu_volts=self._read_cpu_volts(),
|
cpu_volts=cpu_volts,
|
||||||
cpu_amps=self._read_cpu_amps(),
|
cpu_amps=cpu_amps,
|
||||||
power_watts=self._read_power_watts(),
|
power_watts=power_watts,
|
||||||
fan_rpm=self._read_fan_rpm(),
|
fan_rpm=fan_rpm,
|
||||||
input_voltage=self._read_input_voltage()
|
input_voltage=input_voltage
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.debug(
|
||||||
|
f"System metrics: temp={cpu_temp}, power={power_watts}W, "
|
||||||
|
f"fan={fan_rpm}, input={input_voltage}V"
|
||||||
)
|
)
|
||||||
|
|
||||||
self._set_cached("data", self._data)
|
self._set_cached("data", self._data)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to refresh system metrics: {e}")
|
||||||
self._last_error = str(e)
|
self._last_error = str(e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ from typing import Optional, Tuple
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from flipper.providers.base import BaseProvider
|
from flipper.providers.base import BaseProvider
|
||||||
|
from logger import get_logger
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
@@ -171,7 +171,8 @@ static uint8_t parse_items(const char* str, char items[][MAX_LINE_LENGTH], uint8
|
|||||||
|
|
||||||
// Parse PAGE message
|
// Parse PAGE message
|
||||||
// Format: PAGE:<idx>/<total>|<type>|<title>|<lines>|<actions>|<selected>
|
// Format: PAGE:<idx>/<total>|<type>|<title>|<lines>|<actions>|<selected>
|
||||||
static bool parse_page(const char* line, PageContent* page) {
|
// Returns true if page changed (different page_index or page_type)
|
||||||
|
static bool parse_page(const char* line, PageContent* page, bool* page_changed) {
|
||||||
if(strncmp(line, "PAGE:", 5) != 0) {
|
if(strncmp(line, "PAGE:", 5) != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -179,6 +180,11 @@ static bool parse_page(const char* line, PageContent* page) {
|
|||||||
const char* p = line + 5;
|
const char* p = line + 5;
|
||||||
char* end;
|
char* end;
|
||||||
|
|
||||||
|
// Save old values to detect page change
|
||||||
|
uint8_t old_page_index = page->page_index;
|
||||||
|
PageType old_page_type = page->page_type;
|
||||||
|
bool was_valid = page->data_valid;
|
||||||
|
|
||||||
// Parse page index and total
|
// Parse page index and total
|
||||||
page->page_index = (uint8_t)strtoul(p, &end, 10);
|
page->page_index = (uint8_t)strtoul(p, &end, 10);
|
||||||
if(*end != '/') return false;
|
if(*end != '/') return false;
|
||||||
@@ -192,17 +198,27 @@ static bool parse_page(const char* line, PageContent* page) {
|
|||||||
const char* type_end = strchr(p, '|');
|
const char* type_end = strchr(p, '|');
|
||||||
if(!type_end) return false;
|
if(!type_end) return false;
|
||||||
|
|
||||||
|
PageType new_page_type;
|
||||||
if(strncmp(p, "info", type_end - p) == 0) {
|
if(strncmp(p, "info", type_end - p) == 0) {
|
||||||
page->page_type = PageTypeInfo;
|
new_page_type = PageTypeInfo;
|
||||||
} else if(strncmp(p, "menu", type_end - p) == 0) {
|
} else if(strncmp(p, "menu", type_end - p) == 0) {
|
||||||
page->page_type = PageTypeMenu;
|
new_page_type = PageTypeMenu;
|
||||||
} else if(strncmp(p, "confirm", type_end - p) == 0) {
|
} else if(strncmp(p, "confirm", type_end - p) == 0) {
|
||||||
page->page_type = PageTypeConfirm;
|
new_page_type = PageTypeConfirm;
|
||||||
} else {
|
} else {
|
||||||
page->page_type = PageTypeInfo;
|
new_page_type = PageTypeInfo;
|
||||||
}
|
}
|
||||||
|
page->page_type = new_page_type;
|
||||||
p = type_end + 1;
|
p = type_end + 1;
|
||||||
|
|
||||||
|
// Detect if page changed (index OR type changed)
|
||||||
|
bool is_page_change = !was_valid ||
|
||||||
|
(page->page_index != old_page_index) ||
|
||||||
|
(new_page_type != old_page_type);
|
||||||
|
if(page_changed) {
|
||||||
|
*page_changed = is_page_change;
|
||||||
|
}
|
||||||
|
|
||||||
// Parse title
|
// Parse title
|
||||||
const char* title_end = strchr(p, '|');
|
const char* title_end = strchr(p, '|');
|
||||||
if(!title_end) return false;
|
if(!title_end) return false;
|
||||||
@@ -243,8 +259,18 @@ static bool parse_page(const char* line, PageContent* page) {
|
|||||||
page->action_count = parse_items(actions_buf, page->actions, MAX_ACTIONS);
|
page->action_count = parse_items(actions_buf, page->actions, MAX_ACTIONS);
|
||||||
p = actions_end + 1;
|
p = actions_end + 1;
|
||||||
|
|
||||||
// Parse selected index
|
// Parse selected index from server
|
||||||
page->selected_index = (uint8_t)strtoul(p, NULL, 10);
|
uint8_t server_selected = (uint8_t)strtoul(p, NULL, 10);
|
||||||
|
|
||||||
|
// IMPORTANT: Only update selected_index on page change
|
||||||
|
// For menu/confirm pages, preserve local selection during updates
|
||||||
|
if(is_page_change) {
|
||||||
|
page->selected_index = server_selected;
|
||||||
|
} else if(page->page_type == PageTypeInfo) {
|
||||||
|
// Info pages don't have selection, always use server value
|
||||||
|
page->selected_index = server_selected;
|
||||||
|
}
|
||||||
|
// For menu/confirm on same page: keep old_selected (local user choice)
|
||||||
|
|
||||||
page->data_valid = true;
|
page->data_valid = true;
|
||||||
page->last_update_tick = furi_get_tick();
|
page->last_update_tick = furi_get_tick();
|
||||||
@@ -322,7 +348,11 @@ static void process_line(CanMonitorApp* app, const char* line) {
|
|||||||
} else if(app->conn_state == StateConnected) {
|
} else if(app->conn_state == StateConnected) {
|
||||||
// Parse PAGE or RESULT
|
// Parse PAGE or RESULT
|
||||||
if(line[0] == 'P') {
|
if(line[0] == 'P') {
|
||||||
parse_page(line, &app->page);
|
bool page_changed = false;
|
||||||
|
parse_page(line, &app->page, &page_changed);
|
||||||
|
if(page_changed) {
|
||||||
|
FURI_LOG_I(TAG, "Page changed to %d", app->page.page_index);
|
||||||
|
}
|
||||||
} else if(line[0] == 'R') {
|
} else if(line[0] == 'R') {
|
||||||
parse_result(line, &app->result);
|
parse_result(line, &app->result);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user