Browse Source

上传文件至 ''

yangfei 5 months ago
parent
commit
13aecc7f48
4 changed files with 1942 additions and 2 deletions
  1. 178 2
      README.md
  2. 193 0
      USAGE.md
  3. 766 0
      install.sh
  4. 805 0
      oled_system_monitor_final.py

+ 178 - 2
README.md

@@ -1,3 +1,179 @@
-# raspi-OLED
+# 树莓派OLED系统监控完整解决方案
 
 
-带触摸的树莓派OLED监控器
+## 项目概述
+
+这是一个专为树莓派4B设计的OLED系统监控器,具有触摸唤醒和自动熄屏功能。该解决方案可以实时显示系统状态信息,包括CPU使用率、内存使用情况、磁盘空间、系统运行时间等,并支持通过触摸传感器唤醒屏幕显示。
+
+## 功能特性
+
+1. **系统监控**:
+   - CPU使用率和温度监控
+   - 内存使用情况监控
+   - 磁盘空间使用情况监控
+   - 系统运行时间显示
+   - IP地址显示
+   - 实时时间显示
+
+2. **触摸唤醒功能**:
+   - 基于RC电路充放电时间检测的触摸传感器
+   - GPIO18输出低电平放电,然后输出高电平检测充电时间
+   - 通过放电时间长短判断是否发生触摸
+
+3. **自动熄屏**:
+   - 30秒无操作后自动关闭屏幕以节省电量
+   - 触摸唤醒后重新点亮屏幕
+
+4. **中文字体支持**:
+   - 支持中文显示
+   - 自动检测和安装中文字体
+
+5. **系统服务集成**:
+   - 通过systemd服务自动启动
+   - 支持服务管理命令
+
+## 硬件连接
+
+### OLED显示屏连接
+- VCC -> 3.3V (Pin 1)
+- GND -> GND (Pin 6)
+- SDA -> SDA (Pin 3)
+- SCL -> SCL (Pin 5)
+
+### 触摸传感器连接
+- GPIO18 (物理引脚12) -> 1MΩ电阻 -> 金属触摸片
+- 金属触摸片 -> GPIO24 (物理引脚18)
+
+## 文件说明
+
+### `oled_system_monitor_final.py`
+这是主程序文件,包含了所有系统监控和显示功能的实现:
+
+1. **SSD1306Final类**:
+   - SSD1306 OLED驱动程序
+   - 支持I2C通信
+   - 提供文本绘制、矩形绘制等基本图形功能
+
+2. **ChineseSystemMonitorFinal类**:
+   - 系统监控主类
+   - 实现触摸检测功能
+   - 管理屏幕显示和自动熄屏功能
+   - 获取并显示系统信息
+
+3. **主要功能函数**:
+   - `get_cpu_temperature()`:获取CPU温度
+   - `get_ip_address()`:获取IP地址
+   - `format_time_long()`:格式化时间显示
+   - `format_bytes_short()`:格式化字节单位显示
+
+### `install.sh`
+这是自动化安装脚本,用于在树莓派上部署和配置系统监控器:
+
+1. **系统检查**:
+   - 检查root权限
+   - 检查主程序文件
+   - 显示系统信息
+
+2. **依赖安装**:
+   - 更新系统包列表
+   - 安装必要的系统依赖(Python库、字体等)
+   - 安装Python包(Pillow、smbus2等)
+
+3. **I2C配置**:
+   - 启用I2C接口
+   - 配置相关内核模块
+   - 检测OLED设备
+
+4. **服务配置**:
+   - 创建systemd服务
+   - 设置文件权限
+   - 启动服务并验证
+
+5. **安装验证**:
+   - 检查服务状态
+   - 验证程序运行情况
+
+## 安装步骤
+
+1. **准备工作**:
+   ```bash
+   sudo -i
+   ```
+
+2. **运行安装脚本**:
+   ```bash
+   chmod +x install.sh
+   ./install.sh
+   ```
+
+3. **按照提示完成安装**:
+   - 确认安装
+   - 检查I2C设备检测结果
+   - 等待安装完成
+
+## 管理命令
+
+### 服务管理
+```bash
+# 查看服务状态
+systemctl status oled-monitor-final.service
+
+# 启动服务
+systemctl start oled-monitor-final.service
+
+# 停止服务
+systemctl stop oled-monitor-final.service
+
+# 重启服务
+systemctl restart oled-monitor-final.service
+
+# 设置开机自启
+systemctl enable oled-monitor-final.service
+```
+
+### 日志查看
+```bash
+# 查看系统日志
+journalctl -u oled-monitor-final.service -f
+
+# 查看程序日志
+tail -f /opt/oled_monitor_final/logs/monitor.log
+```
+
+### 手动测试运行
+```bash
+cd /opt/oled_monitor_final
+python3 oled_system_monitor_final.py
+```
+
+## 故障排除
+
+1. **I2C设备未检测到**:
+   - 检查OLED屏幕接线是否正确
+   - 确认I2C接口已启用
+   - 使用`i2cdetect -y 1`命令检查设备
+
+2. **中文字体显示异常**:
+   - 确认已安装中文字体
+   - 检查字体文件是否存在
+
+3. **触摸功能不工作**:
+   - 检查GPIO连接是否正确
+   - 确认电阻值是否为1MΩ
+   - 查看调试日志了解触摸检测状态
+
+4. **服务启动失败**:
+   - 查看详细错误日志
+   - 检查依赖是否安装完整
+   - 确认文件权限设置正确
+
+## 定制化修改
+
+如需修改监控信息显示内容或样式,可以编辑`oled_system_monitor_final.py`文件中的以下部分:
+
+1. `draw_main_screen()`函数:修改主显示界面布局
+2. `get_system_info()`函数:添加或修改系统信息获取逻辑
+3. 触摸检测参数:调整`check_touch()`函数中的阈值参数
+
+## 版权信息
+
+本项目为开源软件,可根据需要进行修改和分发。

+ 193 - 0
USAGE.md

@@ -0,0 +1,193 @@
+# 树莓派OLED系统监控使用说明
+
+## 快速开始
+
+### 1. 硬件准备
+确保您拥有以下组件:
+- 树莓派4B
+- SSD1306 OLED显示屏(128x64像素)
+- 1MΩ电阻
+- 杜邦线若干
+- 金属触摸片或导电材料
+
+### 2. 硬件连接
+按照以下方式连接OLED显示屏和触摸传感器:
+
+#### OLED显示屏连接:
+| OLED引脚 | 树莓派引脚 |
+|---------|----------|
+| VCC     | 3.3V (Pin 1) |
+| GND     | GND (Pin 6)  |
+| SDA     | SDA (Pin 3)  |
+| SCL     | SCL (Pin 5)  |
+
+#### 触摸传感器连接:
+1. 将1MΩ电阻一端连接到GPIO18 (物理引脚12)
+2. 将电阻另一端连接到金属触摸片
+3. 将金属触摸片连接到GPIO24 (物理引脚18)
+
+### 3. 软件安装
+在树莓派终端中执行以下命令:
+
+```bash
+# 切换到root用户
+sudo -i
+
+# 进入项目目录
+cd /path/to/树莓派OLED系统监控完整解决方案
+
+# 给安装脚本添加执行权限
+chmod +x install.sh
+
+# 运行安装脚本
+./install.sh
+```
+
+按照安装向导的提示完成安装过程。
+
+## 显示界面说明
+
+安装完成后,OLED显示屏会显示以下系统信息:
+
+1. **第一行**:CPU使用率和温度(例如:CPU 25% 45°C)
+2. **第二行**:内存使用情况(例如:MEM 1.2G/3.8G)
+3. **第三行**:磁盘空间使用情况(例如:DISK 15G/58G)
+4. **第四行**:系统运行时间(例如:UPTIME 2天15小时)
+5. **第五行**:IP地址(例如:IP 192.168.1.100)
+6. **第六行**:当前时间(例如:TIME 14:30:25)
+
+## 使用方法
+
+### 触摸唤醒
+- 屏幕默认会在30秒无操作后自动熄灭以节省电量
+- 轻触金属触摸片即可唤醒屏幕显示系统信息
+- 再次触摸可保持屏幕常亮状态
+
+### 手动测试
+如果您想手动测试程序运行情况,可以在终端中执行:
+
+```bash
+cd /opt/oled_monitor_final
+python3 oled_system_monitor_final.py
+```
+
+## 系统服务管理
+
+安装完成后,系统监控程序会作为systemd服务自动运行。
+
+### 查看服务状态
+```bash
+systemctl status oled-monitor-final.service
+```
+
+### 控制服务
+```bash
+# 启动服务
+systemctl start oled-monitor-final.service
+
+# 停止服务
+systemctl stop oled-monitor-final.service
+
+# 重启服务
+systemctl restart oled-monitor-final.service
+
+# 设置开机自启
+systemctl enable oled-monitor-final.service
+
+# 取消开机自启
+systemctl disable oled-monitor-final.service
+```
+
+## 日志查看
+
+### 系统日志
+```bash
+# 实时查看服务日志
+journalctl -u oled-monitor-final.service -f
+
+# 查看最近的日志
+journalctl -u oled-monitor-final.service --since "10 minutes ago"
+```
+
+### 应用日志
+```bash
+# 查看程序日志
+tail -f /opt/oled_monitor_final/logs/monitor.log
+
+# 查看错误日志
+tail -f /opt/oled_monitor_final/logs/error.log
+```
+
+## 常见问题解决
+
+### 1. 屏幕不显示任何内容
+- 检查OLED显示屏接线是否正确
+- 确认I2C接口已启用:`sudo raspi-config` -> Interfacing Options -> I2C -> Enable
+- 使用`i2cdetect -y 1`命令检查设备是否被识别
+
+### 2. 触摸功能无效
+- 检查GPIO连接是否正确
+- 确认使用的是1MΩ电阻
+- 在调试模式下运行程序查看触摸检测日志
+
+### 3. 中文显示乱码
+- 确认已安装中文字体
+- 检查字体文件是否存在:`ls /usr/share/fonts/truetype/wqy/`
+
+### 4. 服务无法启动
+- 查看服务状态和错误信息:`systemctl status oled-monitor-final.service`
+- 检查程序文件权限:`ls -l /opt/oled_monitor_final/`
+- 验证Python依赖是否安装完整
+
+## 自定义配置
+
+### 修改显示内容
+编辑 `/opt/oled_monitor_final/oled_system_monitor_final.py` 文件:
+
+1. 找到 `draw_main_screen()` 函数
+2. 修改各系统信息的显示位置和格式
+3. 保存文件后重启服务:`systemctl restart oled-monitor-final.service`
+
+### 调整触摸灵敏度
+在 `oled_system_monitor_final.py` 文件中找到 `check_touch()` 函数:
+
+```python
+# 调整这些参数来改变触摸灵敏度
+CHARGE_THRESHOLD = 5000  # 充电时间阈值
+SAMPLE_COUNT = 10        # 采样次数
+```
+
+### 修改自动熄屏时间
+在 `oled_system_monitor_final.py` 文件中找到以下变量:
+
+```python
+SCREEN_TIMEOUT = 30  # 自动熄屏时间(秒)
+```
+
+## 卸载程序
+
+如果需要卸载程序,可以执行以下步骤:
+
+1. 停止并禁用服务:
+```bash
+systemctl stop oled-monitor-final.service
+systemctl disable oled-monitor-final.service
+```
+
+2. 删除服务文件:
+```bash
+rm /etc/systemd/system/oled-monitor-final.service
+systemctl daemon-reload
+```
+
+3. 删除程序文件:
+```bash
+rm -rf /opt/oled_monitor_final
+```
+
+## 技术支持
+
+如有其他问题,请参考以下资源:
+- 项目源代码:oled_system_monitor_final.py 和 install.sh
+- 系统日志:/opt/oled_monitor_final/logs/
+- 树莓派官方文档:https://www.raspberrypi.org/documentation/

