Implement unified uConsole Smart Power Regulator with AC detection
Major overhaul of power management system to address voltage-induced 4G module hangs through intelligent, event-driven power regulation. Key Features: - Unified power regulation based on AC power + 4G modem state - Event-driven AC detection via udev (power_supply subsystem) - Three optimized power modes for different scenarios - Automatic voltage monitoring with multi-method alerts Power Modes: - AC Connected: 2.4GHz (ondemand) - full performance - Battery + 4G: 1.8GHz (powersave) - voltage monitoring enabled - Battery Only: 2.0GHz (ondemand) - balanced performance Technical Improvements: - AC power state detection via udev events (not polling) - Edge case handling (service starts with AC connected) - Unified logging to /var/log/uconsole-power-regulator.log - Upgrade path from old 4G Power Manager - State tracking to avoid redundant regulator triggers Components: - uconsole-power-regulator.sh: Main power orchestrator - uconsole-power-daemon.sh: Background state monitoring (5s interval) - voltage-monitor.sh: Voltage checker (Battery + 4G only) - voltage-alert-notify.sh: Multi-method alerts (desktop/audio/log/LED) - voltage-monitor-control.sh: Monitor lifecycle controller - 99-uconsole-power-regulator.rules: udev event triggers - install-uconsole-power-regulator.sh: Installation + upgrade script Documentation: - Updated README.md with new system overview - Created README_CN.md (Chinese translation) - Updated TOOL-GUIDE.md with new architecture details - Updated CLAUDE.md with unified system documentation Breaking Changes: - Replaces 4G Power Manager with unified regulator - New service name: uconsole-power-regulator.service - New log file: /var/log/uconsole-power-regulator.log - Use upgrade script to migrate from old system Installation: - Fresh: sudo ./install-uconsole-power-regulator.sh install - Upgrade: sudo ./install-uconsole-power-regulator.sh upgrade - Uninstall: sudo ./install-uconsole-power-regulator.sh uninstall
This commit is contained in:
BIN
.playwright-mcp/story-assets/feb4000-battery-percentage.png
Normal file
BIN
.playwright-mcp/story-assets/feb4000-battery-percentage.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
BIN
.playwright-mcp/story-assets/feb4000-voltage-current.png
Normal file
BIN
.playwright-mcp/story-assets/feb4000-voltage-current.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
55
CLAUDE.md
55
CLAUDE.md
@@ -228,36 +228,51 @@ Indexes on `timestamp`, `created_at`, and `session_id` for efficient queries.
|
||||
- Frontend displays error state in a red error card
|
||||
- Missing or null values from sysfs are handled gracefully in `getBatteryData()`
|
||||
|
||||
## 4G Power Management System
|
||||
## uConsole Smart Power Regulator
|
||||
|
||||
Located in `scripts/` directory. **See [scripts/README-4G-POWER-MANAGER.md](scripts/README-4G-POWER-MANAGER.md) for full documentation.**
|
||||
Located in `scripts/` directory. **See [STORY.md](STORY.md) and [TOOL-GUIDE.md](TOOL-GUIDE.md) for full documentation.**
|
||||
|
||||
### Problem
|
||||
The uConsole CM5 + 4G module can peak at 22-25W power draw, but the AXP228 PMIC can only sustainably deliver ~18-20W from battery. This causes system hangs that require physical battery removal to restart.
|
||||
The 4G modem (SimTech SIM7600G-H) requires minimum 3.45V to operate reliably. When battery voltage drops below this threshold, the modem can hang the entire system, requiring physical battery removal to restart. The issue is voltage-related, not power budget.
|
||||
|
||||
### Solution Components
|
||||
### Solution: Unified Event-Driven Power Regulation
|
||||
|
||||
1. **Main Script**: `scripts/4g-power-manager.sh`
|
||||
- Detects 4G modem state (active/inactive) using multiple methods
|
||||
- Adjusts CPU governor and max frequency based on modem state
|
||||
- When 4G active: `powersave` governor + 1.8GHz max (saves ~20-30% power)
|
||||
- When 4G inactive: `ondemand` governor + 2.4GHz max (full performance)
|
||||
- Logs to `/var/log/4g-power-manager.log`
|
||||
**Key Components:**
|
||||
|
||||
2. **udev Rules**: `scripts/99-4g-power-manager.rules`
|
||||
- Triggers on USB modem device changes (vendor:product = 1e0e:9001)
|
||||
1. **uconsole-power-regulator.sh** - Main orchestrator
|
||||
- Determines power state based on AC and 4G status
|
||||
- Applies appropriate CPU settings for each state
|
||||
- Controls voltage monitoring
|
||||
- Logs to `/var/log/uconsole-power-regulator.log`
|
||||
|
||||
2. **uconsole-power-daemon.sh** - Background daemon
|
||||
- Monitors AC power and 4G modem state every 5 seconds
|
||||
- Triggers regulator only when state changes
|
||||
- Handles edge cases (e.g., service starts with AC already connected)
|
||||
|
||||
3. **Voltage Monitoring System**:
|
||||
- `voltage-monitor.sh` - Checks voltage every 5 seconds when Battery + 4G active
|
||||
- `voltage-alert-notify.sh` - Multi-method alerts (desktop notification, audio, log, LED)
|
||||
- `voltage-monitor-control.sh` - Start/stop controller
|
||||
- Alerts when voltage < 3.45V, rate-limited to every 30 seconds
|
||||
|
||||
4. **udev Rules**: `scripts/99-uconsole-power-regulator.rules`
|
||||
- Triggers on AC power connect/disconnect (power_supply subsystem)
|
||||
- Triggers on 4G modem USB device changes (vendor:product = 1e0e:9001)
|
||||
- Monitors wwan0 interface state changes
|
||||
- Responds to ttyUSB and cdc-wdm device events
|
||||
|
||||
3. **Systemd Service**: `scripts/4g-power-monitor.service` + `scripts/4g-power-monitor-daemon.sh`
|
||||
- Background daemon that checks modem state every 5 seconds
|
||||
- More reliable than udev alone for detecting state changes during network activity
|
||||
- Auto-restarts on failure
|
||||
5. **Power Modes**:
|
||||
| State | AC | 4G | Governor | Max Freq | Voltage Monitoring |
|
||||
|-------|----|----|----------|----------|-------------------|
|
||||
| AC_POWER | Connected | Any | ondemand | 2.4GHz | Off |
|
||||
| BATTERY_4G | Disconnected | Active | powersave | 1.8GHz | On |
|
||||
| BATTERY_ONLY | Disconnected | Inactive | ondemand | 2.0GHz | Off |
|
||||
|
||||
4. **Installation**: `scripts/install-4g-power-manager.sh`
|
||||
- One-command setup: `sudo ./install-4g-power-manager.sh`
|
||||
- Installs udev rules, systemd service, creates log files
|
||||
- Provides status and usage instructions
|
||||
6. **Installation**: `scripts/install-uconsole-power-regulator.sh`
|
||||
- Fresh install: `sudo ./install-uconsole-power-regulator.sh install`
|
||||
- Upgrade from old system: `sudo ./install-uconsole-power-regulator.sh upgrade`
|
||||
- Uninstall: `sudo ./install-uconsole-power-regulator.sh uninstall`
|
||||
|
||||
### Hardware Context
|
||||
|
||||
|
||||
53
README.md
53
README.md
@@ -12,24 +12,42 @@ A Next.js 16 web application designed for Raspberry Pi uConsole CM5 that monitor
|
||||
- **Session management** with custom naming and deletion
|
||||
- Reads directly from Linux sysfs (`/sys/class/power_supply/axp20x-battery/`)
|
||||
|
||||
### 4G Power Management 🔋⚡
|
||||
**NEW**: Automatic power management to prevent system hangs when using 4G module on battery.
|
||||
### uConsole Smart Power Regulator 🔋⚡
|
||||
**NEW**: Intelligent power management system that prevents voltage-induced system hangs when using 4G module on battery.
|
||||
|
||||
The uConsole CM5 + 4G module can consume 22-25W peak power, but the AXP228 PMIC can only deliver ~18-20W from battery. This causes system hangs that require battery removal to restart.
|
||||
**The Problem**: The 4G modem requires minimum 3.45V to operate reliably. When battery voltage drops below this threshold, the modem can hang the entire system, requiring physical battery removal to restart.
|
||||
|
||||
**Solution**: Automatically detects 4G modem activity and reduces CPU frequency to keep power consumption within safe limits.
|
||||
**The Solution**: Unified event-driven power regulation that:
|
||||
- **Monitors both AC power and 4G modem states** via udev events
|
||||
- **Adjusts CPU frequency dynamically** based on power source and 4G status
|
||||
- **Alerts when battery voltage is critical** (< 3.45V) with desktop notifications, audio alerts, and LED blinks
|
||||
- **Handles edge cases** like service starting with AC already connected
|
||||
|
||||
📖 **[Full Documentation: 4G Power Manager](scripts/README-4G-POWER-MANAGER.md)**
|
||||
**Power Modes:**
|
||||
| Condition | CPU Frequency | Governor | Voltage Monitoring |
|
||||
|-----------|--------------|----------|-------------------|
|
||||
| AC Connected | 2.4GHz | ondemand | Off |
|
||||
| Battery + 4G | 1.8GHz | powersave | On (< 3.45V alerts) |
|
||||
| Battery Only | 2.0GHz | ondemand | Off |
|
||||
|
||||
📖 **[Read the Full Story](STORY.md)** | **[Tool Guide](TOOL-GUIDE.md)** | **[中文版](README_CN.md)**
|
||||
|
||||
**Quick install:**
|
||||
```bash
|
||||
cd scripts
|
||||
sudo ./install-4g-power-manager.sh
|
||||
sudo ./install-uconsole-power-regulator.sh install
|
||||
```
|
||||
|
||||
**Upgrade from old 4G Power Manager:**
|
||||
```bash
|
||||
cd scripts
|
||||
sudo ./install-uconsole-power-regulator.sh upgrade
|
||||
```
|
||||
|
||||
**Uninstall:**
|
||||
```bash
|
||||
sudo ./install-4g-power-manager.sh uninstall
|
||||
cd scripts
|
||||
sudo ./install-uconsole-power-regulator.sh uninstall
|
||||
```
|
||||
|
||||
## Hardware Requirements
|
||||
@@ -162,10 +180,16 @@ battery-monitor/
|
||||
│ └── lib/
|
||||
│ ├── db.ts # SQLite database utilities
|
||||
│ └── utils.ts # Helper functions
|
||||
├── scripts/ # 4G power management scripts
|
||||
│ ├── 4g-power-manager.sh
|
||||
│ ├── install-4g-power-manager.sh
|
||||
│ └── README-4G-POWER-MANAGER.md
|
||||
├── scripts/ # uConsole Smart Power Regulator
|
||||
│ ├── uconsole-power-regulator.sh # Main power regulator
|
||||
│ ├── uconsole-power-daemon.sh # Background monitoring daemon
|
||||
│ ├── voltage-monitor.sh # Voltage monitoring script
|
||||
│ ├── voltage-alert-notify.sh # Multi-method alerting
|
||||
│ ├── voltage-monitor-control.sh # Monitor control
|
||||
│ ├── install-uconsole-power-regulator.sh
|
||||
│ └── 99-uconsole-power-regulator.rules
|
||||
├── STORY.md # Development story and voltage discovery
|
||||
├── TOOL-GUIDE.md # Complete user guide
|
||||
└── public/ # Static assets
|
||||
```
|
||||
|
||||
@@ -190,9 +214,10 @@ The application requires AXP20x hardware. On systems without this hardware, the
|
||||
|
||||
### System Hangs with 4G Module
|
||||
If your uConsole hangs when using the 4G module on battery:
|
||||
1. Install the 4G Power Manager (see [scripts/README-4G-POWER-MANAGER.md](scripts/README-4G-POWER-MANAGER.md))
|
||||
2. Consider upgrading to high-drain 18650 batteries (Samsung 25R, Sony VTC6, LG HG2)
|
||||
3. Monitor power consumption to ensure it stays below 18-20W
|
||||
1. Install the uConsole Smart Power Regulator (see installation section above)
|
||||
2. Use the Battery Monitor to check voltage levels during 4G usage
|
||||
3. Consider upgrading to batteries with better voltage retention (see [TOOL-GUIDE.md](TOOL-GUIDE.md) for battery recommendations)
|
||||
4. The regulator will alert you if voltage drops below 3.45V
|
||||
|
||||
### Database Issues
|
||||
If you encounter database errors, you can safely delete `battery-data.db` and restart the application. It will create a new database automatically.
|
||||
|
||||
241
README_CN.md
Normal file
241
README_CN.md
Normal file
@@ -0,0 +1,241 @@
|
||||
# uConsole CM5 电池监控工具
|
||||
|
||||
为 Raspberry Pi uConsole CM5 设计的 Next.js 16 Web 应用程序,可实时监控和可视化电池指标。
|
||||
|
||||
## 功能特性
|
||||
|
||||
### 电池监控
|
||||
- **实时监控** AXP20x 电池指标(电压、电流、功率、电量百分比)
|
||||
- **交互式图表** 显示电池趋势(Recharts 可视化)
|
||||
- **历史数据存储** SQLite 数据库,支持会话管理
|
||||
- **CSV 导出** 用于数据分析
|
||||
- **会话管理** 支持自定义命名和删除
|
||||
- 直接从 Linux sysfs 读取数据 (`/sys/class/power_supply/axp20x-battery/`)
|
||||
|
||||
### uConsole 智能电源调节器 🔋⚡
|
||||
**新功能**:智能电源管理系统,防止使用 4G 模块时因电压过低导致的系统死机。
|
||||
|
||||
**问题**:4G 调制解调器需要最低 3.45V 才能可靠运行。当电池电压降至此阈值以下时,调制解调器可能会导致整个系统死机,需要物理拔出电池才能重启。
|
||||
|
||||
**解决方案**:统一的事件驱动电源调节系统:
|
||||
- **监控 AC 电源和 4G 调制解调器状态** 通过 udev 事件
|
||||
- **动态调整 CPU 频率** 基于电源和 4G 状态
|
||||
- **电池电压临界告警** (< 3.45V) 通过桌面通知、音频提示和 LED 闪烁
|
||||
- **处理边缘情况** 如服务启动时 AC 已连接
|
||||
|
||||
**电源模式:**
|
||||
| 条件 | CPU 频率 | 调节器 | 电压监控 |
|
||||
|------|---------|--------|---------|
|
||||
| AC 已连接 | 2.4GHz | ondemand | 关闭 |
|
||||
| 电池 + 4G | 1.8GHz | powersave | 开启 (< 3.45V 告警) |
|
||||
| 仅电池 | 2.0GHz | ondemand | 关闭 |
|
||||
|
||||
📖 **[阅读完整故事](STORY.md)** | **[工具指南](TOOL-GUIDE_CN.md)** | **[English](README.md)**
|
||||
|
||||
**快速安装:**
|
||||
```bash
|
||||
cd scripts
|
||||
sudo ./install-uconsole-power-regulator.sh install
|
||||
```
|
||||
|
||||
**从旧版 4G 电源管理器升级:**
|
||||
```bash
|
||||
cd scripts
|
||||
sudo ./install-uconsole-power-regulator.sh upgrade
|
||||
```
|
||||
|
||||
**卸载:**
|
||||
```bash
|
||||
cd scripts
|
||||
sudo ./install-uconsole-power-regulator.sh uninstall
|
||||
```
|
||||
|
||||
## 硬件要求
|
||||
|
||||
- **Raspberry Pi CM5**(或 CM4)在 uConsole 中
|
||||
- **AXP228 电源管理芯片**(uConsole 标配)
|
||||
- **18650 电池** (2 节并联配置)
|
||||
- 可选:**4G 扩展模块**
|
||||
|
||||
## 技术栈
|
||||
|
||||
- **框架**:Next.js 16(App Router)
|
||||
- **语言**:TypeScript
|
||||
- **UI**:React 19、shadcn/ui 组件、Tailwind CSS 4
|
||||
- **图表**:Recharts
|
||||
- **数据库**:SQLite(better-sqlite3)
|
||||
- **硬件接口**:通过 Node.js fs 访问 Linux sysfs
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 安装
|
||||
|
||||
```bash
|
||||
# 安装依赖
|
||||
npm install
|
||||
|
||||
# 运行开发服务器
|
||||
npm run dev
|
||||
```
|
||||
|
||||
打开 [http://localhost:3000](http://localhost:3000) 查看电池监控界面。
|
||||
|
||||
### 生产构建
|
||||
|
||||
```bash
|
||||
# 生产构建
|
||||
npm run build
|
||||
|
||||
# 运行生产服务器
|
||||
npm start
|
||||
```
|
||||
|
||||
### 数据库
|
||||
|
||||
应用程序会在项目根目录自动创建 `battery-data.db` SQLite 数据库。它存储:
|
||||
- 带时间戳的电池读数
|
||||
- 监控会话及元数据
|
||||
- 用于分析的历史数据
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 监控和记录
|
||||
|
||||
电池监控工具将**监控**(实时显示)和**记录**(保存到数据库)分离:
|
||||
|
||||
**实时监控:**
|
||||
1. 点击**"开始监控"**开始实时数据显示
|
||||
2. 电池数据每 2 秒更新一次
|
||||
3. 图表显示实时数据(内存中最后 100 个读数)
|
||||
4. 仅监控时数据**不会**保存到数据库
|
||||
|
||||
**记录会话:**
|
||||
1. 监控激活时,选择记录起始点:
|
||||
- **"从现在开始记录"** - 从此刻开始保存
|
||||
- **"从监控开始记录"** - 保存自监控开始以来的所有缓冲数据
|
||||
2. 点击**"开始记录"**将数据保存到数据库
|
||||
3. 点击**"停止记录"**结束会话(监控继续)
|
||||
4. 点击**"停止监控"**停止所有操作
|
||||
|
||||
**为什么分离?** 这让您可以在决定记录之前观察电池行为,避免不必要的数据库写入。
|
||||
|
||||
### 导出数据
|
||||
|
||||
**按会话导出:**
|
||||
- "记录会话"卡片中的每个会话都有下载按钮
|
||||
- 导出该特定会话的所有读数为 CSV
|
||||
|
||||
**自定义时间范围导出:**
|
||||
1. 在"导出自定义时间范围"卡片中选择开始和结束日期/时间
|
||||
2. 点击**"加载数据"**在图表中预览数据
|
||||
3. 点击**"导出 CSV"**直接下载而不先加载
|
||||
4. 文件名自动包含日期范围
|
||||
|
||||
### 查看历史数据
|
||||
|
||||
1. 在"记录会话"中点击任何会话名称查看其数据
|
||||
2. 或使用"导出自定义时间范围"→"加载数据"查看任意范围
|
||||
3. 图表显示历史趋势
|
||||
4. 点击**"返回实时视图"**返回实时监控
|
||||
|
||||
### 会话管理
|
||||
|
||||
1. 在**"记录会话"**卡片中查看所有会话
|
||||
2. 点击会话名称查看其数据
|
||||
3. 点击编辑图标重命名会话
|
||||
4. 点击下载图标导出会话数据
|
||||
5. 点击删除图标删除会话(需确认)
|
||||
|
||||
## API 端点
|
||||
|
||||
- `GET /api/battery` - 当前电池数据
|
||||
- 添加 `?save=true` 将读数保存到数据库
|
||||
- `GET /api/battery/history?start=<ISO>&end=<ISO>` - 按时间范围的历史数据
|
||||
- `GET /api/battery/sessions` - 列出所有监控会话
|
||||
- `GET /api/battery/sessions/:id` - 获取特定会话的读数
|
||||
- `PATCH /api/battery/sessions/:id` - 更新会话名称
|
||||
- `DELETE /api/battery/sessions/:id` - 删除会话及读数
|
||||
|
||||
## 开发命令
|
||||
|
||||
```bash
|
||||
npm run dev # 开发服务器(热重载)
|
||||
npm run build # 生产构建
|
||||
npm start # 生产服务器
|
||||
npm run lint # 运行 ESLint
|
||||
```
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
battery-monitor/
|
||||
├── src/
|
||||
│ ├── app/ # Next.js App Router
|
||||
│ │ ├── api/battery/ # API 路由
|
||||
│ │ ├── layout.tsx # 根布局
|
||||
│ │ └── page.tsx # 主页
|
||||
│ ├── components/
|
||||
│ │ ├── BatteryMonitor.tsx # 主监控组件
|
||||
│ │ └── ui/ # shadcn/ui 组件
|
||||
│ └── lib/
|
||||
│ ├── db.ts # SQLite 数据库工具
|
||||
│ └── utils.ts # 辅助函数
|
||||
├── scripts/ # uConsole 智能电源调节器
|
||||
│ ├── uconsole-power-regulator.sh # 主电源调节器
|
||||
│ ├── uconsole-power-daemon.sh # 后台监控守护进程
|
||||
│ ├── voltage-monitor.sh # 电压监控脚本
|
||||
│ ├── voltage-alert-notify.sh # 多方式告警
|
||||
│ ├── voltage-monitor-control.sh # 监控控制
|
||||
│ ├── install-uconsole-power-regulator.sh
|
||||
│ └── 99-uconsole-power-regulator.rules
|
||||
├── STORY.md # 开发故事和电压发现
|
||||
├── TOOL-GUIDE_CN.md # 完整用户指南(中文)
|
||||
└── public/ # 静态资源
|
||||
```
|
||||
|
||||
## 配置
|
||||
|
||||
### 路径别名
|
||||
项目使用 `@/*` 引用 `src/*`:
|
||||
```typescript
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { cn } from '@/lib/utils';
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
- 启用严格模式
|
||||
- 路径别名 `@/*` 映射到 `./src/*`
|
||||
- 模块解析:`bundler`
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 电池数据不可用
|
||||
应用程序需要 AXP20x 硬件。在没有此硬件的系统上,API 将返回 500 错误。这在非 uConsole 系统上是预期行为。
|
||||
|
||||
### 4G 模块导致系统死机
|
||||
如果您的 uConsole 在使用电池供电的 4G 模块时死机:
|
||||
1. 安装 uConsole 智能电源调节器(见上面的安装部分)
|
||||
2. 使用电池监控工具检查 4G 使用期间的电压水平
|
||||
3. 考虑升级到电压保持性更好的电池(参见 [TOOL-GUIDE_CN.md](TOOL-GUIDE_CN.md) 了解电池推荐)
|
||||
4. 调节器将在电压降至 3.45V 以下时提醒您
|
||||
|
||||
### 数据库问题
|
||||
如果遇到数据库错误,可以安全地删除 `battery-data.db` 并重启应用程序。它会自动创建新数据库。
|
||||
|
||||
## 贡献
|
||||
|
||||
本项目专为 uConsole CM5 硬件设计。欢迎贡献,特别是:
|
||||
- 性能优化
|
||||
- 额外的电池指标
|
||||
- UI/UX 改进
|
||||
- 电源管理增强
|
||||
|
||||
## 许可证
|
||||
|
||||
MIT
|
||||
|
||||
## 致谢
|
||||
|
||||
- 为 [ClockworkPi uConsole](https://www.clockworkpi.com/uconsole) 构建
|
||||
- UI 组件来自 [shadcn/ui](https://ui.shadcn.com/)
|
||||
- 图表由 [Recharts](https://recharts.org/) 提供
|
||||
100
TOOL-GUIDE.md
100
TOOL-GUIDE.md
@@ -236,76 +236,102 @@ Usable Percentage = (Usable Capacity / Total Capacity) × 100%
|
||||
|
||||
---
|
||||
|
||||
## 4G Power Manager
|
||||
## uConsole Smart Power Regulator
|
||||
|
||||
### What It Does
|
||||
|
||||
Automatically reduces CPU frequency when the 4G module is active to prevent voltage sag and system hangs.
|
||||
Intelligently manages CPU performance and monitors battery voltage based on power source and 4G module status to prevent system hangs caused by voltage drops below 3.45V.
|
||||
|
||||
### How It Works
|
||||
|
||||
1. **Detection**: Monitors 4G modem state using:
|
||||
- `wwan0` network interface status
|
||||
- ModemManager modem state
|
||||
- USB device presence
|
||||
The unified system combines three monitoring mechanisms:
|
||||
|
||||
2. **Action**: When 4G is active:
|
||||
- Switch to `powersave` governor
|
||||
- Limit max CPU frequency to 1.8GHz
|
||||
- Reduces current draw by 20-30%
|
||||
- Keeps voltage above 3.45V threshold
|
||||
1. **Event-Driven Detection** (udev events):
|
||||
- AC power connect/disconnect events
|
||||
- 4G modem USB device changes
|
||||
- Network interface (wwan0) state changes
|
||||
- Modem serial port changes
|
||||
|
||||
3. **Restore**: When 4G is inactive:
|
||||
- Switch to `ondemand` governor
|
||||
- Restore max frequency to 2.4GHz
|
||||
- Full performance available
|
||||
2. **Background Daemon** (5-second polling):
|
||||
- Monitors 4G modem state continuously
|
||||
- Monitors AC power status
|
||||
- Triggers regulator only when state changes
|
||||
- Handles edge cases (e.g., service starts with AC connected)
|
||||
|
||||
3. **Voltage Monitoring** (when Battery + 4G active):
|
||||
- Checks voltage every 5 seconds
|
||||
- Alerts when voltage < 3.45V
|
||||
- Multiple alert methods: desktop notification, audio, log, LED blink
|
||||
- Rate-limited to every 30 seconds
|
||||
|
||||
### Power Modes
|
||||
|
||||
| Condition | CPU Governor | Max Frequency | Voltage Monitoring |
|
||||
|-----------|-------------|---------------|-------------------|
|
||||
| **AC Connected** | ondemand | 2.4GHz | Off |
|
||||
| **Battery + 4G** | powersave | 1.8GHz | On (< 3.45V alerts) |
|
||||
| **Battery Only** | ondemand | 2.0GHz | Off |
|
||||
|
||||
### Installation
|
||||
|
||||
**Fresh Install:**
|
||||
```bash
|
||||
cd scripts
|
||||
sudo ./install-4g-power-manager.sh
|
||||
sudo ./install-uconsole-power-regulator.sh install
|
||||
```
|
||||
|
||||
**Upgrade from old 4G Power Manager:**
|
||||
```bash
|
||||
cd scripts
|
||||
sudo ./install-uconsole-power-regulator.sh upgrade
|
||||
```
|
||||
|
||||
**Uninstall:**
|
||||
```bash
|
||||
cd scripts
|
||||
sudo ./install-uconsole-power-regulator.sh uninstall
|
||||
```
|
||||
|
||||
**What it installs:**
|
||||
- `/usr/local/bin/4g-power-manager.sh` - Main detection script
|
||||
- `/usr/local/bin/4g-power-monitor-daemon.sh` - Background daemon
|
||||
- `/etc/udev/rules.d/99-4g-power-manager.rules` - udev triggers
|
||||
- `/etc/systemd/system/4g-power-monitor.service` - Systemd service
|
||||
- `/var/log/4g-power-manager.log` - Log file
|
||||
- `uconsole-power-regulator.sh` - Main power regulation orchestrator
|
||||
- `uconsole-power-daemon.sh` - Background state monitoring daemon
|
||||
- `voltage-monitor.sh` - Voltage monitoring script (runs when Battery + 4G)
|
||||
- `voltage-alert-notify.sh` - Multi-method alert system
|
||||
- `voltage-monitor-control.sh` - Start/stop voltage monitor
|
||||
- `/etc/udev/rules.d/99-uconsole-power-regulator.rules` - udev event triggers
|
||||
- `/etc/systemd/system/uconsole-power-regulator.service` - Systemd service
|
||||
- `/var/log/uconsole-power-regulator.log` - Unified log file
|
||||
|
||||
### Verification
|
||||
|
||||
Check if it's running:
|
||||
Check if service is running:
|
||||
```bash
|
||||
sudo systemctl status 4g-power-monitor
|
||||
sudo systemctl status uconsole-power-regulator
|
||||
```
|
||||
|
||||
View recent logs:
|
||||
```bash
|
||||
sudo tail -f /var/log/4g-power-manager.log
|
||||
sudo tail -f /var/log/uconsole-power-regulator.log
|
||||
```
|
||||
|
||||
Test manually:
|
||||
Check voltage monitor status:
|
||||
```bash
|
||||
sudo /usr/local/bin/4g-power-manager.sh
|
||||
```
|
||||
|
||||
### Uninstallation
|
||||
|
||||
```bash
|
||||
cd scripts
|
||||
sudo ./install-4g-power-manager.sh uninstall
|
||||
sudo /usr/local/bin/voltage-monitor-control.sh status
|
||||
```
|
||||
|
||||
### Tuning
|
||||
|
||||
Edit `/usr/local/bin/4g-power-manager.sh` to customize:
|
||||
Edit `/home/pi/battery-monitor/scripts/uconsole-power-regulator.sh` to customize power modes:
|
||||
|
||||
```bash
|
||||
# Power-saving configuration
|
||||
MAX_FREQ_POWERSAVE="1800000" # Try 1500000 for more power saving
|
||||
POWERSAVE_GOVERNOR="powersave" # Or "conservative"
|
||||
# Configuration options
|
||||
AC_GOVERNOR="ondemand" # Governor when AC connected
|
||||
BATTERY_GOVERNOR="ondemand" # Governor on battery without 4G
|
||||
POWERSAVE_GOVERNOR="powersave" # Governor on battery with 4G
|
||||
|
||||
MAX_FREQ_AC="2400000" # 2.4GHz - AC power, full performance
|
||||
MAX_FREQ_BATTERY="2000000" # 2.0GHz - battery only, balanced
|
||||
MAX_FREQ_POWERSAVE="1800000" # 1.8GHz - battery + 4G (try 1500000 for more savings)
|
||||
|
||||
# Performance configuration
|
||||
MAX_FREQ_PERFORMANCE="2400000" # Full CM5 speed
|
||||
|
||||
@@ -82,6 +82,17 @@ apply_cpu_settings() {
|
||||
done
|
||||
}
|
||||
|
||||
# Check if AC power is connected
|
||||
check_ac_connected() {
|
||||
if [ -f /sys/class/power_supply/axp22x-ac/online ]; then
|
||||
local ac_online=$(cat /sys/class/power_supply/axp22x-ac/online 2>/dev/null)
|
||||
if [ "$ac_online" = "1" ]; then
|
||||
return 0 # AC is connected
|
||||
fi
|
||||
fi
|
||||
return 1 # AC is not connected (on battery)
|
||||
}
|
||||
|
||||
# Main logic
|
||||
main() {
|
||||
log "=== 4G Power Manager triggered ==="
|
||||
@@ -92,6 +103,17 @@ main() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if AC power is connected
|
||||
if check_ac_connected; then
|
||||
log "AC power connected - Skipping power management (not needed on AC power)"
|
||||
# Restore normal CPU settings when on AC
|
||||
apply_cpu_settings "$NORMAL_GOVERNOR" "$MAX_FREQ_NORMAL"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Only apply power-saving if on battery power
|
||||
log "Running on battery power - Checking 4G modem state"
|
||||
|
||||
# Determine modem state
|
||||
if check_modem_active; then
|
||||
log "4G modem is ACTIVE - Applying power-saving mode"
|
||||
|
||||
37
scripts/99-uconsole-power-regulator.rules
Normal file
37
scripts/99-uconsole-power-regulator.rules
Normal file
@@ -0,0 +1,37 @@
|
||||
# udev rules for uConsole Smart Power Regulator
|
||||
#
|
||||
# This rule set triggers intelligent power management based on:
|
||||
# 1. 4G modem state changes (USB device, network interface, modem control)
|
||||
# 2. AC power state changes (power_supply subsystem)
|
||||
#
|
||||
# The power regulator automatically:
|
||||
# • Reduces CPU frequency when on battery with 4G active (prevents system hangs)
|
||||
# • Starts voltage monitoring when needed (alerts if voltage < 3.45V)
|
||||
# • Restores full performance when AC connected or 4G inactive
|
||||
# • Handles edge cases (AC already connected at boot, etc.)
|
||||
|
||||
# ============================================================================
|
||||
# AC Power State Changes
|
||||
# ============================================================================
|
||||
|
||||
# Trigger on AC adapter connect/disconnect events
|
||||
SUBSYSTEM=="power_supply", KERNEL=="axp22x-ac", ACTION=="change", RUN+="/home/pi/battery-monitor/scripts/uconsole-power-regulator.sh"
|
||||
|
||||
# ============================================================================
|
||||
# 4G Modem State Changes
|
||||
# ============================================================================
|
||||
|
||||
# Trigger on Qualcomm/SimTech 4G modem USB device changes
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="1e0e", ATTR{idProduct}=="9001", ACTION=="add", RUN+="/home/pi/battery-monitor/scripts/uconsole-power-regulator.sh"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="1e0e", ATTR{idProduct}=="9001", ACTION=="remove", RUN+="/home/pi/battery-monitor/scripts/uconsole-power-regulator.sh"
|
||||
|
||||
# Trigger on wwan0 network interface changes (up/down)
|
||||
SUBSYSTEM=="net", KERNEL=="wwan0", ACTION=="add", RUN+="/home/pi/battery-monitor/scripts/uconsole-power-regulator.sh"
|
||||
SUBSYSTEM=="net", KERNEL=="wwan0", ACTION=="remove", RUN+="/home/pi/battery-monitor/scripts/uconsole-power-regulator.sh"
|
||||
|
||||
# Trigger on modem manager state changes via cdc-wdm0 (modem control device)
|
||||
SUBSYSTEM=="usb", KERNEL=="cdc-wdm0", ACTION=="change", RUN+="/home/pi/battery-monitor/scripts/uconsole-power-regulator.sh"
|
||||
|
||||
# Trigger on ttyUSB device changes (modem serial ports)
|
||||
SUBSYSTEM=="tty", KERNEL=="ttyUSB[0-4]", ACTION=="add", RUN+="/home/pi/battery-monitor/scripts/uconsole-power-regulator.sh"
|
||||
SUBSYSTEM=="tty", KERNEL=="ttyUSB[0-4]", ACTION=="remove", RUN+="/home/pi/battery-monitor/scripts/uconsole-power-regulator.sh"
|
||||
343
scripts/install-uconsole-power-regulator.sh
Executable file
343
scripts/install-uconsole-power-regulator.sh
Executable file
@@ -0,0 +1,343 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Installation/Uninstallation script for uConsole Smart Power Regulator
|
||||
# Usage:
|
||||
# sudo ./install-uconsole-power-regulator.sh [install|uninstall|upgrade]
|
||||
#
|
||||
# Examples:
|
||||
# sudo ./install-uconsole-power-regulator.sh install # Fresh install
|
||||
# sudo ./install-uconsole-power-regulator.sh upgrade # Upgrade from 4G Power Manager
|
||||
# sudo ./install-uconsole-power-regulator.sh uninstall # Complete removal
|
||||
|
||||
set -e # Exit on error
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ACTION=${1:-"install"}
|
||||
|
||||
# Check if running as root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "ERROR: Please run as root (use sudo)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to install components
|
||||
install_components() {
|
||||
echo "=========================================="
|
||||
echo "uConsole Smart Power Regulator"
|
||||
echo "Installation"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# Install dependencies
|
||||
echo "Checking and installing dependencies..."
|
||||
PACKAGES_TO_INSTALL=""
|
||||
|
||||
# bc - for power/voltage calculations
|
||||
if ! command -v bc &> /dev/null; then
|
||||
PACKAGES_TO_INSTALL="$PACKAGES_TO_INSTALL bc"
|
||||
fi
|
||||
|
||||
# libnotify-bin - for desktop notifications (notify-send)
|
||||
if ! command -v notify-send &> /dev/null; then
|
||||
PACKAGES_TO_INSTALL="$PACKAGES_TO_INSTALL libnotify-bin"
|
||||
fi
|
||||
|
||||
# pulseaudio-utils - for audio alerts (paplay)
|
||||
if ! command -v paplay &> /dev/null; then
|
||||
PACKAGES_TO_INSTALL="$PACKAGES_TO_INSTALL pulseaudio-utils"
|
||||
fi
|
||||
|
||||
if [ -n "$PACKAGES_TO_INSTALL" ]; then
|
||||
echo "Installing: $PACKAGES_TO_INSTALL"
|
||||
apt-get update && apt-get install -y $PACKAGES_TO_INSTALL
|
||||
else
|
||||
echo "✓ All dependencies already installed"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Ensure main power regulator script is executable
|
||||
echo "Checking power regulator script..."
|
||||
if [ ! -f "$SCRIPT_DIR/uconsole-power-regulator.sh" ]; then
|
||||
echo "ERROR: uconsole-power-regulator.sh not found in $SCRIPT_DIR"
|
||||
exit 1
|
||||
fi
|
||||
chmod +x "$SCRIPT_DIR/uconsole-power-regulator.sh"
|
||||
chmod +x "$SCRIPT_DIR/uconsole-power-daemon.sh"
|
||||
echo "✓ Power regulator scripts are executable"
|
||||
echo ""
|
||||
|
||||
# Install voltage monitoring scripts
|
||||
echo "Installing voltage monitoring scripts..."
|
||||
cp "$SCRIPT_DIR/voltage-monitor.sh" /usr/local/bin/
|
||||
cp "$SCRIPT_DIR/voltage-alert-notify.sh" /usr/local/bin/
|
||||
cp "$SCRIPT_DIR/voltage-monitor-control.sh" /usr/local/bin/
|
||||
chmod +x /usr/local/bin/voltage-monitor.sh
|
||||
chmod +x /usr/local/bin/voltage-alert-notify.sh
|
||||
chmod +x /usr/local/bin/voltage-monitor-control.sh
|
||||
echo "✓ Installed voltage monitoring scripts to /usr/local/bin/"
|
||||
echo ""
|
||||
|
||||
# Install udev rules
|
||||
echo "Installing udev rules..."
|
||||
cp "$SCRIPT_DIR/99-uconsole-power-regulator.rules" /etc/udev/rules.d/
|
||||
echo "✓ Copied udev rules to /etc/udev/rules.d/"
|
||||
|
||||
# Reload udev rules
|
||||
udevadm control --reload-rules
|
||||
udevadm trigger
|
||||
echo "✓ Reloaded udev rules"
|
||||
echo ""
|
||||
|
||||
# Install systemd service
|
||||
echo "Installing systemd service..."
|
||||
cp "$SCRIPT_DIR/uconsole-power-regulator.service" /etc/systemd/system/
|
||||
echo "✓ Copied service file to /etc/systemd/system/"
|
||||
|
||||
# Reload systemd
|
||||
systemctl daemon-reload
|
||||
echo "✓ Reloaded systemd"
|
||||
|
||||
# Enable and start service
|
||||
systemctl enable uconsole-power-regulator.service
|
||||
systemctl start uconsole-power-regulator.service
|
||||
echo "✓ Enabled and started uconsole-power-regulator service"
|
||||
echo ""
|
||||
|
||||
# Create log file with proper permissions
|
||||
touch /var/log/uconsole-power-regulator.log
|
||||
chmod 644 /var/log/uconsole-power-regulator.log
|
||||
echo "✓ Created log file at /var/log/uconsole-power-regulator.log"
|
||||
echo ""
|
||||
|
||||
echo "=========================================="
|
||||
echo "Installation Complete!"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
echo "The uConsole Smart Power Regulator is now active and will:"
|
||||
echo ""
|
||||
echo "Power Management:"
|
||||
echo " • AC Connected → Full performance (2.4GHz)"
|
||||
echo " • Battery + 4G → Power-saving mode (1.8GHz)"
|
||||
echo " • Battery only → Balanced performance (2.0GHz)"
|
||||
echo ""
|
||||
echo "Voltage Monitoring:"
|
||||
echo " • Active when: Battery + 4G enabled"
|
||||
echo " • Alert threshold: < 3.45V"
|
||||
echo " • Alert methods: Desktop popup, audio, log, LED"
|
||||
echo " • Alert frequency: Every 30 seconds when low"
|
||||
echo ""
|
||||
echo "Useful Commands:"
|
||||
echo " • View logs: tail -f /var/log/uconsole-power-regulator.log"
|
||||
echo " • Check service: systemctl status uconsole-power-regulator"
|
||||
echo " • Check voltage monitor: sudo /usr/local/bin/voltage-monitor-control.sh status"
|
||||
echo " • Stop service: sudo systemctl stop uconsole-power-regulator"
|
||||
echo " • Disable service: sudo systemctl disable uconsole-power-regulator"
|
||||
echo " • Uninstall: sudo $0 uninstall"
|
||||
echo " • Test manually: sudo /home/pi/battery-monitor/scripts/uconsole-power-regulator.sh"
|
||||
echo ""
|
||||
echo "Current System State:"
|
||||
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null | sed 's/^/ Governor: /' || echo " Governor: N/A"
|
||||
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq 2>/dev/null | sed 's/^/ Max freq: /' || echo " Max freq: N/A"
|
||||
|
||||
if [ -f /sys/class/power_supply/axp22x-ac/online ]; then
|
||||
AC_STATUS=$(cat /sys/class/power_supply/axp22x-ac/online)
|
||||
if [ "$AC_STATUS" = "1" ]; then
|
||||
echo " AC Power: CONNECTED"
|
||||
else
|
||||
echo " AC Power: DISCONNECTED (on battery)"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Function to upgrade from old 4G Power Manager
|
||||
upgrade_from_old() {
|
||||
echo "=========================================="
|
||||
echo "Upgrading from 4G Power Manager"
|
||||
echo "to uConsole Smart Power Regulator"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# Stop and disable old service
|
||||
if systemctl is-active --quiet 4g-power-monitor.service 2>/dev/null; then
|
||||
echo "Stopping old 4g-power-monitor service..."
|
||||
systemctl stop 4g-power-monitor.service
|
||||
echo "✓ Stopped old service"
|
||||
fi
|
||||
|
||||
if systemctl is-enabled --quiet 4g-power-monitor.service 2>/dev/null; then
|
||||
echo "Disabling old 4g-power-monitor service..."
|
||||
systemctl disable 4g-power-monitor.service
|
||||
echo "✓ Disabled old service"
|
||||
fi
|
||||
|
||||
if [ -f /etc/systemd/system/4g-power-monitor.service ]; then
|
||||
echo "Removing old service file..."
|
||||
rm /etc/systemd/system/4g-power-monitor.service
|
||||
echo "✓ Removed old service file"
|
||||
fi
|
||||
|
||||
# Remove old udev rules
|
||||
if [ -f /etc/udev/rules.d/99-4g-power-manager.rules ]; then
|
||||
echo "Removing old udev rules..."
|
||||
rm /etc/udev/rules.d/99-4g-power-manager.rules
|
||||
echo "✓ Removed old udev rules"
|
||||
fi
|
||||
|
||||
# Stop voltage monitor if running
|
||||
if [ -x /usr/local/bin/voltage-monitor-control.sh ]; then
|
||||
/usr/local/bin/voltage-monitor-control.sh stop 2>/dev/null || true
|
||||
echo "✓ Stopped voltage monitor"
|
||||
fi
|
||||
|
||||
# Migrate old log file
|
||||
if [ -f /var/log/4g-power-manager.log ]; then
|
||||
echo "Migrating old log file..."
|
||||
cp /var/log/4g-power-manager.log /var/log/uconsole-power-regulator.log
|
||||
echo "========================================" >> /var/log/uconsole-power-regulator.log
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Upgraded to uConsole Smart Power Regulator" >> /var/log/uconsole-power-regulator.log
|
||||
echo "========================================" >> /var/log/uconsole-power-regulator.log
|
||||
echo "✓ Migrated log file"
|
||||
fi
|
||||
|
||||
systemctl daemon-reload
|
||||
echo "✓ Reloaded systemd"
|
||||
echo ""
|
||||
|
||||
# Now install new components
|
||||
install_components
|
||||
}
|
||||
|
||||
# Function to uninstall components
|
||||
uninstall_components() {
|
||||
echo "=========================================="
|
||||
echo "uConsole Smart Power Regulator"
|
||||
echo "Uninstallation"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# Stop and disable systemd service
|
||||
if systemctl is-active --quiet uconsole-power-regulator.service 2>/dev/null; then
|
||||
echo "Stopping uconsole-power-regulator service..."
|
||||
systemctl stop uconsole-power-regulator.service
|
||||
echo "✓ Stopped service"
|
||||
fi
|
||||
|
||||
if systemctl is-enabled --quiet uconsole-power-regulator.service 2>/dev/null; then
|
||||
echo "Disabling uconsole-power-regulator service..."
|
||||
systemctl disable uconsole-power-regulator.service
|
||||
echo "✓ Disabled service"
|
||||
fi
|
||||
|
||||
if [ -f /etc/systemd/system/uconsole-power-regulator.service ]; then
|
||||
echo "Removing service file..."
|
||||
rm /etc/systemd/system/uconsole-power-regulator.service
|
||||
echo "✓ Removed service file"
|
||||
fi
|
||||
|
||||
systemctl daemon-reload
|
||||
echo "✓ Reloaded systemd"
|
||||
echo ""
|
||||
|
||||
# Remove udev rules
|
||||
if [ -f /etc/udev/rules.d/99-uconsole-power-regulator.rules ]; then
|
||||
echo "Removing udev rules..."
|
||||
rm /etc/udev/rules.d/99-uconsole-power-regulator.rules
|
||||
echo "✓ Removed udev rules"
|
||||
|
||||
udevadm control --reload-rules
|
||||
udevadm trigger
|
||||
echo "✓ Reloaded udev rules"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Stop voltage monitor if running
|
||||
echo "Stopping voltage monitor..."
|
||||
if [ -x /usr/local/bin/voltage-monitor-control.sh ]; then
|
||||
/usr/local/bin/voltage-monitor-control.sh stop 2>/dev/null || true
|
||||
echo "✓ Stopped voltage monitor"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Remove voltage monitoring scripts
|
||||
if [ -f /usr/local/bin/voltage-monitor.sh ] || \
|
||||
[ -f /usr/local/bin/voltage-alert-notify.sh ] || \
|
||||
[ -f /usr/local/bin/voltage-monitor-control.sh ]; then
|
||||
echo "Removing voltage monitoring scripts..."
|
||||
rm -f /usr/local/bin/voltage-monitor.sh
|
||||
rm -f /usr/local/bin/voltage-alert-notify.sh
|
||||
rm -f /usr/local/bin/voltage-monitor-control.sh
|
||||
echo "✓ Removed voltage monitoring scripts"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Clean up temporary files
|
||||
echo "Cleaning up temporary files..."
|
||||
rm -f /tmp/4g-modem-state /tmp/4g-modem-last-state
|
||||
rm -f /tmp/uconsole-power-daemon-state /tmp/power-state
|
||||
rm -f /run/voltage-monitor.pid
|
||||
echo "✓ Removed temporary state files"
|
||||
echo ""
|
||||
|
||||
# Ask about log file
|
||||
read -p "Remove log file /var/log/uconsole-power-regulator.log? (y/n) " -n 1 -r
|
||||
echo ""
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
rm -f /var/log/uconsole-power-regulator.log
|
||||
echo "✓ Removed log file"
|
||||
else
|
||||
echo "• Kept log file for reference"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Restore CPU to normal settings
|
||||
echo "Restoring CPU to normal settings..."
|
||||
for cpu in /sys/devices/system/cpu/cpu[0-9]*; do
|
||||
if [ -f "$cpu/cpufreq/scaling_governor" ]; then
|
||||
echo "ondemand" > "$cpu/cpufreq/scaling_governor" 2>/dev/null || true
|
||||
fi
|
||||
if [ -f "$cpu/cpufreq/scaling_max_freq" ]; then
|
||||
echo "2400000" > "$cpu/cpufreq/scaling_max_freq" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
echo "✓ Restored CPU governor to ondemand"
|
||||
echo "✓ Restored CPU max frequency to 2.4GHz"
|
||||
echo ""
|
||||
|
||||
echo "=========================================="
|
||||
echo "Uninstallation Complete"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
echo "The uConsole Smart Power Regulator has been removed."
|
||||
echo "CPU power management restored to default settings."
|
||||
echo ""
|
||||
echo "To reinstall: sudo $0 install"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Main logic
|
||||
case "$ACTION" in
|
||||
install)
|
||||
install_components
|
||||
;;
|
||||
upgrade)
|
||||
upgrade_from_old
|
||||
;;
|
||||
uninstall)
|
||||
uninstall_components
|
||||
;;
|
||||
*)
|
||||
echo "Usage: sudo $0 [install|uninstall|upgrade]"
|
||||
echo ""
|
||||
echo "Actions:"
|
||||
echo " install - Fresh installation of uConsole Smart Power Regulator"
|
||||
echo " upgrade - Upgrade from old 4G Power Manager to new unified system"
|
||||
echo " uninstall - Remove uConsole Smart Power Regulator"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " sudo $0 install # Fresh install"
|
||||
echo " sudo $0 upgrade # Upgrade from 4G Power Manager"
|
||||
echo " sudo $0 uninstall # Complete removal"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
100
scripts/uconsole-power-daemon.sh
Executable file
100
scripts/uconsole-power-daemon.sh
Executable file
@@ -0,0 +1,100 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# uConsole Smart Power Daemon
|
||||
# Continuously monitors system power state and triggers power regulator
|
||||
#
|
||||
# This daemon runs in the background and checks system state every 5 seconds.
|
||||
# It monitors:
|
||||
# - 4G modem state (active/inactive)
|
||||
# - AC power state (connected/disconnected)
|
||||
#
|
||||
# More reliable than udev alone for detecting state changes during:
|
||||
# - Network activity (4G connecting, data transfer)
|
||||
# - Edge cases (service starts with AC already connected)
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REGULATOR_SCRIPT="$SCRIPT_DIR/uconsole-power-regulator.sh"
|
||||
CHECK_INTERVAL=5 # Check every 5 seconds
|
||||
LAST_STATE_FILE="/tmp/uconsole-power-daemon-state"
|
||||
AC_PATH="/sys/class/power_supply/axp22x-ac"
|
||||
|
||||
log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [POWER-DAEMON] $1"
|
||||
}
|
||||
|
||||
# Get current AC power state
|
||||
get_ac_state() {
|
||||
if [ -f "$AC_PATH/online" ]; then
|
||||
local ac_online=$(cat "$AC_PATH/online" 2>/dev/null)
|
||||
if [ "$ac_online" = "1" ]; then
|
||||
echo "connected"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
echo "disconnected"
|
||||
}
|
||||
|
||||
# Get current modem state
|
||||
get_modem_state() {
|
||||
# Check if wwan0 is up and has IP address
|
||||
if ip addr show wwan0 2>/dev/null | grep -q "inet "; then
|
||||
echo "active"
|
||||
return
|
||||
fi
|
||||
|
||||
# Check if wwan0 link is up
|
||||
if ip link show wwan0 2>/dev/null | grep -q "state UP"; then
|
||||
echo "active"
|
||||
return
|
||||
fi
|
||||
|
||||
# Check ModemManager state
|
||||
if command -v mmcli &> /dev/null; then
|
||||
local modem_state=$(mmcli -m 0 --output-keyvalue 2>/dev/null | grep "modem.generic.state " | cut -d: -f2 | tr -d ' ')
|
||||
if [[ "$modem_state" == "connected" ]] || [[ "$modem_state" == "registered" ]]; then
|
||||
echo "active"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "inactive"
|
||||
}
|
||||
|
||||
# Get combined system state
|
||||
get_system_state() {
|
||||
local ac=$(get_ac_state)
|
||||
local modem=$(get_modem_state)
|
||||
echo "${ac}:${modem}"
|
||||
}
|
||||
|
||||
log "uConsole Smart Power Daemon started"
|
||||
|
||||
# Initialize last state
|
||||
LAST_STATE="unknown"
|
||||
if [ -f "$LAST_STATE_FILE" ]; then
|
||||
LAST_STATE=$(cat "$LAST_STATE_FILE")
|
||||
fi
|
||||
|
||||
# On startup, always trigger regulator to handle edge case where service
|
||||
# starts with AC already connected or 4G already active
|
||||
log "Initial state check on daemon startup"
|
||||
"$REGULATOR_SCRIPT"
|
||||
CURRENT_STATE=$(get_system_state)
|
||||
echo "$CURRENT_STATE" > "$LAST_STATE_FILE"
|
||||
LAST_STATE="$CURRENT_STATE"
|
||||
log "Initial system state: $CURRENT_STATE"
|
||||
|
||||
# Main monitoring loop
|
||||
while true; do
|
||||
CURRENT_STATE=$(get_system_state)
|
||||
|
||||
# Only trigger regulator if state changed
|
||||
if [ "$CURRENT_STATE" != "$LAST_STATE" ]; then
|
||||
log "System state changed: $LAST_STATE → $CURRENT_STATE"
|
||||
"$REGULATOR_SCRIPT"
|
||||
echo "$CURRENT_STATE" > "$LAST_STATE_FILE"
|
||||
LAST_STATE="$CURRENT_STATE"
|
||||
fi
|
||||
|
||||
sleep "$CHECK_INTERVAL"
|
||||
done
|
||||
24
scripts/uconsole-power-regulator.service
Normal file
24
scripts/uconsole-power-regulator.service
Normal file
@@ -0,0 +1,24 @@
|
||||
[Unit]
|
||||
Description=uConsole Smart Power Regulator
|
||||
Documentation=https://github.com/yourusername/battery-monitor
|
||||
After=network.target ModemManager.service
|
||||
Wants=ModemManager.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/home/pi/battery-monitor/scripts/uconsole-power-daemon.sh
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
# Security hardening
|
||||
NoNewPrivileges=false
|
||||
PrivateTmp=false
|
||||
|
||||
# Resource limits
|
||||
Nice=0
|
||||
CPUSchedulingPolicy=other
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
227
scripts/uconsole-power-regulator.sh
Executable file
227
scripts/uconsole-power-regulator.sh
Executable file
@@ -0,0 +1,227 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# uConsole Smart Power Regulator
|
||||
# Intelligently manages CPU power and voltage monitoring based on system state
|
||||
#
|
||||
# This script orchestrates power management based on:
|
||||
# - AC power status (connected/disconnected)
|
||||
# - 4G modem state (active/inactive)
|
||||
#
|
||||
# Power Management Logic:
|
||||
# AC Connected: → Normal CPU settings (ondemand @ 2.4GHz), no voltage monitoring
|
||||
# AC + 4G: → Normal CPU settings (ondemand @ 2.4GHz), no voltage monitoring
|
||||
# Battery Only: → Normal CPU settings (ondemand @ 2.4GHz), no voltage monitoring
|
||||
# Battery + 4G: → Power-save mode (powersave @ 1.8GHz), voltage monitoring enabled
|
||||
#
|
||||
# Triggered by:
|
||||
# - udev events (4G modem state changes, AC power changes)
|
||||
# - systemd daemon (periodic state polling)
|
||||
# - Manual execution
|
||||
|
||||
LOGFILE="/var/log/uconsole-power-regulator.log"
|
||||
MODEM_STATE_FILE="/tmp/4g-modem-state"
|
||||
LAST_POWER_STATE_FILE="/tmp/power-state"
|
||||
|
||||
# Configuration
|
||||
AC_GOVERNOR="ondemand" # Governor when AC connected
|
||||
BATTERY_GOVERNOR="ondemand" # Governor when on battery without 4G
|
||||
POWERSAVE_GOVERNOR="powersave" # Governor when on battery with 4G active
|
||||
MAX_FREQ_AC="2400000" # Max freq (2.4GHz) - AC power, full performance
|
||||
MAX_FREQ_BATTERY="2000000" # Max freq (2.0GHz) - battery only, balanced
|
||||
MAX_FREQ_POWERSAVE="1800000" # Max freq (1.8GHz) - battery + 4G, power-saving
|
||||
|
||||
# Paths
|
||||
BATTERY_PATH="/sys/class/power_supply/axp20x-battery"
|
||||
AC_PATH="/sys/class/power_supply/axp22x-ac"
|
||||
|
||||
# Logging function
|
||||
log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [POWER-REGULATOR] $1" | tee -a "$LOGFILE"
|
||||
}
|
||||
|
||||
# Check if AC power is connected
|
||||
check_ac_connected() {
|
||||
if [ -f "$AC_PATH/online" ]; then
|
||||
local ac_online=$(cat "$AC_PATH/online" 2>/dev/null)
|
||||
if [ "$ac_online" = "1" ]; then
|
||||
return 0 # AC is connected
|
||||
fi
|
||||
fi
|
||||
return 1 # AC is not connected (on battery)
|
||||
}
|
||||
|
||||
# Check if 4G modem is active
|
||||
check_modem_active() {
|
||||
# Method 1: Check if wwan0 interface exists and is up
|
||||
if ip link show wwan0 2>/dev/null | grep -q "state UP"; then
|
||||
return 0 # Modem is active
|
||||
fi
|
||||
|
||||
# Method 2: Check if wwan0 has IP address (more reliable)
|
||||
if ip addr show wwan0 2>/dev/null | grep -q "inet "; then
|
||||
return 0 # Modem is active with IP
|
||||
fi
|
||||
|
||||
# Method 3: Check ModemManager state
|
||||
if command -v mmcli &> /dev/null; then
|
||||
local modem_state=$(mmcli -m 0 --output-keyvalue 2>/dev/null | grep "modem.generic.state " | cut -d: -f2 | tr -d ' ')
|
||||
if [[ "$modem_state" == "connected" ]] || [[ "$modem_state" == "registered" ]]; then
|
||||
return 0 # Modem is active
|
||||
fi
|
||||
fi
|
||||
|
||||
# Method 4: Check if there's active data on wwan0
|
||||
if [ -f /sys/class/net/wwan0/statistics/rx_bytes ]; then
|
||||
local rx_bytes=$(cat /sys/class/net/wwan0/statistics/rx_bytes 2>/dev/null || echo 0)
|
||||
local tx_bytes=$(cat /sys/class/net/wwan0/statistics/tx_bytes 2>/dev/null || echo 0)
|
||||
local total=$((rx_bytes + tx_bytes))
|
||||
|
||||
# Read previous state
|
||||
local prev_total=0
|
||||
if [ -f "$MODEM_STATE_FILE" ]; then
|
||||
prev_total=$(cat "$MODEM_STATE_FILE")
|
||||
fi
|
||||
|
||||
# Save current state
|
||||
echo "$total" > "$MODEM_STATE_FILE"
|
||||
|
||||
# If traffic increased significantly, modem is active
|
||||
if [ $((total - prev_total)) -gt 1000 ]; then
|
||||
return 0 # Modem is active (data transfer)
|
||||
fi
|
||||
fi
|
||||
|
||||
return 1 # Modem is inactive
|
||||
}
|
||||
|
||||
# Apply CPU power settings
|
||||
apply_cpu_settings() {
|
||||
local governor=$1
|
||||
local max_freq=$2
|
||||
local reason=$3
|
||||
|
||||
log "Applying CPU settings: $reason"
|
||||
log " Governor: $governor, Max Frequency: ${max_freq}Hz"
|
||||
|
||||
# Apply to all CPUs
|
||||
for cpu in /sys/devices/system/cpu/cpu[0-9]*; do
|
||||
if [ -f "$cpu/cpufreq/scaling_governor" ]; then
|
||||
echo "$governor" > "$cpu/cpufreq/scaling_governor" 2>/dev/null
|
||||
fi
|
||||
|
||||
if [ -f "$cpu/cpufreq/scaling_max_freq" ]; then
|
||||
echo "$max_freq" > "$cpu/cpufreq/scaling_max_freq" 2>/dev/null
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Determine and apply appropriate power state
|
||||
determine_power_state() {
|
||||
local ac_connected=$1
|
||||
local modem_active=$2
|
||||
local state=""
|
||||
|
||||
if [ "$ac_connected" = "true" ]; then
|
||||
state="AC_POWER"
|
||||
elif [ "$modem_active" = "true" ]; then
|
||||
state="BATTERY_4G"
|
||||
else
|
||||
state="BATTERY_ONLY"
|
||||
fi
|
||||
|
||||
echo "$state"
|
||||
}
|
||||
|
||||
# Apply power state configuration
|
||||
apply_power_state() {
|
||||
local state=$1
|
||||
|
||||
case "$state" in
|
||||
AC_POWER)
|
||||
log "Power State: AC CONNECTED"
|
||||
apply_cpu_settings "$AC_GOVERNOR" "$MAX_FREQ_AC" "AC power - full performance"
|
||||
# Stop voltage monitoring (not needed on AC)
|
||||
if command -v voltage-monitor-control.sh &> /dev/null; then
|
||||
/usr/local/bin/voltage-monitor-control.sh stop 2>/dev/null
|
||||
fi
|
||||
;;
|
||||
|
||||
BATTERY_4G)
|
||||
log "Power State: BATTERY + 4G ACTIVE"
|
||||
apply_cpu_settings "$POWERSAVE_GOVERNOR" "$MAX_FREQ_POWERSAVE" "Battery with 4G - power saving mode"
|
||||
# Start voltage monitoring (critical on battery with 4G)
|
||||
if command -v voltage-monitor-control.sh &> /dev/null; then
|
||||
/usr/local/bin/voltage-monitor-control.sh start 2>/dev/null
|
||||
fi
|
||||
;;
|
||||
|
||||
BATTERY_ONLY)
|
||||
log "Power State: BATTERY - 4G INACTIVE"
|
||||
apply_cpu_settings "$BATTERY_GOVERNOR" "$MAX_FREQ_BATTERY" "Battery without 4G - balanced performance"
|
||||
# Stop voltage monitoring (not needed when 4G off)
|
||||
if command -v voltage-monitor-control.sh &> /dev/null; then
|
||||
/usr/local/bin/voltage-monitor-control.sh stop 2>/dev/null
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Main logic
|
||||
main() {
|
||||
log "=========================================="
|
||||
log "uConsole Smart Power Regulator triggered"
|
||||
log "=========================================="
|
||||
|
||||
# Check if cpufreq is available
|
||||
if [ ! -f /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor ]; then
|
||||
log "ERROR: CPU frequency scaling not available"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Determine current system state
|
||||
local ac_status="false"
|
||||
local modem_status="false"
|
||||
|
||||
if check_ac_connected; then
|
||||
ac_status="true"
|
||||
log "AC Power: CONNECTED"
|
||||
else
|
||||
log "AC Power: DISCONNECTED (on battery)"
|
||||
fi
|
||||
|
||||
if check_modem_active; then
|
||||
modem_status="true"
|
||||
log "4G Modem: ACTIVE"
|
||||
else
|
||||
log "4G Modem: INACTIVE"
|
||||
fi
|
||||
|
||||
# Determine required power state
|
||||
local new_state=$(determine_power_state "$ac_status" "$modem_status")
|
||||
|
||||
# Check if state changed
|
||||
local last_state=""
|
||||
if [ -f "$LAST_POWER_STATE_FILE" ]; then
|
||||
last_state=$(cat "$LAST_POWER_STATE_FILE")
|
||||
fi
|
||||
|
||||
if [ "$new_state" != "$last_state" ]; then
|
||||
log "Power state transition: ${last_state:-UNKNOWN} → $new_state"
|
||||
apply_power_state "$new_state"
|
||||
echo "$new_state" > "$LAST_POWER_STATE_FILE"
|
||||
else
|
||||
log "Power state unchanged: $new_state (no action needed)"
|
||||
fi
|
||||
|
||||
# Display current power consumption
|
||||
if [ -f "$BATTERY_PATH/power_now" ]; then
|
||||
local power_now=$(cat "$BATTERY_PATH/power_now" 2>/dev/null)
|
||||
local power_watts=$(echo "scale=2; $power_now / 1000000" | bc 2>/dev/null || echo "N/A")
|
||||
log "Current battery power: ${power_watts}W"
|
||||
fi
|
||||
|
||||
log "=========================================="
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
PID_FILE="/run/voltage-monitor.pid"
|
||||
MONITOR_SCRIPT="/usr/local/bin/voltage-monitor.sh"
|
||||
AC_PATH="/sys/class/power_supply/axp22x-ac"
|
||||
LOGFILE="/var/log/4g-power-manager.log"
|
||||
|
||||
# Logging function
|
||||
@@ -20,8 +21,25 @@ log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [VOLTAGE-CONTROL] $1" >> "$LOGFILE"
|
||||
}
|
||||
|
||||
# Check if AC power is connected
|
||||
check_ac_connected() {
|
||||
if [ -f "$AC_PATH/online" ]; then
|
||||
local ac_online=$(cat "$AC_PATH/online" 2>/dev/null)
|
||||
if [ "$ac_online" = "1" ]; then
|
||||
return 0 # AC is connected
|
||||
fi
|
||||
fi
|
||||
return 1 # AC is not connected (on battery)
|
||||
}
|
||||
|
||||
# Start voltage monitor
|
||||
start_monitor() {
|
||||
# Check if AC power is connected
|
||||
if check_ac_connected; then
|
||||
log "AC power connected - Skipping voltage monitor (not needed on AC power)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Check if already running
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
PID=$(cat "$PID_FILE")
|
||||
|
||||
@@ -15,6 +15,7 @@ VOLTAGE_THRESHOLD="3.45" # Critical voltage threshold in volts
|
||||
CHECK_INTERVAL=5 # Normal check interval in seconds
|
||||
ALERT_INTERVAL=30 # Minimum time between alerts in seconds
|
||||
BATTERY_PATH="/sys/class/power_supply/axp20x-battery"
|
||||
AC_PATH="/sys/class/power_supply/axp22x-ac"
|
||||
LOGFILE="/var/log/4g-power-manager.log"
|
||||
|
||||
# State tracking
|
||||
@@ -25,6 +26,17 @@ log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [VOLTAGE-MONITOR] $1" >> "$LOGFILE"
|
||||
}
|
||||
|
||||
# Check if AC power is connected
|
||||
check_ac_connected() {
|
||||
if [ -f "$AC_PATH/online" ]; then
|
||||
local ac_online=$(cat "$AC_PATH/online" 2>/dev/null)
|
||||
if [ "$ac_online" = "1" ]; then
|
||||
return 0 # AC is connected
|
||||
fi
|
||||
fi
|
||||
return 1 # AC is not connected (on battery)
|
||||
}
|
||||
|
||||
# Cleanup function
|
||||
cleanup() {
|
||||
log "Voltage monitor stopped"
|
||||
@@ -40,6 +52,12 @@ log "Voltage monitor started (threshold: ${VOLTAGE_THRESHOLD}V, check interval:
|
||||
|
||||
# Main monitoring loop
|
||||
while true; do
|
||||
# Check if AC power is connected - if so, exit monitoring
|
||||
if check_ac_connected; then
|
||||
log "AC power connected - Exiting voltage monitor (not needed on AC power)"
|
||||
cleanup
|
||||
fi
|
||||
|
||||
# Read current voltage
|
||||
if [ -f "$BATTERY_PATH/voltage_now" ]; then
|
||||
VOLTAGE_UV=$(cat "$BATTERY_PATH/voltage_now" 2>/dev/null)
|
||||
|
||||
Reference in New Issue
Block a user