掌控Apple Silicon MacBook电池健康的神器

batt - Apple Silicon MacBook 电池充电控制器

batt 是一款专为 Apple Silicon MacBook 设计的电池充电控制工具,能够有效延长电池寿命。通过智能限制充电阈值,防止电池长期处于满电状态,从而减缓电池老化过程。

功能特性

  • 智能充电限制:设置上下充电阈值(10%-100%),像 ThinkPad 一样保护电池健康
  • MagSafe LED 控制:根据充电状态自动控制 MagSafe LED 指示灯颜色
  • 睡眠保护机制:防止系统睡眠时电池过充,支持空闲睡眠和系统睡眠防护
  • 电源适配器控制:可手动启用或禁用电源适配器供电
  • 实时状态监控:提供详细的电池状态和电源信息监控
  • 图形化界面:提供直观的 GUI 界面,方便用户操作

安装指南

系统要求

  • macOS 11.0 或更高版本
  • Apple Silicon MacBook
  • 需要 root 权限进行系统级安装

快速安装

bash 复制代码
# 使用自动安装脚本
curl -fsSL https://github.com/charlie0129/batt/raw/main/install.sh | bash

手动安装

  1. GitHub Releases 下载最新版本
  2. 解压到系统目录:
bash 复制代码
sudo tar -xzf batt-*.tar.gz -C /usr/local/bin
  1. 安装守护进程:
bash 复制代码
sudo batt install --allow-non-root-access

Homebrew 安装

bash 复制代码
brew install batt
sudo brew services start batt

使用说明

基础命令

设置充电上限为 80%:

bash 复制代码
batt limit 80

禁用电池充电限制:

bash 复制代码
batt disable

查看当前状态:

bash 复制代码
batt status

高级功能

启用 MagSafe LED 控制:

bash 复制代码
batt magsafe-led enable

防止空闲睡眠:

bash 复制代码
batt prevent-idle-sleep enable

禁用充电前睡眠保护:

bash 复制代码
batt disable-charging-pre-sleep enable

电源适配器控制

启用电源适配器:

bash 复制代码
batt adapter enable

禁用电源适配器:

bash 复制代码
batt adapter disable

核心代码

充电限制核心逻辑

go 复制代码
// pkg/daemon/loop.go
func maintainLoopInner(force bool) {
    maintainLoopInnerLock.Lock()
    defer maintainLoopInnerLock.Unlock()

    charge, err := smcConn.GetBatteryCharge()
    if err != nil {
        logrus.Errorf("failed to get battery charge: %v", err)
        return
    }

    pluggedIn, err := smcConn.IsPluggedIn()
    if err != nil {
        logrus.Errorf("failed to check if plugged in: %v", err)
        return
    }

    // 根据充电状态和配置决定是否充电
    if pluggedIn && conf.UpperLimit() < 100 && charge >= conf.UpperLimit() {
        // 达到上限,停止充电
        if err := smcConn.DisableCharging(); err != nil {
            logrus.Errorf("failed to disable charging: %v", err)
        }
        maintainedChargingInProgress = true
    } else if pluggedIn && conf.UpperLimit() < 100 && charge <= conf.LowerLimit() {
        // 低于下限,开始充电
        if err := smcConn.EnableCharging(); err != nil {
            logrus.Errorf("failed to enable charging: %v", err)
        }
        maintainedChargingInProgress = true
    } else {
        maintainedChargingInProgress = false
    }
}

SMC 通信模块

go 复制代码
// pkg/smc/apple_smc.go
type AppleSMC struct {
    conn gosmc.Connection
    capabilities map[string]bool
}

func (c *AppleSMC) EnableCharging() error {
    logrus.Tracef("EnableCharging called")
    
    // 预 Tahoe 固件版本
    if c.capabilities[ChargingKey1] && c.capabilities[ChargingKey2] {
        err := c.Write(ChargingKey1, []byte{0x0})
        if err != nil {
            return err
        }
        err = c.Write(ChargingKey2, []byte{0x0})
        return err
    }
    
    // Tahoe 固件版本
    return c.Write(ChargingKey3, []byte{0x00, 0x00, 0x00, 0x00})
}

func (c *AppleSMC) DisableCharging() error {
    logrus.Tracef("DisableCharging called")
    
    // 预 Tahoe 固件版本
    if c.capabilities[ChargingKey1] && c.capabilities[ChargingKey2] {
        err := c.Write(ChargingKey1, []byte{0x2})
        if err != nil {
            return err
        }
        err = c.Write(ChargingKey2, []byte{0x2})
        return err
    }
    
    // Tahoe 固件版本
    return c.Write(ChargingKey3, []byte{0x01, 0x00, 0x00, 0x00})
}