+ 766 - 0
install.sh

@@ -0,0 +1,766 @@
+#!/bin/bash
+# OLED中文系统监控器安装脚本 - 终极修复版 v2.0(已修复)
+# 说明:此脚本基于用户原始脚本全面修复:
+#  - 添加 start_step(步骤计数)并自动递增 CURRENT_STEP
+#  - 修复 show_progress(百分比、填充条、转轮、颜色、行尾残影)
+#  - 保留原有流程、日志、I2C 检测、systemd 服务创建等逻辑
+#  - 在脚本中加入中文注释,便于阅读与维护
+
+# ---------------------------
+# 颜色定义(ANSI)—— 中文注释
+# ---------------------------
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+MAGENTA='\033[0;35m'
+CYAN='\033[0;36m'
+NC='\033[0m' # No Color
+
+# ---------------------------
+# 全局变量 - 终极修复版配置
+# ---------------------------
+TOTAL_STEPS=18
+CURRENT_STEP=0
+INSTALL_DIR="/opt/oled_monitor_final"  # 使用新目录避免冲突
+SYSTEM_USER="root"
+SYSTEM_GROUP="root"
+MAIN_PROGRAM="oled_system_monitor_final.py"  # 新的程序文件名
+SERVICE_NAME="oled-monitor-final.service"    # 新的服务名
+LOG_FILE="install_final.log"
+
+# ---------------------------
+# 日志记录函数(中文注释)
+# ---------------------------
+log_message() {
+    local level=$1
+    local message=$2
+    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $message" >> "$LOG_FILE"
+}
+
+# ---------------------------
+# 输出样式函数(中文注释)
+# ---------------------------
+status_msg() { echo -e "${YELLOW}[*]${NC} $1"; }
+success_msg() { echo -e "${GREEN}[✓]${NC} $1"; }
+warning_msg() { echo -e "${YELLOW}[!]${NC} $1"; }
+error_msg() { echo -e "${RED}[✗]${NC} $1"; }
+
+# ---------------------------
+# start_step:统一步骤开始,自动增加 CURRENT_STEP,并打印美观标题
+# ---------------------------
+start_step() {
+    # 增加当前步骤
+    CURRENT_STEP=$((CURRENT_STEP + 1))
+    # 打印步骤标题,保留中文说明
+    echo
+    echo -e "${CYAN}────────────────────────────────────────────${NC}"
+    echo -e "${MAGENTA}▶️  步骤 ${CURRENT_STEP}/${TOTAL_STEPS}:$1${NC}"
+    echo -e "${CYAN}────────────────────────────────────────────${NC}"
+    echo
+    # 记录到日志
+    log_message "INFO" "开始步骤 ${CURRENT_STEP}/${TOTAL_STEPS}:$1"
+}
+
+# ---------------------------
+# 修正版进度条:show_progress
+# 说明:
+#  - 参数:当前值 current,总值 total,文本 text(可选)
+#  - 避免 %0.s 的错误使用,使用 printf + tr 构造填充
+#  - 使用 tput el 清除行尾遗留字符,防止残影
+# ---------------------------
+show_progress() {
+    local current=$1
+    local total=$2
+    local text=${3:-""}
+
+    # 避免除以0
+    if [ "$total" -eq 0 ]; then
+        total=1
+    fi
+
+    # 计算百分比(整数)
+    local percentage=$((current * 100 / total))
+
+    # 进度条长度(可调整)
+    local bar_length=50
+    local filled_length=$((bar_length * current / total))
+    local empty_length=$((bar_length - filled_length))
+
+    # 构造填充和空白部分(使用 printf + tr)
+    local filled=$(printf "%${filled_length}s" | tr ' ' '#')
+    local empty=$(printf "%${empty_length}s" | tr ' ' '-')
+
+    # 旋转指示符(ASCII,避免 UTF-8 终端问题)
+    local spinners='|/-\'
+    # 使用 CURRENT_STEP 来驱动转轮更平滑
+    local idx=$((CURRENT_STEP % 4))
+    local spinner=${spinners:$idx:1}
+
+    # 输出(带颜色),使用 printf 安全替换百分比
+    printf "\r${BLUE}[${spinner}]${NC} ${GREEN}%3s%%${NC} [${GREEN}${filled}${NC}${empty}] ${text}" "$percentage"
+    # 清除行尾残留字符
+    # 如果 tput 不存在,也不会致命,保底
+    if command -v tput >/dev/null 2>&1; then
+        tput el
+    fi
+}
+
+# ---------------------------
+# 检查 root 权限(中文注释)
+# ---------------------------
+check_root() {
+    if [ "$(id -u)" -ne 0 ]; then
+        error_msg "此脚本需要以root用户运行"
+        echo -e "${YELLOW}正确命令: sudo -i${NC}"
+        echo -e "${YELLOW}然后运行: ./install_final.sh${NC}"
+        exit 1
+    fi
+
+    echo -e "${YELLOW}⚠️  警告: 您正在使用root用户安装${NC}"
+    echo
+}
+
+# ---------------------------
+# 检查主程序文件(中文注释)
+# ---------------------------
+check_program_file() {
+    if [ ! -f "$MAIN_PROGRAM" ]; then
+        error_msg "未找到主程序文件: $MAIN_PROGRAM"
+        error_msg "请确保程序文件在当前目录中"
+        log_message "ERROR" "主程序文件 $MAIN_PROGRAM 不存在"
+        exit 1
+    fi
+
+    # 检查文件大小
+    file_size=$(stat -c%s "$MAIN_PROGRAM")
+    if [ $file_size -lt 1000 ]; then
+        warning_msg "程序文件过小,可能不完整: ${file_size} bytes"
+        log_message "WARNING" "程序文件过小: ${file_size} bytes"
+    fi
+
+    success_msg "找到主程序文件: $MAIN_PROGRAM (${file_size} bytes)"
+    log_message "INFO" "找到主程序文件: $MAIN_PROGRAM"
+}
+
+# ---------------------------
+# 备份旧版本函数(中文注释)
+# ---------------------------
+backup_old_version() {
+    start_step "备份旧版本"
+
+    if [ -d "/opt/oled_monitor" ]; then
+        backup_dir="/opt/oled_monitor_backup_$(date +%Y%m%d_%H%M%S)"
+        mv /opt/oled_monitor "$backup_dir"
+        success_msg "旧版本已备份到: $backup_dir"
+        log_message "INFO" "旧版本备份到: $backup_dir"
+    else
+        status_msg "未找到旧版本,跳过备份"
+    fi
+
+    # 停止旧服务(原名)
+    if systemctl list-units --full -all | grep -q "oled-monitor.service"; then
+        systemctl stop oled-monitor.service > /dev/null 2>&1
+        systemctl disable oled-monitor.service > /dev/null 2>&1
+        success_msg "旧服务已停止并禁用"
+        log_message "INFO" "旧服务已停止并禁用"
+    fi
+
+    # 显示进度(当前步骤 / 总步骤)
+    show_progress $CURRENT_STEP $TOTAL_STEPS "备份完成"
+    echo
+}
+
+# ---------------------------
+# 主安装函数(中文注释)
+# ---------------------------
+main() {
+    # 初始化日志
+    echo "安装日志 - $(date)" > "$LOG_FILE"
+    log_message "INFO" "开始安装 OLED中文监控器终极修复版 v2.0"
+
+    clear
+    echo -e "${BLUE}=============================================${NC}"
+    echo -e "${MAGENTA}     OLED中文系统监控器安装脚本 v2.0${NC}"
+    echo -e "${RED}         终极修复版 - Root用户专用${NC}"
+    echo -e "${BLUE}=============================================${NC}"
+    echo -e "${CYAN}彻底解决draw属性问题 | 完整依赖检查 | 详细日志${NC}"
+    echo -e "${CYAN}全新安装目录 | 独立服务名称 | 安装后验证${NC}"
+    echo
+
+    # 检查 root
+    check_root
+
+    # 检查主程序文件
+    check_program_file
+
+    # 显示系统信息
+    start_step "系统信息检测"
+    status_msg "系统信息检测中..."
+    SYSTEM_INFO=$(uname -a)
+    echo -e "${YELLOW}  用户:${NC} $SYSTEM_USER (root)"
+    echo -e "${YELLOW}  目录:${NC} $INSTALL_DIR"
+    echo -e "${YELLOW}  系统:${NC} $SYSTEM_INFO"
+    echo -e "${YELLOW}  时间:${NC} $(date)"
+    echo -e "${YELLOW}  程序:${NC} $MAIN_PROGRAM"
+    echo
+    log_message "INFO" "系统信息: $SYSTEM_INFO"
+    log_message "INFO" "安装目录: $INSTALL_DIR"
+    show_progress $CURRENT_STEP $TOTAL_STEPS "系统信息检测完成"
+    echo
+
+    # 确认安装
+    read -p "⚠️  确认安装中文监控器终极修复版? (y/n): " -n 1 -r
+    echo
+    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+        error_msg "安装已取消"
+        log_message "INFO" "安装已取消"
+        exit 0
+    fi
+
+    echo -e "\n${GREEN} 🚀 开始终极修复版安装流程...${NC}"
+    echo
+
+    #
+    # 步骤 1: 备份旧版本
+    #
+    backup_old_version
+
+    #
+    # 步骤 2: 创建新的安装目录
+    #
+    start_step "创建全新安装目录"
+    status_msg "正在创建目录: $INSTALL_DIR"
+
+    # 确保目录不存在(若存在则清理)
+    if [ -d "$INSTALL_DIR" ]; then
+        rm -rf "$INSTALL_DIR"
+        status_msg "清理旧的安装目录"
+        log_message "INFO" "清理旧安装目录: $INSTALL_DIR"
+    fi
+
+    mkdir -p "$INSTALL_DIR"
+    chmod 755 "$INSTALL_DIR"
+    success_msg "全新安装目录创建完成: $INSTALL_DIR"
+    log_message "INFO" "创建安装目录: $INSTALL_DIR"
+    show_progress $CURRENT_STEP $TOTAL_STEPS "目录创建完成"
+    echo
+
+    #
+    # 步骤 3: 更新系统包列表
+    #
+    start_step "更新系统包列表"
+    status_msg "正在更新apt包索引..."
+
+    # 使用子进程更新并显示简单进度
+    apt-get update -y >> "$LOG_FILE" 2>&1 &
+    pid=$!
+    counter=0
+    while kill -0 $pid 2>/dev/null; do
+        counter=$((counter + 1))
+        show_progress $CURRENT_STEP $TOTAL_STEPS "正在更新... ${counter}s"
+        sleep 1
+    done
+    wait $pid 2>/dev/null
+    if [ $? -eq 0 ]; then
+        success_msg "包列表更新完成"
+        log_message "INFO" "包列表更新完成"
+    else
+        warning_msg "包列表更新可能失败,但继续安装"
+        log_message "WARNING" "包列表更新可能失败"
+    fi
+    show_progress $CURRENT_STEP $TOTAL_STEPS "包列表更新完成"
+    echo
+
+    #
+    # 步骤 4: 安装系统依赖
+    #
+    start_step "安装系统依赖包"
+    status_msg "正在安装必需的系统组件..."
+
+    REQUIRED_PACKAGES="python3 python3-pip python3-pil python3-smbus i2c-tools python3-psutil python3-setuptools python3-wheel"
+    apt-get install -y $REQUIRED_PACKAGES >> "$LOG_FILE" 2>&1 &
+    pid=$!
+    counter=0
+    while kill -0 $pid 2>/dev/null; do
+        counter=$((counter + 1))
+        show_progress $CURRENT_STEP $TOTAL_STEPS "正在安装依赖... ${counter}s"
+        sleep 1
+    done
+    wait $pid 2>/dev/null
+
+    if [ $? -eq 0 ]; then
+        success_msg "系统依赖安装完成"
+        log_message "INFO" "系统依赖安装完成"
+    else
+        warning_msg "部分依赖安装可能失败,请检查错误"
+        log_message "WARNING" "系统依赖安装可能失败"
+    fi
+    show_progress $CURRENT_STEP $TOTAL_STEPS "依赖安装完成"
+    echo
+
+    #
+    # 步骤 5: 安装中文字体
+    #
+    start_step "安装中文字体支持"
+    status_msg "正在安装文泉驿中文字体..."
+
+    apt-get install -y fonts-wqy-zenhei >> "$LOG_FILE" 2>&1 &
+    pid=$!
+    counter=0
+    while kill -0 $pid 2>/dev/null; do
+        counter=$((counter + 1))
+        show_progress $CURRENT_STEP $TOTAL_STEPS "正在安装字体... ${counter}s"
+        sleep 1
+    done
+    wait $pid 2>/dev/null
+
+    success_msg "中文字体安装完成"
+    log_message "INFO" "中文字体安装完成"
+    show_progress $CURRENT_STEP $TOTAL_STEPS "字体安装完成"
+    echo
+
+    #
+    # 步骤 6: 验证中文字体
+    #
+    start_step "验证中文字体"
+    status_msg "检查中文字体是否正确安装..."
+
+    FONT_FILE="/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc"
+    if [ -f "$FONT_FILE" ]; then
+        success_msg "文泉驿字体安装成功: $FONT_FILE"
+        log_message "INFO" "文泉驿字体安装成功"
+        ls -la "$FONT_FILE" >> "$LOG_FILE" 2>&1
+    else
+        warning_msg "文泉驿字体未找到,尝试其他字体..."
+        log_message "WARNING" "文泉驿字体未找到"
+
+        # 检查其他中文字体
+        OTHER_FONTS=$(find /usr/share/fonts -type f -iname "*.ttc" -o -iname "*.ttf" 2>/dev/null | grep -E "(wqy|song|hei|sim|chinese)" | head -5)
+        if [ -n "$OTHER_FONTS" ]; then
+            echo -e "${YELLOW}找到其他中文字体:${NC}"
+            echo "$OTHER_FONTS"
+            log_message "INFO" "找到其他中文字体: $OTHER_FONTS"
+        else
+            error_msg "未找到任何中文字体,中文显示可能受影响"
+            log_message "ERROR" "未找到任何中文字体"
+        fi
+    fi
+    show_progress $CURRENT_STEP $TOTAL_STEPS "字体验证完成"
+    echo
+
+    #
+    # 步骤 7: 升级 pip 和 setuptools
+    #
+    start_step "升级Python包管理器"
+    status_msg "正在升级pip和setuptools..."
+
+    pip3 install --break-system-packages --upgrade pip setuptools wheel >> "$LOG_FILE" 2>&1 &
+    pid=$!
+    counter=0
+    while kill -0 $pid 2>/dev/null; do
+        counter=$((counter + 1))
+        show_progress $CURRENT_STEP $TOTAL_STEPS "正在升级... ${counter}s"
+        sleep 1
+    done
+    wait $pid 2>/dev/null
+
+    success_msg "Python包管理器升级完成"
+    log_message "INFO" "Python包管理器升级完成"
+    show_progress $CURRENT_STEP $TOTAL_STEPS "包管理器升级完成"
+    echo
+
+    #
+    # 步骤 8: 安装 Adafruit Blinka
+    #
+    start_step "安装Python依赖库"
+    status_msg "正在安装Adafruit Blinka..."
+
+    pip3 install --break-system-packages Adafruit-Blinka >> "$LOG_FILE" 2>&1 &
+    pid=$!
+    counter=0
+    while kill -0 $pid 2>/dev/null; do
+        counter=$((counter + 1))
+        show_progress $CURRENT_STEP $TOTAL_STEPS "正在安装Blinka... ${counter}s"
+        sleep 1
+    done
+    wait $pid 2>/dev/null
+
+    success_msg "Adafruit Blinka安装完成"
+    log_message "INFO" "Adafruit Blinka安装完成"
+    show_progress $CURRENT_STEP $TOTAL_STEPS "Blinka安装完成"
+    echo
+
+    #
+    # 步骤 9: 安装 SSD1306 驱动
+    #
+    start_step "安装SSD1306驱动库"
+    status_msg "正在安装OLED驱动..."
+
+    pip3 install --break-system-packages adafruit-circuitpython-ssd1306 >> "$LOG_FILE" 2>&1 &
+    pid=$!
+    counter=0
+    while kill -0 $pid 2>/dev/null; do
+        counter=$((counter + 1))
+        show_progress $CURRENT_STEP $TOTAL_STEPS "正在安装SSD1306... ${counter}s"
+        sleep 1
+    done
+    wait $pid 2>/dev/null
+
+    success_msg "SSD1306驱动安装完成"
+    log_message "INFO" "SSD1306驱动安装完成"
+    show_progress $CURRENT_STEP $TOTAL_STEPS "驱动安装完成"
+    echo
+
+    # #
+    # # 步骤 10: 强制重新安装 Pillow(中文显示必需)
+    # #
+    # start_step "强制安装Pillow库"
+    # status_msg "正在重新安装Pillow库(中文显示必需)..."
+
+    # pip3 uninstall -y pillow >> "$LOG_FILE" 2>&1 || true
+    # pip3 install --break-system-packages --force-reinstall pillow >> "$LOG_FILE" 2>&1 &
+    # pid=$!
+    # counter=0
+    # while kill -0 $pid 2>/dev/null; do
+    #     counter=$((counter + 1))
+    #     show_progress $CURRENT_STEP $TOTAL_STEPS "正在安装Pillow... ${counter}s"
+    #     sleep 1
+    # done
+    # wait $pid 2>/dev/null
+
+    # success_msg "Pillow库强制安装完成"
+    # log_message "INFO" "Pillow库强制安装完成"
+    # show_progress $CURRENT_STEP $TOTAL_STEPS "Pillow安装完成"
+    # echo
+    #
+    # 步骤 10: 检查并安装 Pillow(中文显示依赖)
+    #
+    start_step "检查 Pillow 库(中文显示依赖)"
+    status_msg "正在检测系统中是否已安装 Pillow 库..."
+
+    # 检查 Pillow 是否存在
+    if python3 -c "import PIL" &>/dev/null; then
+        success_msg "系统已安装 Pillow 库,跳过安装"
+        log_message "INFO" "Pillow 已存在,跳过安装"
+        show_progress $CURRENT_STEP $TOTAL_STEPS "Pillow 已存在,跳过"
+    else
+        warn_msg "未检测到 Pillow 库,开始安装..."
+        log_message "INFO" "开始安装 Pillow 库"
+        (
+            pip3 install --break-system-packages --upgrade pillow >> "$LOG_FILE" 2>&1
+        ) &
+        pid=$!
+        counter=0
+        while kill -0 $pid 2>/dev/null; do
+            counter=$((counter + 1))
+            show_progress $CURRENT_STEP $TOTAL_STEPS "正在安装 Pillow... ${counter}s"
+            sleep 1
+        done
+        wait $pid 2>/dev/null
+
+        if python3 -c "import PIL" &>/dev/null; then
+            success_msg "Pillow 库安装完成"
+            log_message "INFO" "Pillow 安装成功"
+            show_progress $CURRENT_STEP $TOTAL_STEPS "Pillow 安装完成"
+        else
+            error_msg "Pillow 安装失败,请检查日志"
+            log_message "ERROR" "Pillow 安装失败"
+        fi
+    fi
+
+    echo
+
+    #
+    # 步骤 11: 启用 I2C 接口
+    #
+    start_step "配置I2C接口"
+    status_msg "正在启用并配置I2C接口..."
+
+    # 尝试使用 raspi-config 非交互方式启用 I2C(若可用)
+    if command -v raspi-config >/dev/null 2>&1; then
+        raspi-config nonint do_i2c 0 >> "$LOG_FILE" 2>&1 || true
+    fi
+
+    # 加载 I2C 模块(兼容性处理)
+    modprobe i2c-dev >> "$LOG_FILE" 2>&1 || true
+    modprobe i2c-bcm2835 >> "$LOG_FILE" 2>&1 || true
+
+    # 确保 /etc/modules 包含 i2c 模块(避免重复写入)
+    if ! grep -q '^i2c-dev' /etc/modules 2>/dev/null; then
+        echo "i2c-dev" >> /etc/modules
+    fi
+    if ! grep -q '^i2c-bcm2835' /etc/modules 2>/dev/null; then
+        echo "i2c-bcm2835" >> /etc/modules
+    fi
+
+    # 更新 config.txt(只追加一次)
+    if ! grep -q '^dtparam=i2c_arm=on' /boot/config.txt 2>/dev/null; then
+        echo "dtparam=i2c_arm=on,i2c_arm_baudrate=400000" >> /boot/config.txt
+    fi
+
+    sleep 2
+    success_msg "I2C接口配置完成"
+    log_message "INFO" "I2C接口配置完成"
+    show_progress $CURRENT_STEP $TOTAL_STEPS "I2C配置完成"
+    echo
+
+    #
+    # 步骤 12: 检测 I2C 设备
+    #
+    start_step "检测I2C设备"
+    status_msg "正在扫描I2C总线..."
+    echo -e "${YELLOW}I2C设备列表:${NC}"
+    i2cdetect -y 1 | tee -a "$LOG_FILE" 2>&1
+
+    # 检查 OLED 设备地址(3c 或 3d)
+    OLED_FOUND=$(i2cdetect -y 1 | grep -E "(3c|3d)" || true)
+    if [ -n "$OLED_FOUND" ]; then
+        success_msg "✅ 检测到OLED设备: $OLED_FOUND"
+        log_message "INFO" "检测到OLED设备: $OLED_FOUND"
+    else
+        error_msg "❌ 未检测到OLED设备"
+        error_msg "请检查OLED屏幕接线和电源"
+        log_message "ERROR" "未检测到OLED设备"
+
+        # 显示接线提示(中文)
+        echo -e "${CYAN}接线提示:${NC}"
+        echo -e "  VCC -> 3.3V (Pin 1)"
+        echo -e "  GND -> GND (Pin 6)"
+        echo -e "  SDA -> SDA (Pin 3)"
+        echo -e "  SCL -> SCL (Pin 5)"
+        echo
+
+        read -p "⚠️  确认继续安装? (y/n): " -n 1 -r
+        echo
+        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+            error_msg "安装已取消"
+            log_message "INFO" "用户取消安装"
+            exit 0
+        fi
+    fi
+    show_progress $CURRENT_STEP $TOTAL_STEPS "I2C检测完成"
+    echo
+
+    #
+    # 步骤 13: 复制程序文件到安装目录
+    #
+    start_step "部署程序文件"
+    status_msg "正在复制终极修复版程序..."
+
+    cp "$MAIN_PROGRAM" "$INSTALL_DIR/" 2>>"$LOG_FILE" || abort "复制主程序失败,请检查权限"
+    chmod 755 "$INSTALL_DIR/$MAIN_PROGRAM"
+
+    # 创建配置 & 日志目录
+    mkdir -p "$INSTALL_DIR/config"
+    chmod 755 "$INSTALL_DIR/config"
+    mkdir -p "$INSTALL_DIR/logs"
+    chmod 755 "$INSTALL_DIR/logs"
+
+    success_msg "程序文件部署完成"
+    log_message "INFO" "程序文件部署完成"
+
+    echo -e "${YELLOW}文件列表:${NC}"
+    ls -la "$INSTALL_DIR/" | tee -a "$LOG_FILE"
+    show_progress $CURRENT_STEP $TOTAL_STEPS "文件部署完成"
+    echo
+
+    #
+    # 步骤 14: 设置权限
+    #
+    start_step "设置系统权限"
+    status_msg "正在配置文件权限..."
+
+    chown -R "$SYSTEM_USER:$SYSTEM_GROUP" "$INSTALL_DIR"
+    chmod -R 755 "$INSTALL_DIR"
+
+    # 设置日志文件权限
+    touch "$INSTALL_DIR/logs/monitor.log"
+    chmod 644 "$INSTALL_DIR/logs/monitor.log"
+    chown "$SYSTEM_USER:$SYSTEM_GROUP" "$INSTALL_DIR/logs/monitor.log"
+
+    # 验证权限并列出
+    echo -e "${YELLOW}权限验证:${NC}"
+    ls -ld "$INSTALL_DIR"
+    ls -la "$INSTALL_DIR/$MAIN_PROGRAM"
+
+    success_msg "权限设置完成"
+    log_message "INFO" "权限设置完成"
+    show_progress $CURRENT_STEP $TOTAL_STEPS "权限配置完成"
+    echo
+
+    #
+    # 步骤 15: 创建 systemd 服务(终极修复版)
+    #
+    start_step "创建系统服务"
+    status_msg "正在配置systemd服务..."
+
+    cat > "/etc/systemd/system/$SERVICE_NAME" << EOF
+[Unit]
+Description=OLED中文系统监控器(终极修复版)
+After=network.target i2c-dev.service systemd-modules-load.service
+Wants=i2c-dev.service
+
+[Service]
+Type=simple
+User=$SYSTEM_USER
+Group=$SYSTEM_GROUP
+WorkingDirectory=$INSTALL_DIR
+ExecStart=/usr/bin/python3 $INSTALL_DIR/$MAIN_PROGRAM >> $INSTALL_DIR/logs/monitor.log 2>&1
+Restart=always
+RestartSec=10
+Environment="PYTHONPATH=/usr/local/lib/python3.9/dist-packages:/usr/lib/python3/dist-packages"
+Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+# 终极修复版特殊配置
+ExecStartPre=/bin/sleep 5
+ExecStartPre=/bin/chmod 755 $INSTALL_DIR/$MAIN_PROGRAM
+ExecStartPre=/bin/bash -c "modprobe i2c-dev; modprobe i2c-bcm2835"
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+    # 重新加载 systemd 单元
+    systemctl daemon-reload
+    success_msg "系统服务创建完成"
+    log_message "INFO" "系统服务创建完成"
+    show_progress $CURRENT_STEP $TOTAL_STEPS "服务创建完成"
+    echo
+
+    #
+    # 步骤 16: 启动服务并测试
+    #
+    start_step "启动并测试服务"
+    status_msg "正在启动终极修复版监控器服务..."
+
+    # 尝试停止同名服务(以防重复)
+    systemctl stop "$SERVICE_NAME" > /dev/null 2>&1 || true
+
+    # 启用并启动服务
+    systemctl enable "$SERVICE_NAME" >> "$LOG_FILE" 2>&1
+    systemctl start "$SERVICE_NAME" >> "$LOG_FILE" 2>&1 || true
+
+    # 等待一段时间观察服务是否启动
+    echo -e "${YELLOW}等待服务启动...${NC}"
+    for i in {1..10}; do
+        show_progress $CURRENT_STEP $TOTAL_STEPS "服务启动中... ${i}s"
+        sleep 1
+    done
+    echo
+
+    # 检查服务状态
+    if systemctl is-active --quiet "$SERVICE_NAME"; then
+        success_msg "🎉 终极修复版服务启动成功!"
+        log_message "INFO" "服务启动成功"
+
+        # 显示服务信息(短)
+        echo -e "${CYAN}服务信息:${NC}"
+        systemctl status "$SERVICE_NAME" --no-pager -l | sed -n '1,10p'
+        echo
+
+        # 显示实时日志(前10行)
+        echo -e "\n${CYAN}实时日志(前10行):${NC}"
+        tail -n 10 "$INSTALL_DIR/logs/monitor.log"
+    else
+        error_msg "服务启动失败"
+        log_message "ERROR" "服务启动失败"
+
+        echo -e "${YELLOW}错误日志(journalctl 末尾):${NC}"
+        journalctl -u "$SERVICE_NAME" --no-pager -n 20
+
+        echo -e "${YELLOW}监控器日志:${NC}"
+        if [ -f "$INSTALL_DIR/logs/monitor.log" ]; then
+            tail -n 20 "$INSTALL_DIR/logs/monitor.log"
+        fi
+
+        warning_msg "请检查错误日志并重新安装"
+    fi
+    show_progress $CURRENT_STEP $TOTAL_STEPS "服务启动完成"
+    echo
+
+    #
+    # 安装后验证(附加检查)
+    #
+    start_step "安装后验证"
+    status_msg "正在验证安装结果..."
+
+    PROCESS_COUNT=$(ps aux | grep "$MAIN_PROGRAM" | grep -v grep | wc -l)
+    if [ "$PROCESS_COUNT" -gt 0 ]; then
+        success_msg "✅ 程序正在运行,进程数: $PROCESS_COUNT"
+        log_message "INFO" "程序正在运行,进程数: $PROCESS_COUNT"
+
+        echo -e "${YELLOW}运行中的进程:${NC}"
+        ps aux | grep "$MAIN_PROGRAM" | grep -v grep
+    else
+        warning_msg "⚠️ 未检测到运行中的程序进程"
+        log_message "WARNING" "未检测到运行中的程序进程"
+    fi
+
+    # 检查文件完整性
+    if [ -f "$INSTALL_DIR/$MAIN_PROGRAM" ]; then
+        file_size=$(stat -c%s "$INSTALL_DIR/$MAIN_PROGRAM")
+        success_msg "✅ 程序文件完整: ${file_size} bytes"
+        log_message "INFO" "程序文件完整: ${file_size} bytes"
+    else
+        error_msg "❌ 程序文件缺失"
+        log_message "ERROR" "程序文件缺失"
+    fi
+
+    show_progress $CURRENT_STEP $TOTAL_STEPS "安装验证完成"
+    echo
+
+    # 最终完成提示
+    echo -e "\n\n${GREEN}=============================================${NC}"
+    echo -e "${MAGENTA}🎉 OLED中文监控器终极修复版安装完成!${NC}"
+    echo -e "${GREEN}=============================================${NC}"
+    echo
+    echo -e "${YELLOW}📊 安装统计:${NC}"
+    echo -e "   总步骤: $TOTAL_STEPS"
+    echo -e "   完成率: 100%"
+    echo -e "   安装目录: $INSTALL_DIR"
+    echo -e "   主程序: $MAIN_PROGRAM"
+    echo -e "   服务名称: $SERVICE_NAME"
+    echo -e "   日志文件: $LOG_FILE"
+    echo
+    echo -e "${CYAN}🔧 管理命令:${NC}"
+    echo -e "   📖 查看日志: journalctl -u $SERVICE_NAME -f"
+    echo -e "   📖 程序日志: tail -f $INSTALL_DIR/logs/monitor.log"
+    echo -e "   🛑 停止服务: systemctl stop $SERVICE_NAME"
+    echo -e "   🔁 重启服务: systemctl restart $SERVICE_NAME"
+    echo -e "   📊 查看状态: systemctl status $SERVICE_NAME"
+    echo -e "   📁 程序目录: cd $INSTALL_DIR && ls -la"
+    echo -e "   🧪 测试运行: cd $INSTALL_DIR && python3 $MAIN_PROGRAM"
+    echo
+    echo -e "${YELLOW}💡 终极修复特色:${NC}"
+    echo -e "   - 彻底解决draw属性初始化问题"
+    echo -e "   - 多层备用机制确保稳定运行"
+    echo -e "   - 详细的调试日志和错误处理"
+    echo -e "   - 智能I2C地址检测"
+    echo -e "   - 自动字体安装和验证"
+    echo -e "   - 全新的安装目录避免冲突"
+    echo
+    echo -e "${RED}⚠️  重要提醒:${NC}"
+    echo -e "   - 如果服务启动失败,请查看详细日志"
+    echo -e "   - 安装日志已保存到: $LOG_FILE"
+    echo -e "   - 程序日志已保存到: $INSTALL_DIR/logs/monitor.log"
+    echo -e "   - OLED屏幕应显示中文监控信息"
+    echo -e "   - 如有问题请提供完整日志文件"
+    echo
+    echo -e "${GREEN}=============================================${NC}"
+    echo -e "${MAGENTA}终极修复版安装完成!祝您使用愉快!${NC}"
+    echo -e "${GREEN}=============================================${NC}"
+
+    log_message "INFO" "终极修复版安装完成"
+}
+
+# ---------------------------
+# 帮助函数:在必要处退出并记录日志
+# ---------------------------
+abort() {
+    echo -e "${RED}安装中遇到致命错误:$1${NC}"
+    log_message "ERROR" "$1"
+    exit 1
+}
+
+# 启动主函数
+main

