飞牛NAS 买回来第一天,我就被风扇噪音劝退了。默认策略要么全速轰鸣,要么低温时完全不转让人焦虑。官方没有提供灵活的风扇控制方案,社区的脚本又各有各的问题——于是我决定自己写一个。
痛点在哪
飞牛NAS(fnOS)基于 Linux,硬件控制走的是标准的 hwmon 子系统。理论上可以直接写 sysfs 文件来控制风扇,但实际使用中有几个现实问题:
- 噪音与散热的平衡难:默认的 BIOS 风扇策略太粗暴,低温全速或者高温才启动,没有中间地带
- 机型差异大:不同飞牛机型用的主板芯片不同(ITE、Nuvoton、Fintek),控制方式有细微差别
- 缺少可视化管理:命令行脚本虽然能用,但调曲线、看温度都不方便
- 安全风险:手动控制风扇如果程序崩了,风扇可能停转导致硬件过热
我需要的是一个安装即用、有 Web 界面、自带安全保护的风扇控制应用。
目标定义
经过需求分析,我确定了几个核心目标:
| 目标 | 说明 |
|---|---|
| 四种运行模式 | 默认(保守曲线)/ 自动(自定义曲线)/ 手动(固定转速)/ 全速(紧急散热) |
| 自定义温控曲线 | 2-10 个节点,支持自动生成和手动微调 |
| Web 管理界面 | 深色主题、实时监控、响应式布局 |
| 多设备兼容 | 不绑定特定芯片型号,通用 hwmon 探测 |
| 多层安全保护 | 程序崩溃、温度读取失败、PWM 写入异常都有兜底 |
| FPK 打包 | 作为飞牛应用商店的标准应用分发 |
技术选型
为什么用 Python?
这个项目的核心是读写 sysfs 文件和运行一个轻量 HTTP 服务,不需要高性能计算。Python 标准库自带 http.server、json、threading,完全够用。最关键的是——零第三方依赖。
NAS 环境特殊,用户不一定有 pip,也不想装一堆包。Python 3.11+ 在飞牛系统上是预装的,拿来就能用。
前端方案:纯 HTML + CSS + 原生 JavaScript,单文件。不需要 Node.js 构建工具链,不需要 npm install,打开就能用。
整体技术栈:
后端:Python 3.11+(标准库 only)
前端:HTML + CSS + Vanilla JS(单文件)
硬件接口:Linux hwmon sysfs
打包:FPK(飞牛应用包格式)
CI:GitHub Actions
测试:unittest(120 个测试用例)
项目结构规划
fnOS-fan-control/
├── src/
│ ├── app/bin/ # Python 应用核心(5 个模块)
│ │ ├── main.py # 入口(启动、信号处理、OOM 保护)
│ │ ├── hardware.py # 硬件抽象层(hwmon 探测、PWM 读写)
│ │ ├── fan_controller.py # 风扇控制核心(温控逻辑)
│ │ ├── config_manager.py # 配置管理(校验、线程安全)
│ │ ├── web_server.py # REST API 服务
│ │ └── static/index.html # Web 管理界面
│ ├── cmd/ # FPK 生命周期脚本(9 个)
│ └── manifest # FPK 包元数据
├── tests/ # 120 个单元 + 集成测试
├── scripts/ # 构建和清理脚本
└── .github/workflows/ # CI 自动构建
模块划分的原则是单一职责:硬件层只管读写 sysfs,控制层只管温控逻辑,配置层只管数据校验,Web 层只管 HTTP 请求。模块之间通过明确的接口交互,任何一个模块出问题都不会拖垮整个系统。
开发计划
整个开发分为 6 个阶段:
- 基础框架 — 硬件探测、配置管理、单风扇控制
- Web 管理界面 — REST API、前端页面、实时监控
- 温控曲线编辑 — SVG 可视化、自动生成、手动微调
- FPK 打包 — 生命周期脚本、安装向导、权限配置
- 多设备适配 — 通用 hwmon 探测、多区域控制
- 测试与文档 — 单元测试、集成测试、完整文档
下一篇预告
下一篇会聊架构设计的核心决策:为什么选择「sysfs 就是抽象层」的设计哲学,如何用最少的代码实现多芯片兼容,以及多层安全机制是怎么设计的。
项目地址:fnOS-fan-control on GitHub(MIT 许可证)