客户端 API 通信

go 复制代码
// pkg/client/client.go
type Client struct {
    socketPath string
    httpClient *http.Client
}

func (c *Client) SetLimit(l int) (string, error) {
    return c.Put("/limit", strconv.Itoa(l))
}

func (c *Client) GetCharging() (bool, error) {
    ret, err := c.Get("/charging")
    if err != nil {
        return false, pkgerrors.Wrapf(err, "failed to get charging status")
    }
    return parseBoolResponse(ret)
}

func (c *Client) Send(method string, path string, data string) (string, error) {
    logrus.WithFields(logrus.Fields{
        "method": method,
        "path":   path,
        "data":   data,
        "unix":   c.socketPath,
    }).Debug("sending request")
    
    var resp *http.Response
    var err error
    url := "http://unix" + path
    
    // 通过 Unix socket 与守护进程通信
    switch method {
    case "GET":
        resp, err = c.httpClient.Get(url)
    case "PUT":
        req, err2 := http.NewRequest("PUT", url, strings.NewReader(data))
        if err2 != nil {
            return "", fmt.Errorf("failed to create request: %w", err2)
        }
        resp, err = c.httpClient.Do(req)
    default:
        return "", fmt.Errorf("unknown method: %s", method)
    }
    
    if err != nil {
        return "", fmt.Errorf("failed to send request: %w", err)
    }
    
    defer resp.Body.Close()
    b, err := io.ReadAll(resp.Body)
    return string(b), err
}

系统睡眠监听

go 复制代码
// pkg/daemon/sleep_darwin.go
//export canSystemSleepCallback
func canSystemSleepCallback() {
    logrus.Debugln("received kIOMessageCanSystemSleep notification")
    
    if !conf.PreventIdleSleep() {
        logrus.Debugln("PreventIdleSleep is disabled, allow idle sleep")
        C.AllowPowerChange()
        return
    }
    
    // 系统刚唤醒时拒绝空闲睡眠
    if timeAfterWokenUp := time.Since(lastWakeTime); 
       timeAfterWokenUp < time.Duration(preSleepLoopDelaySeconds)*time.Second {
        logrus.Debugf("system has just waked up, deny idle sleep")
        C.CancelPowerChange()
        return
    }
    
    // 立即运行循环更新充电状态
    maintainLoopInner(false)
    
    if maintainedChargingInProgress {
        logrus.Debugln("maintained charging in progress, deny idle sleep")
        C.CancelPowerChange()
    } else {
        C.AllowPowerChange()
    }
}

batt 通过深度集成 macOS 系统服务,提供了完整的电池健康管理解决方案,让您的 Apple Silicon MacBook 电池寿命得到有效延长。

相关推荐
GuWenyue20 小时前
Cursor黑盒拆解!1套LangChain.js手写Mini编程Agent,自动生成React项目,效率提升60%
前端·数据库·人工智能
GuWenyue20 小时前
传统Agent工具两大痛点!300行代码落地MCP跨语言工具,彻底解耦LLM与工具
前端·人工智能·算法
老云讲算力市场20 小时前
WAIC首日观察:国产算力与机器人加速落地,奇点算力迎来产业新机遇
人工智能·科技
小林ixn21 小时前
大模型随机说话的秘密:Temperature 和 Top K 深度解析,LangChain 实战调优
人工智能·langchain
ALINX技术博客21 小时前
ALINX 亮相 2026 WAIC 世界人工智能大会,展示 AI 视觉 FPGA+GPU 异构计算与电子后视镜解决方案
人工智能·ai·fpga·世界人工智能大会·电子后视镜
程序员老猫21 小时前
当 AI 能写 80% 的代码时,后端工程师的核心价值还剩什么?
人工智能
想会飞的蒲公英21 小时前
计算机怎样读取中文文本:编码、清洗与标准化
人工智能·python·自然语言处理
CIO_Alliance21 小时前
AI+iPaaS解决方案深度整合:让跨系统业务流程自动化一步到位
人工智能·ipaas·系统集成·ai+ipaas·企业cio联盟·企业级ai化转型
苏州IT威翰德21 小时前
算力资产“续命”专家:苏州威翰德科技赋能NVIDIA高端AI芯片芯片级维修
大数据·人工智能
天上路人1 天前
A59P双波束语音模块:神经网络降噪在远场拾音中的工程实现分析
人工智能·深度学习·神经网络·ai降噪·ai语音·麦克风·回音消除