+ 805 - 0
oled_system_monitor_final.py

@@ -0,0 +1,805 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+OLED系统监控器 - 树莓派4B专用版
+功能:触摸唤醒(GPIO18->1M电阻->金属片->GPIO24)+ 30秒自动熄屏
+"""
+import time
+import socket
+import psutil
+from datetime import datetime
+import RPi.GPIO as GPIO
+import sys
+
+# 全局变量
+DRAW_OBJECT = None
+
+class I2CDevice:
+    def __init__(self, address, busnum=1):
+        import smbus2  # 树莓派4B推荐使用smbus2
+        self._address = address
+        self._bus = smbus2.SMBus(busnum)
+    
+    def write8(self, register, value):
+        self._bus.write_byte_data(self._address, register, value)
+        
+    def writeList(self, register, data):
+        self._bus.write_i2c_block_data(self._address, register, data)
+
+class SSD1306Final:
+    """SSD1306驱动(树莓派4B优化版)"""
+    
+    # SSD1306寄存器地址
+    SETCONTRAST = 0x81
+    DISPLAYALLON_RESUME = 0xA4
+    NORMALDISPLAY = 0xA6
+    DISPLAYOFF = 0xAE
+    DISPLAYON = 0xAF
+    SETDISPLAYOFFSET = 0xD3
+    SETCOMPINS = 0xDA
+    SETVCOMDETECT = 0xDB
+    SETDISPLAYCLOCKDIV = 0xD5
+    SETPRECHARGE = 0xD9
+    SETMULTIPLEX = 0xA8
+    SETSTARTLINE = 0x40
+    MEMORYMODE = 0x20
+    COLUMNADDR = 0x21
+    PAGEADDR = 0x22
+    COMSCANDEC = 0xC8
+    SEGREMAP = 0xA0
+    CHARGEPUMP = 0x8D
+    
+    def __init__(self, width=128, height=64, address=0x3C):
+        global DRAW_OBJECT
+        
+        print("=" * 60)
+        print("SSD1306Final 初始化开始...")
+        print(f"设备: 树莓派4B专用优化")
+        print(f"分辨率: {width}x{height}")
+        print(f"I2C地址: 0x{address:02X}")
+        print("=" * 60)
+        
+        self.width = width
+        self.height = height
+        self.address = address
+        self._device = None
+        self.buffer = [0] * (self.width * self.height // 8)
+        self.image = None
+        self.fonts = None
+        
+        # 1. 检查PIL库
+        self._check_pil()
+        
+        # 2. 初始化draw对象
+        self._force_init_draw()
+        
+        # 3. 初始化I2C设备(树莓派4B优化)
+        self._init_i2c(address)
+        
+        # 4. 初始化SSD1306硬件
+        if self._device:
+            self._initialize_hardware()
+        
+        # 5. 加载字体
+        self._load_fonts()
+        
+        print("SSD1306Final 初始化完成!")
+        print(f"draw对象状态: {'✅ 可用' if self.draw else '❌ 不可用'}")
+        print(f"I2C设备状态: {'✅ 连接' if self._device else '❌ 未连接'}")
+        print("=" * 60)
+    
+    def _check_pil(self):
+        """检查PIL库"""
+        global DRAW_OBJECT
+        
+        try:
+            from PIL import Image, ImageDraw, ImageFont
+            self.pil_available = True
+            self.Image = Image
+            self.ImageDraw = ImageDraw
+            self.ImageFont = ImageFont
+            print(" PIL库检查通过")
+        except ImportError as e:
+            self.pil_available = False
+            print(f" PIL库导入失败: {e}")
+            print("  正在尝试安装Pillow库...")
+            import subprocess
+            try:
+                subprocess.check_call([sys.executable, "-m", "pip", "install", "pillow"])
+                from PIL import Image, ImageDraw, ImageFont
+                self.pil_available = True
+                self.Image = Image
+                self.ImageDraw = ImageDraw
+                self.ImageFont = ImageFont
+                print(" Pillow库安装成功")
+            except Exception as e2:
+                print(f" Pillow库安装失败: {e2}")
+    
+    def _force_init_draw(self):
+        """强制初始化draw对象"""
+        global DRAW_OBJECT
+        
+        print(" 初始化draw对象...")
+        
+        if self.pil_available and hasattr(self, 'Image') and hasattr(self, 'ImageDraw'):
+            try:
+                self.image = self.Image.new('1', (self.width, self.height))
+                self.draw = self.ImageDraw.Draw(self.image)
+                DRAW_OBJECT = self.draw
+                print(" draw对象创建成功")
+            except Exception as e:
+                print(f" PIL创建draw失败: {e}")
+                self._create_fallback_draw()
+        else:
+            print(" 创建备用draw对象")
+            self._create_fallback_draw()
+        
+        if not hasattr(self, 'draw') or self.draw is None:
+            self._create_fallback_draw()
+        
+        DRAW_OBJECT = self.draw
+    
+    def _create_fallback_draw(self):
+        """创建备用draw对象"""
+        class FallbackDraw:
+            def text(self, *args, **kwargs):
+                print(f" 文本绘制: {args}")
+            def rectangle(self, *args, **kwargs):
+                print(f" 矩形绘制: {args}")
+        
+        self.draw = FallbackDraw()
+        print(" 使用备用draw对象")
+    
+    def _init_i2c(self, address):
+        """初始化I2C设备(树莓派4B优化)"""
+        print(f"🔌 初始化I2C设备 @ 0x{address:02X}...")
+        try:
+            self._device = I2CDevice(address)
+            print(f" I2C设备连接成功")
+        except Exception as e:
+            self._device = None
+            print(f" I2C设备连接失败: {e}")
+            print(" 请检查I2C是否启用: sudo raspi-config -> 启用I2C")
+    
+    def _initialize_hardware(self):
+        """初始化SSD1306硬件"""
+        if not self._device:
+            print(" 跳过硬件初始化")
+            return
+        
+        print(" 初始化SSD1306硬件...")
+        try:
+            init_commands = [
+                self.DISPLAYOFF,
+                self.SETDISPLAYCLOCKDIV, 0x80,
+                self.SETMULTIPLEX, 0x3F,
+                self.SETDISPLAYOFFSET, 0x00,
+                self.SETSTARTLINE | 0x00,
+                self.CHARGEPUMP, 0x14,
+                self.MEMORYMODE, 0x00,
+                self.SEGREMAP | 0x01,
+                self.COMSCANDEC,
+                self.SETCOMPINS, 0x12,
+                self.SETCONTRAST, 0xFF,
+                self.SETPRECHARGE, 0xF1,
+                self.SETVCOMDETECT, 0x40,
+                self.DISPLAYALLON_RESUME,
+                self.NORMALDISPLAY,
+                self.DISPLAYON
+            ]
+            
+            for cmd in init_commands:
+                self.command(cmd)
+                time.sleep(0.01)  # 树莓派4B增加命令间隔
+            
+            self.clear()
+            self.display()
+            print(" SSD1306硬件初始化成功")
+        except Exception as e:
+            print(f" SSD1306硬件初始化失败: {e}")
+    
+    def _load_fonts(self):
+        """加载字体"""
+        self.fonts = {}
+        
+        if not self.pil_available or not hasattr(self, 'ImageFont'):
+            print(" 无法加载字体")
+            return
+        
+        print(" 加载字体...")
+        
+        # 中文字体路径(树莓派常用路径)
+        font_paths = [
+            '/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc',
+            '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf',
+            '/usr/share/fonts/truetype/freefont/FreeSans.ttf'
+        ]
+        
+        font_path = None
+        for path in font_paths:
+            try:
+                self.ImageFont.truetype(path, 12)
+                font_path = path
+                break
+            except Exception as e:
+                print(f"  字体 {path} 不可用: {e}")
+        
+        if font_path:
+            print(f" 找到字体: {font_path}")
+            try:
+                self.fonts['small'] = self.ImageFont.truetype(font_path, 12)
+                self.fonts['medium'] = self.ImageFont.truetype(font_path, 14)
+                self.fonts['large'] = self.ImageFont.truetype(font_path, 18)
+                print(" 字体加载完成")
+            except Exception as e:
+                print(f" 字体加载失败: {e}")
+                self._load_default_fonts()
+        else:
+            print(" 使用默认字体")
+            self._load_default_fonts()
+    
+    def _load_default_fonts(self):
+        """加载默认字体"""
+        if not self.pil_available or not hasattr(self, 'ImageFont'):
+            return
+        
+        try:
+            self.fonts['small'] = self.ImageFont.load_default(size=10)
+            self.fonts['medium'] = self.ImageFont.load_default(size=12)
+            self.fonts['large'] = self.ImageFont.load_default(size=14)
+            print(" 默认字体加载完成")
+        except Exception as e:
+            print(f" 默认字体加载失败: {e}")
+    
+    def command(self, cmd):
+        """发送命令"""
+        if self._device:
+            try:
+                self._device.write8(0x00, cmd)
+            except Exception as e:
+                print(f" 命令发送失败: {e}")
+    
+    def clear(self):
+        """清空显示"""
+        self.buffer = [0] * (self.width * self.height // 8)
+        if self.draw:
+            try:
+                self.draw.rectangle((0, 0, self.width, self.height), fill=0)
+            except Exception as e:
+                print(f" 清屏失败: {e}")
+    
+    def display(self):
+        """更新显示"""
+        if not self._device:
+            print(" I2C设备未连接")
+            return
+        
+        try:
+            self.command(self.COLUMNADDR)
+            self.command(0)
+            self.command(self.width - 1)
+            
+            self.command(self.PAGEADDR)
+            self.command(0)
+            self.command(self.height // 8 - 1)
+            
+            if self.image:
+                for y in range(self.height):
+                    for x in range(self.width):
+                        if self.image.getpixel((x, y)):
+                            self.draw_pixel(x, y, True)
+            
+            for i in range(0, len(self.buffer), 16):
+                chunk = self.buffer[i:i+16]
+                self._device.writeList(0x40, chunk)
+                
+            print(" 显示更新成功")
+        except Exception as e:
+            print(f" 显示更新失败: {e}")
+    
+    def draw_pixel(self, x, y, color=True):
+        """绘制像素"""
+        if x < 0 or x >= self.width or y < 0 or y >= self.height:
+            return
+        
+        page = y // 8
+        bit_in_page = y % 8
+        buffer_index = page * self.width + x
+        
+        if color:
+            self.buffer[buffer_index] |= (1 << bit_in_page)
+        else:
+            self.buffer[buffer_index] &= ~(1 << bit_in_page)
+    
+    def draw_text(self, x, y, text, font_size='medium', color=1):
+        """绘制文本"""
+        if not self.draw:
+            print(f" 无法绘制文本: {text}")
+            return
+            
+        if not self.fonts or font_size not in self.fonts:
+            print(f" 使用默认字体绘制: {text}")
+            if self.pil_available and hasattr(self, 'ImageFont'):
+                font = self.ImageFont.load_default(size=12)
+            else:
+                return
+        
+        font = self.fonts.get(font_size, self.fonts.get('medium', None))
+        if not font:
+            print(f" 无法绘制文本: {text}")
+            return
+        
+        try:
+            color = 1 if color != 0 else 0
+            self.draw.text((x, y), text, font=font, fill=color)
+            print(f" 文本绘制成功: '{text}'")
+        except Exception as e:
+            print(f" 文本绘制失败 '{text}': {e}")
+    
+    def draw_text_centered(self, y, text, font_size='medium', color=1):
+        """居中绘制文本"""
+        if not self.draw or not self.fonts or font_size not in self.fonts:
+            self.draw_text(0, y, text, font_size, color)
+            return
+        
+        font = self.fonts[font_size]
+        try:
+            text_width, text_height = font.getsize(text)
+            x = (self.width - text_width) // 2
+            color = 1 if color != 0 else 0
+            self.draw.text((x, y), text, font=font, fill=color)
+            print(f" 居中文本绘制成功: '{text}'")
+        except Exception as e:
+            print(f" 居中文本绘制失败 '{text}': {e}")
+            self.draw_text(0, y, text, font_size, color)
+    
+    def draw_rectangle(self, x, y, width, height, fill=False, outline=True):
+        """绘制矩形"""
+        if not self.draw:
+            print(f" 无法绘制矩形")
+            return
+            
+        try:
+            self.draw.rectangle((x, y, x + width - 1, y + height - 1), 
+                              fill=fill, outline=outline)
+            print(f" 矩形绘制成功")
+        except Exception as e:
+            print(f" 矩形绘制失败: {e}")
+
+def get_cpu_temperature():
+    """获取CPU温度"""
+    try:
+        with open('/sys/class/thermal/thermal_zone0/temp', 'r') as f:
+            temp = float(f.read()) / 1000.0
+        return temp
+    except Exception as e:
+        print(f" 获取温度失败: {e}")
+        return 0.0
+
+def get_ip_address():
+    """获取IP地址"""
+    try:
+        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        s.connect(("8.8.8.8", 80))
+        ip = s.getsockname()[0]
+        s.close()
+        return ip
+    except Exception as e:
+        print(f" 获取IP失败: {e}")
+        return "Unknown"
+
+def format_time_long(seconds):
+    """格式化时间"""
+    days = int(seconds // (3600 * 24))
+    hours = int((seconds % (3600 * 24)) // 3600)
+    minutes = int((seconds % 3600) // 60)
+    secs = int(seconds % 60)
+    
+    if days > 0:
+        return f"{days}天{hours}时"
+    elif hours > 0:
+        return f"{hours}时{minutes}分"
+    else:
+        return f"{minutes}分{secs}秒"
+
+def format_bytes_short(bytes_value):
+    """格式化字节数"""
+    if bytes_value < 1024:
+        return f"{bytes_value}B"
+    elif bytes_value < 1024 * 1024:
+        return f"{bytes_value / 1024:.0f}K"
+    elif bytes_value < 1024 * 1024 * 1024:
+        return f"{bytes_value / (1024 * 1024):.0f}M"
+    else:
+        return f"{bytes_value / (1024 * 1024 * 1024):.1f}G"
+
+class ChineseSystemMonitorFinal:
+    """树莓派4B专用系统监控器"""
+    
+    def __init__(self):
+        self.display = None
+        self.startup_time = time.time()
+        
+        # 触摸功能配置(树莓派4B优化)
+        self.GPIO_TOUCH_OUT = 18  # BCM18 (物理引脚12)
+        self.GPIO_TOUCH_IN = 24   # BCM24 (物理引脚18)
+        self.last_touch_time = time.time()
+        self.screen_on = True
+        self.screen_timeout = 30  # 自动熄屏时间(秒)
+        self.touch_available = False
+        
+        print("=" * 60)
+        print(" 树莓派4B专用OLED监控器 v2.5")
+        print(" 触摸功能: GPIO18->1M电阻->金属片->GPIO24")
+        print("⏱ 自动熄屏: 30秒无操作")
+        print("=" * 60)
+        print(f"启动时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
+        print(f"Python版本: {sys.version}")
+        print("=" * 60)
+        
+        try:
+            # 树莓派4B启动延时
+            print("⏳ 系统启动延迟...")
+            time.sleep(3)
+            
+            # 初始化GPIO触摸功能
+            self.init_gpio()
+            
+            # 初始化显示
+            self._init_display()
+            
+            # 显示启动信息
+            self._show_startup_screen()
+            
+        except Exception as e:
+            print(f" 初始化错误: {e}")
+            import traceback
+            traceback.print_exc()
+    
+    def init_gpio(self):
+        """初始化树莓派4B GPIO(优化版)"""
+        print(" 初始化触摸GPIO...")
+        try:
+            # 树莓派4B必须用BCM模式
+            GPIO.setmode(GPIO.BCM)
+            GPIO.setwarnings(False)  # 关闭GPIO警告
+            
+            # 配置充电GPIO(输出模式)
+            GPIO.setup(self.GPIO_TOUCH_OUT, GPIO.OUT)
+            GPIO.output(self.GPIO_TOUCH_OUT, GPIO.LOW)  # 初始低电平
+            
+            # 配置感应GPIO(输入模式)
+            GPIO.setup(self.GPIO_TOUCH_IN, GPIO.IN, pull_up_down=GPIO.PUD_OFF)
+            
+            # 验证初始电平(关键调试信息)
+            print(f" GPIO{self.GPIO_TOUCH_OUT}输出电平: {GPIO.input(self.GPIO_TOUCH_OUT)} (应为0)")
+            print(f" GPIO{self.GPIO_TOUCH_IN}初始电平: {GPIO.input(self.GPIO_TOUCH_IN)} (未触摸时可能为0或1)")
+            
+            self.touch_available = True
+            print(" GPIO初始化成功")
+            print(f"   物理引脚对应: GPIO18=12号, GPIO24=18号")
+        except Exception as e:
+            self.touch_available = False
+            print(f" GPIO初始化失败: {e}")
+            print(" 请检查是否安装RPi.GPIO: pip3 install RPi.GPIO")
+    
+    def check_touch(self):
+        """树莓派4B专用触摸检测(基于RC电路充放电时间检测)"""
+        if not self.touch_available:
+            return False
+        
+        try:
+            # 1. 放电阶段:输出低电平,让电容放电
+            GPIO.output(self.GPIO_TOUCH_OUT, GPIO.LOW)
+            time.sleep(0.001)  # 1ms放电时间
+            
+            # 2. 充电检测阶段:输出高电平,测量上升沿时间
+            GPIO.setup(self.GPIO_TOUCH_IN, GPIO.IN, pull_up_down=GPIO.PUD_OFF)
+            GPIO.output(self.GPIO_TOUCH_OUT, GPIO.HIGH)
+            
+            # 计算放电时间
+            discharge_time = 0
+            start_time = time.time_ns()
+            threshold = 3000  # 触摸检测阈值,单位微秒
+            
+            # 等待输入变为高电平或超时
+            while GPIO.input(self.GPIO_TOUCH_IN) == GPIO.LOW and discharge_time < threshold * 2:
+                discharge_time = (time.time_ns() - start_time) // 1000  # 转换为微秒
+            
+            # 3. 恢复初始状态
+            GPIO.output(self.GPIO_TOUCH_OUT, GPIO.LOW)
+            
+            # 4. 判断是否触摸
+            is_touched = discharge_time > threshold
+            
+            if is_touched:
+                print(f" 检测到有效触摸! 放电时间: {discharge_time}μs")
+                return True
+            else:
+                # 添加调试信息
+                print(f" 触摸检测 - 放电时间: {discharge_time}μs (阈值: {threshold}μs)")
+                
+        except Exception as e:
+            print(f" 触摸检测异常: {e}")
+        
+        return False
+    
+    def turn_screen_on(self):
+        """树莓派4B屏幕点亮优化(增加时序等待)"""
+        if not self.display or not hasattr(self.display, 'command'):
+            return
+        
+        if not self.screen_on:
+            print("💡 尝试点亮屏幕...")
+            # 发送点亮命令
+            self.display.command(self.display.DISPLAYON)
+            # 树莓派4B需要等待OLED响应
+            time.sleep(0.2)
+            # 强制刷新显示内容
+            system_info = self.get_system_info()
+            if system_info:
+                self.draw_main_screen(system_info)
+            self.screen_on = True
+            print(" 屏幕已点亮")
+    
+    def turn_screen_off(self):
+        """关闭屏幕"""
+        if not self.display or not hasattr(self.display, 'command'):
+            return
+        
+        if self.screen_on:
+            self.display.command(self.display.DISPLAYOFF)
+            self.screen_on = False
+            print(" 屏幕已关闭")
+    
+    def _init_display(self):
+        """初始化显示设备"""
+        print(" 初始化显示设备...")
+        
+        # 尝试树莓派常用I2C地址
+        addresses = [0x3C, 0x3D]
+        
+        for addr in addresses:
+            print(f"尝试I2C地址: 0x{addr:02X}")
+            try:
+                self.display = SSD1306Final(address=addr)
+                if self.display:
+                    print(f"✅ 显示设备初始化成功 @ 0x{addr:02X}")
+                    return
+            except Exception as e:
+                print(f" 地址0x{addr:02X}初始化失败: {e}")
+        
+        print(" 创建模拟显示")
+        self._create_mock_display()
+    
+    def _create_mock_display(self):
+        """创建模拟显示对象"""
+        class MockDisplay:
+            def __init__(self):
+                self.draw = None
+                self.fonts = {}
+                
+                class MockDraw:
+                    def text(self, *args, **kwargs):
+                        print(f" [模拟] 文本: {args}")
+                    def rectangle(self, *args, **kwargs):
+                        print(f" [模拟] 矩形: {args}")
+                
+                self.draw = MockDraw()
+                self.command = lambda x: None
+        
+        self.display = MockDisplay()
+        print(" 模拟显示对象创建成功")
+    
+    def _show_startup_screen(self):
+        """显示启动屏幕"""
+        if not self.display or not self.display.draw:
+            print(" 无法显示启动屏幕")
+            return
+        
+        print(" 显示启动屏幕...")
+        try:
+            self.display.clear()
+            self.display.draw_text_centered(10, "系统监控器", 'large')
+            self.display.draw_text_centered(35, "树莓派4B专用", 'small')
+            self.display.display()
+            time.sleep(2)
+            
+        except Exception as e:
+            print(f" 启动屏幕显示失败: {e}")
+    
+    def get_system_info(self):
+        """获取系统信息"""
+        try:
+            cpu_percent = psutil.cpu_percent(interval=0)
+            memory = psutil.virtual_memory()
+            disk = psutil.disk_usage('/')
+            temp = get_cpu_temperature()
+            system_uptime = time.time() - psutil.boot_time()
+            monitor_uptime = time.time() - self.startup_time
+            ip_address = get_ip_address()
+            
+            return {
+                'cpu_percent': cpu_percent,
+                'cpu_temp': temp,
+                'mem_used': memory.used,
+                'mem_total': memory.total,
+                'mem_percent': memory.percent,
+                'disk_used': disk.used,
+                'disk_total': disk.total,
+                'disk_percent': disk.percent,
+                'system_uptime': system_uptime,
+                'monitor_uptime': monitor_uptime,
+                'datetime': datetime.now(),
+                'ip_address': ip_address
+            }
+            
+        except Exception as e:
+            print(f"⚠️ 获取系统信息失败: {e}")
+            return {}
+    
+    def draw_main_screen(self, system_info):
+        """绘制主屏幕"""
+        if not self.display or not self.display.draw:
+            print(" 无法绘制界面")
+            return False
+        
+        try:
+            self.display.clear()
+            
+            # CPU信息
+            y_offset = 0
+            if 'cpu_percent' in system_info and 'cpu_temp' in system_info:
+                cpu_text = f"CPU: {system_info['cpu_percent']:2.0f}%  温度: {system_info['cpu_temp']:3.0f}°C"
+                self.display.draw_text(2, y_offset, cpu_text, 'small')
+            
+            # 内存信息
+            y_offset += 12
+            if 'mem_used' in system_info and 'mem_total' in system_info:
+                ram_used = format_bytes_short(system_info['mem_used'])
+                ram_total = format_bytes_short(system_info['mem_total'])
+                ram_text = f"内存: {ram_used}/{ram_total}  {system_info['mem_percent']:2.0f}%"
+                self.display.draw_text(2, y_offset, ram_text, 'small')
+            
+            # 磁盘信息
+            y_offset += 14
+            if 'disk_used' in system_info and 'disk_total' in system_info:
+                disk_used = format_bytes_short(system_info['disk_used'])
+                disk_total = format_bytes_short(system_info['disk_total'])
+                disk_text = f"磁盘: {disk_used}/{disk_total} {system_info['disk_percent']:2.0f}%"
+                self.display.draw_text(2, y_offset, disk_text, 'small')
+            
+            # 系统运行时间
+            y_offset += 14
+            if 'system_uptime' in system_info:
+                uptime_str = format_time_long(system_info['system_uptime'])
+                uptime_text = f"运行: {uptime_str}"
+                self.display.draw_text(2, y_offset, uptime_text, 'small')
+            
+            # 底部状态栏
+            y_offset += 11
+            if y_offset + 11 <= 64:
+                if 'datetime' in system_info:
+                    time_str = system_info['datetime'].strftime("%H:%M")
+                    self.display.draw_text(95, y_offset + 1, time_str, 'small', 1)
+                
+                if 'ip_address' in system_info:
+                    ip_text = f"IP:{system_info['ip_address'][:12]}"
+                    self.display.draw_text(2, y_offset + 1, ip_text, 'small', 1)
+            
+            self.display.display()
+            return True
+            
+        except Exception as e:
+            print(f" 界面绘制失败: {e}")
+            return False
+    
+    def run(self):
+        """运行监控器"""
+        print(" 开始监控系统...")
+        print("按 Ctrl+C 退出")
+        print(" 触摸金属片点亮屏幕")
+        print("=" * 60)
+        
+        try:
+            update_counter = 0
+            loop_count = 0
+            while True:
+                loop_count += 1
+                # 1. 检测触摸
+                touch_detected = self.check_touch()
+                
+                # 调试用:每隔10次循环显示一次GPIO状态
+                if self.touch_available and loop_count % 10 == 0:
+                    out_level = GPIO.input(self.GPIO_TOUCH_OUT)
+                    in_level = GPIO.input(self.GPIO_TOUCH_IN)
+                    print(f"[调试] GPIO状态 - OUT({self.GPIO_TOUCH_OUT}): {out_level}, IN({self.GPIO_TOUCH_IN}): {in_level}")
+                
+                if touch_detected:
+                    print(f" 触摸事件触发 - 时间: {datetime.now().strftime('%H:%M:%S')}")
+                    self.last_touch_time = time.time()
+                    self.turn_screen_on()
+                
+                # 2. 自动熄屏检查
+                current_time = time.time()
+                if self.screen_on and (current_time - self.last_touch_time) > self.screen_timeout:
+                    print(f" 自动熄屏 - 超时时间: {self.screen_timeout}秒")
+                    self.turn_screen_off()
+                
+                # 3. 屏幕开启时更新显示
+                if self.screen_on:
+                    system_info = self.get_system_info()
+                    if system_info:
+                        draw_success = self.draw_main_screen(system_info)
+                        
+                        update_counter += 1
+                        if update_counter % 5 == 0:
+                            self._print_debug_info(system_info, draw_success)
+                else:
+                    # 屏幕关闭时也显示简要信息
+                    if loop_count % 50 == 0:  # 每50次循环显示一次
+                        print(f"💤 屏幕关闭中... 无操作时间: {current_time - self.last_touch_time:.1f}秒")
+                
+                # 4. 控制循环频率
+                time.sleep(0.1)  # 提高触摸检测频率(从0.3秒改为0.1秒)
+                
+        except KeyboardInterrupt:
+            print("\n 程序被用户中断")
+        except Exception as e:
+            print(f"\n 运行时错误: {e}")
+            import traceback
+            traceback.print_exc()
+        finally:
+            self._cleanup()
+    
+    def _print_debug_info(self, system_info, draw_success):
+        """打印调试信息"""
+        status = "" if draw_success else "❌"
+        screen_status = "亮" if self.screen_on else "熄"
+        print(f"[{datetime.now().strftime('%H:%M:%S')}] {status} 屏{screen_status} | "
+              f"CPU:{system_info.get('cpu_percent', 0):2.0f}%/{system_info.get('cpu_temp', 0):3.0f}°C | "
+              f"内存:{system_info.get('mem_percent', 0):2.0f}% | "
+              f"磁盘:{system_info.get('disk_percent', 0):2.0f}%")
+    
+    def _cleanup(self):
+        """清理资源"""
+        print("\n 清理资源...")
+        
+        # 清理GPIO
+        try:
+            if self.touch_available:
+                GPIO.cleanup([self.GPIO_TOUCH_OUT, self.GPIO_TOUCH_IN])
+                print(" GPIO资源清理完成")
+        except Exception as e:
+            print(f" GPIO清理失败: {e}")
+        
+        # 清理显示
+        try:
+            if self.display and hasattr(self.display, 'clear'):
+                self.display.clear()
+                self.display.display()
+                if hasattr(self.display, 'command'):
+                    self.display.command(self.display.DISPLAYOFF)
+            print(" 显示清理完成")
+        except Exception as e:
+            print(f" 显示清理失败: {e}")
+        
+        print(" 程序退出")
+
+def main():
+    """主函数"""
+    try:
+        # 检查树莓派4B环境
+        import platform
+        print(f"设备信息: {platform.uname()}")
+        
+        monitor = ChineseSystemMonitorFinal()
+        monitor.run()
+    except Exception as e:
+        print(f"💥 程序启动失败: {e}")
+        import traceback
+        traceback.print_exc()
+        sys.exit(1)
+
+if __name__ == "__main__":
+    main()