博客

  • [项目] ClarityAI 智能需求对齐工具

    当你在用AI生成代码、方案或内容时,是否常遇到这样的场景:
    你写了一长串需求,AI却给出了完全跑偏的答案;
    你反复修改提示词,但生成结果始终“差点意思”;
    你觉得自己说清楚了,但AI理解的是另一个版本……

    这不是AI不够聪明,而是你的需求还不够“结构化”。
    ClarityAI 正是为此而生——它通过多轮智能问答,帮你把零散的想法梳理成一份逻辑清晰、细节完备的需求报告,让下游任何AI都能精准理解你的意图。

    使用说明:

    我在自己的服务器上部署了后端,可以直接访问使用:链接直达ClarityAI
    由于资金有限,我设置了单日token使用限额,如达到限额,请在“设置”中填写自己的API BaseURL和API-Key
    自定义设置

    使用示例

    [photos]
    示例
    [/photos]

    一、痛点:用户与AI之间的“代沟”

    我们正处在AI应用爆发期,从代码生成、文案创作到产品设计,人人都想借助AI提高效率。但一个普遍存在的误区是:我们常常高估了自己表达需求的能力,也低估了AI准确理解模糊语言的门槛。

    • 你说“做一个类似小红书但更简洁的App”,AI可能理解为“去掉部分功能”,但你对“简洁”的定义是“极简设计风格、只保留图文分享”;
    • 你说“用Python写个爬虫”,AI给了你一个通用框架,但你忘了说明需要处理反爬、需要存储到数据库、需要定时执行;
    • 你说“生成一份市场分析报告”,AI按模板输出,但你没说清楚目标受众是投资人还是内部团队,导致报告侧重点完全错误。

    结果就是:AI输出的内容不符合预期 → 反复修改提示词 → 耗费大量时间 → 最终可能还是手动重写。这不是AI能力不行,而是我们缺少一个把模糊需求转化为精确指令的中间层。

    ClarityAI 的角色就是这一中间层。它不直接生成最终产品,而是通过系统化提问,引导你一步步补充功能边界、技术约束、用户场景、优先级等关键信息,最终输出一份结构化的需求报告。这份报告可以直接喂给任何下游AI(如ChatGPT、Claude、Copilot、Midjourney等),让它们基于完整的上下文给出更贴合你初衷的结果。

    二、产品定位:需求报告的生成器,而非最终产出物

    ClarityAI 的核心价值不是替代AI,而是增强你与AI之间的沟通效率。它像一位专业的需求分析师,帮你把脑子里“一团乱麻”的想法梳理成清晰条理的需求文档。

    • 输入:一句简单的想法(例如:“我想做一个帮助用户记账的微信小程序”)
    • 过程:多轮动态问答(覆盖用户画像、功能列表、技术选型、数据隐私、迭代计划等维度)
    • 输出:一份Markdown格式的详细需求报告,包含背景、目标、功能描述、非功能需求、验收标准等章节
      这份报告可以直接粘贴到对话窗口,作为高级提示词发给任意AI,让其生成代码、设计稿、方案或文案;也可以作为团队内部的需求规格书,用于后续开发。

    三、技术架构:Vue 3 + Flask,轻量而高效

    项目采用前后端分离架构,代码仓库分置,便于独立部署和扩展。

    前端 —— ClarityAI-Frontend

    基于 Vue 3 + Vite + Element Plus,注重交互流畅性和界面清晰度:

    • 核心依赖:Vue 3.5.27、Vite 7.3.1、Element Plus 2.7.7、Pinia 3.0.4、Vue Router 5.0.1
    • Markdown 渲染使用 markdown-it,结果页清晰展示报告
    • 主要页面:
    • 首页:输入初步想法,一键启动需求澄清流程
    • 问答页:展示AI动态生成的问题(单选/填空/论述),逐题作答
    • 结果页:渲染完整需求报告,支持下载Markdown,并生成分享链接
    • 总览页:以时间线展示整个对话和报告版本,方便回溯

    后端 —— ClarityAI-Backend

    基于 Flask 3.0.3,提供RESTful API,并集成Qwen(通义千问)或OpenAI作为智能引擎:

    • 数据库:SQLite(轻量,开箱即用)
    • AI接口:支持动态生成问题、基于答案继续追问、汇总生成最终报告
    • 安全与成本控制:支持Token每日限额配置,避免API费用超支

    主要API端点:

    GET  /api/health                     # 服务状态
    POST /api/generate-questions         # 根据初始想法生成问卷
    GET  /api/session/<id>               # 获取会话所有数据
    POST /api/submit-answers             # 提交当前轮答案
    POST /api/continue-with-feedback     # 继续追问细化
    POST /api/generate-pdf               # 生成PDF报告
    GET  /api/download-pdf/<id>          # 下载PDF
    DELETE /api/session/<id>             # 删除会话

    四、核心流程:三步生成高质量需求报告

    第一步:输入你的原始想法

    在首页输入框中写下你最粗颗粒的想法,哪怕只有一句话也可以。例如:“我想做一个在线教育平台”。

    第二步:AI引导式问答

    后端AI会根据你的输入,自动生成一组结构清晰的问题,可能会根据你的想法涵盖:

    • 目标用户:谁会用?他们的痛点是什么?
    • 核心功能:必须有的功能和锦上添花的功能?
    • 技术偏好:有指定技术栈吗?有无性能要求?
    • 资源约束:时间、预算、团队规模?
    • 成功标准:如何衡量最终成果是否达标?
      问题形式包括单/多选题、填空题和开放式叙述题。你回答完一轮后,还可以选择“继续细化”,AI会根据已有答案再生成更深层的问题,直到你觉得需求已经足够清晰为止。

    第三步:生成需求报告并用于下游AI

    所有问答完成后,后端会自动汇总所有信息,生成一份结构化的Markdown报告。报告包含以下典型章节:

    1. 项目概述(背景、目标)
    2. 用户角色与场景(谁在什么情况下使用)
    3. 功能需求(优先级分级)
    4. 非功能需求(性能、安全、兼容性)
    5. 技术约束与依赖
    6. 验收标准
      你可以在结果页直接复制这份报告,粘贴到其他AI工具的对话框,作为超级提示词(Super Prompt)。例如,复制报告内容发送给代码生成AI,它会基于完整的需求描述生成更准确的代码骨架;发送给设计AI,它会产出风格更匹配的设计稿。

    五、快速本地部署

    # 后端
    git clone https://github.com/kazuky233/ClarityAI-Backend.git
    cd ClarityAI-Backend
    python -m venv .venv
    source .venv/bin/activate  # Windows: .venv\Scripts\activate
    pip install -r requirements.txt
    # 配置 .env 文件,填写 QWEN_API_KEY(或 OPENAI_API_KEY)
    python run.py
    
    # 前端
    git clone https://github.com/kazuky233/ClarityAI-Frontend.git
    cd ClarityAI-Frontend
    npm i
    npm run dev

    访问 http://localhost:5173 即可体验。

    六、使用场景

    • 个人开发者:用AI辅助生成项目代码前,先用ClarityAI理清需求
    • 产品经理:快速产出需求文档初稿,作为团队讨论的基础
    • 创业者:将自己的商业想法转化为可执行的规格说明
    • AI重度用户:通过高质量需求报告,减少与AI的反复拉扯

    结语

    ClarityAI 不试图替代任何AI,而是为AI“指路”。在AI能力日益强大的今天,清晰的输入比复杂的提示词技巧更重要。通过将模糊想法转化为结构化需求,ClarityAI 让你与任何下游AI的对话都变得更高效、更精准。
    如果你也曾因需求没说清楚而让AI“翻车”,不妨试试 ClarityAI。欢迎访问GitHub仓库,点个Star,也期待你的Issue!

  • [项目] 基于自训练AI的Mesh自适应路由优化系统研究

    跳转:建模论文

    项目文档&研究概述

    一、研究背景

    当前无线 Mesh 网络普遍存在“信号强却连接不稳定”的问题。传统 Zigbee、WIFI Mesh 等协议依赖单一信号强度因素进行路由选择,无法全面感知链路丢包率、物理遮挡及节点负载等关键因素。一旦遭遇墙体遮挡、人员移动等动态干扰,网络容易中断,不能适应变化/复杂的环境,难以满足特殊环境下的通信需求。
    本项目改变了传统单一因素决策模式,搭建“AI 智能决策”架构。通过将随机森林算法部署至 ESP32-C6 芯片,赋予每个节点独立决策的能力,无需云端参与。系统融合信号质量、链路跳数、节点负载、链路稳定性等多维特征,实现从“被动连接”到“主动优化”的跨越,确保在复杂多变环境下网络依然稳健、高效、可自愈。


    二、项目概述

    本项目构建了一种基于 AI 算法的自适应路由优化系统。
    通过 OMNet++无线网络物理仿真软件构建含有若干墙体与通信节点的场景,获得了 6959 条仿真训练数据。之后,采用随机森林算法拟合训练集数据,得出了拟合效果较好的数学模型。
    该模型可用函数近似表示(f 由随机森林近似):

    $$DeliveryRatio = f(RSSI, Hop, Child, Loss)$$

    研究后,将得到的预测算法部署至 ESP32-C6 单片机并进行实验,结果表明本文得出的模型在选择上级节点时能够更好地兼顾信号强度、链路跳数、节点负载等信息进而选择综合质量更优的节点进行组网。
    该算法能够应用于大型复杂环境的快速组网部署等场景,具有一定的实用前景。


    三、核心亮点

    1、多特征融合路由决策

    突破传统仅依赖信号强度的路由方式,综合 RSSI、传输距离、链路质量、能耗等多维特征,提升路径决策准确性。

    2、模块化智能组网

    每个 ESP32-C6 为一个独立的单元,单元之间彼此通信协商,通过训练的决策模型综合多方面实际数据推算节点质量指标,最终能够形成最优的拓补网络。
    组网后,不论是 ESP32(C6/S3/C3/8266),还是手机、平板、电脑,都可以通过这些节点进行网络访问。此时这些节点起到了网络中继路由作用。

    3、训练基于机器学习的拟合预测模型

    通过 OMNeT++无线物理仿真工具采集数据,使用随机森林训练路由选择模型,决定系数:

    $$\mathrm{R}^2 = 0.965047, \mathrm{MSE} = 0.001571$$

    实现高精度路径质量预测。

    [photos]
    OMNet++仿真
    拟合1
    拟合2
    [/photos]

    4、AI 边缘化部署

    将模型部署到 ESP32-C6 节点,实现本地实时推理,无需云端参与,提升模型决策响应速度与便捷性。

    5、3D 建模打印 + PCB 设计

    将采用 3D 建模打印技术设计终端外壳,集成锂电池与充放电模块,通过将各个部件焊接到设计并打样的 PCB 电路板上,实现电路集成。

    [photos]
    3D建模图
    PCB设计图
    实体成品图
    [/photos]

    6、云端数据/结构实时监控

    结合 Python Flask 框架搭建服务端(后端),并将服务端通过 Docker 容器化部署于 Linux 云服务器(Debian-12.0),通过 Vue.JS 编写前端页面,实现网络拓补结构及节点信息的实时监控。

    [photos]
    后端
    前端
    [/photos]


    四、与传统网络连接方式的对比图解

    1、正常情况

    正常情况

    2、可能遇到的意外情况(信号阻挡 或 距离远信号弱)

    意外情况
    对比图解 1,2:该创新方案优势明显,由于结合了训练的 AI 模型,在多变环境下本项目拥有自适应环境、自动优化网络拓补结构的能力,具备更强的适应性、灵活性、预见性。


    五、应用前景

    • 灾害现场应急通信(无基站环境)
    • 智慧物联网网络
    • 工业低功耗监测网络
    • 智能家居自组织网络

    研究日志

    一:选题

    现状:
    当前无线 Mesh 网络普遍存在“信号强却不稳定”的现象。
    问题所在:
    传统协议依赖单一信号强度进行路由选择,无法全面感知链路丢包率、物理遮挡及节点负载等关键因素。
    研究目标:
    搭建稳健、高效、可自愈的智能 Mesh 网络体系。


    二:仿真环境构建、数据采集

    选用 OMNet++ 无线网络物理仿真软件构建场景。
    仿真逻辑基于以下假设:

    1. 场景为二维房间,网关、终端、中继、墙体都在每一轮随机生成
    2. 墙体简化为线段,链路是否“穿墙”通过线段相交判断,信号衰减随穿墙数量线性累加。
    3. 组网为树形结构,以主网关作为根节点
    4. 跳数定义为中继到网关路径长度(中继跳),子设备数定义为该中继在树中的直接子节点个数
    5. 墙壁对信号造成的衰弱影响利用对数距离路径损耗模型的修正模型计算

    $$PL = PL_0 + 10n \log_{10}\left(\frac{d}{d_0}\right) + N_{\text{wall}} \cdot A_{\text{wall}}$$

    1. 中继节点的子设备数越多,节点负载越大,数据包丢包概率越高。
    2. 数据包在每一次中继转发过程中均存在一定的丢包可能性。

    基于以上假设:
    使用 C++ 编写仿真逻辑,包括随机环境生成(网关、终端、中继节点与墙体位置)、终端到各中继及中继到网关路径的 RSSI 与跳数计算、子设备负载对链路成功率的影响、中继概率丢包、统计仿真发数据包可达率,以及 CSV 结果输出(RSSI、跳数、子设备数、节点到网关丢包率、可达率)


    三:数据处理、AI 模型训练与优化

    (一)数据预处理

    数据共包含 6959 条记录,每条记录由 5 个字段组成:

    • 信号强度(RSSI_dBm)
    • 节点跳数(HopCount)
    • 节点子节点数(ChildCount)
    • 节点到网关的丢包率(NodeToGatewayLossRate)
    • 终端数据包可达率(DeliveryRatio)
      其中 RSSI_dBm、HopCount、ChildCount、NodeToGatewayLossRate 作为特征。
      终端与网关可达率 DeliveryRatio 作为模型预测的标签(目标变量)。
      通过 Python 中 pandas 库读取 csv 数据。

    (二)划分训练集和测试集

    随机划分数据中 20% 为测试集,另外 80% 为训练集。

    (三)算法拟合

    利用 Python 中 scikit-learn 库,分别构建线性回归、多项式回归和随机森林算法。

    (四)结果分析

    (1)线性回归

    $$\mathrm{R}^2 = 0.622295, \mathrm{MSE} = 0.016977$$

    拟合效果较弱,特征数据与标签数据线性关系不明显。

    [photos]
    线性回归1
    线性回归2
    [/photos]

    (2)多项式回归(二次)

    $$\mathrm{R}^2 = 0.836970, \mathrm{MSE} = 0.007328$$
    根据图像得出拟合效果略优于线性回归,但在真实值较小处预测出现了负值,模型存在过拟合现象。

    [photos]
    多项式回归1
    多项式回归2
    [/photos]

    (3)随机森林

    $$\mathrm{R}^2 = 0.965047, \mathrm{MSE} = 0.001571$$
    由于特征与标签之间存在非线性关系,且样本中存在噪声,经分析该算法是符合要求的预测方式。

    [photos]
    随机森林1
    随机森林2
    [/photos]


    四:硬件开发与部署

    核心:
    选定 ESP32-C6 单片机作为核心控制单元。将训练好的预测算法部署至 ESP32-C6 节点。完善基本逻辑。
    结构:
    采用 3D 建模打印技术设计终端外壳。完成 PCB 电路板设计与打样。
    功能:
    集成锂电池与充放电模块,开关,OLED 屏幕。
    组网能力:
    每个 ESP32-C6 为独立单元,彼此通信协商,形成最优拓扑网络。
    兼容 ESP32 系列(C6/S3/C3/8266)及手机、平板、电脑等终端接入。

    [photos]
    3D建模图
    PCB设计图
    实体成品图
    [/photos]


    五:云端监控系统搭建

    后端:
    结合 Python Flask 框架搭建服务端。
    通过 Docker 容器化部署于 Linux 云服务器(Debian-12.0)。
    前端:
    使用 Vue.JS 编写前端页面。
    实现了网络拓扑结构及节点信息的实时监控(包括节点编号、子设备数、丢包率、RSSI 等数据展示)。
    后端日志可实时记录数据接收情况(如 POST /api/data 请求处理)。

    [photos]
    后端
    前端
    [/photos]


    六:优化系统、修复问题

    整理各部分程序,查找并修复逻辑和细节错误,优化系统,同时增加一些有意义的功能。

  • [项目] 一套完整的智能共享单车系统

    一套覆盖用户APP、智能车锁、管理后台的完整共享单车解决方案,技术栈全面,实测抗压 89.7 次/秒

    项目缘起

    为了参加2025全国青少年信息素养大赛总决赛,我们按照给定题目要求完成了基本开关锁功能,但为了更贴近生活、做成完整成熟的产品,我们开发了更多分支及创新功能,包括但不限于:GPS定位、事故检测报警、车辆故障上报、车辆数据集群管理、后台管理大屏、以用户为单位的数据管理、行程数据记录展示。涵盖用户端APP、嵌入式智能锁、后台管理系统以及API服务
    本文将深入解析这套系统的技术架构与实现亮点。

    团队分工

    |——|——–|——|
    | 我(XHL) | 服务器运维、前后端搭建、APP、全部软件部分等 | 个人网站
    | The Sandy | 车锁3D结构设计与打印、硬件结构构建、协助完成ESP32程序开发等 | 个人网站

    一、整体架构:分层设计

    项目三层架构:

    层级技术栈功能
    客户端Vue + Android + 高德地图 SDK地图展示、扫码开锁、行程记录、用户中心
    单车端MicroPython + ESP32 + GPS/MPU6050定位上报、姿态检测、开锁执行
    API 服务Python Flask业务逻辑处理、数据接口
    数据层MySQL + 连接池数据存储
    基础设施Docker + Nginx + Debian容器化部署、负载均衡

    [photos]
    APP端截图

    [/photos]

    二、服务端亮点:高性能与高可用

    2.1 连接池设计

    服务端基于 Python Flask 开发,数据库方面我自己封装了 SQL

    from dbutils.pooled_db import PooledDB
    
    class SQL:
        def __init__(self, db_address, db_username, db_passwd, db_name):
            self.pool = PooledDB(
                creator=pymysql,
                maxconnections=10,
                host=db_address,
                user=db_username,
                password=db_passwd,
                database=db_name
            )

    实测数据:系统可承受约 89次/秒 的数据请求,在网络攻击测试中服务端从未崩溃。

    2.2 日志系统

    所有 API 请求都会通过 server_log() 函数记录到数据库,日志类型分为:

    • USER:用户登录、注册、查询等操作
    • BIKE:单车解锁、锁车、位置更新
    • ACCI:事故报警、防盗报警
    • MAIN:报修、维修完成
    • PANEL:后台数据访问
      这不仅便于问题追溯,也为数据分析和运营决策提供了基础。

    2.3 钉钉告警集成

    事故报警和防盗报警会通过钉钉机器人实时推送:

    [photos]
    钉钉告警推送
    [/photos]

    三、智能车锁:硬件与算法的结合

    [photos]
    智能锁实物图
    [/photos]

    3.1 机械结构迭代

    建模设计与3D打印部分由The Sandy完成(个人网站

    外壳经历了五代迭代:

    版本材料改进点
    初代PLA验证基础结构可行性
    二代PLA优化润滑油方案
    三代PLA固定方案优化
    四代PETG-CF强度大幅提升
    四+代PETG-CF + PETG 开窗解决 GPS 信号屏蔽问题

    技术细节:碳纤维增强 PETG 会屏蔽 GPS 信号,因此天线区域专门采用 PETG 开窗设计。

    3.2 姿态检测与事故报警

    使用 MPU6050 六轴传感器实时检测车辆姿态。当检测到异常冲击(如摔车),系统会:

    1. 通过 OLED 屏幕弹出提示,给用户 10 秒取消时间(防止误报)
    2. 确认后调用 /bike/accident 接口
    3. 服务端查询用户预留的紧急联系人
    4. 钉钉机器人自动推送事故位置和用户信息

    3.3 电源管理与光伏充电

    太阳能板 → 充电IC → 7.4V锂电池
                          ↓
                   DC-DC降压 → 5.06V → ESP32
                          ↓
                   继电器直连 → 电磁铁(大电流)
    • 光伏充电:6V 3W 太阳能板持续补电
    • 低功耗策略:GPS 无数据时自动重试,干簧管异常触发三次重试后上报故障

    四、后台管理系统:数据可视化

    后台管理仪表盘截图

    后台采用 Vue3 + ECharts + 高德地图API 构建,功能包括:

    • 仪表盘:单车总数、用户总数、请求总量实时刷新
    • 单车位置追踪:地图上实时显示所有车辆分布
    • 用户管理:查看所有用户信息及操作记录
    • 骑行记录:订单详情、轨迹回放
    • 维修管理:报修/修复状态流转
    • 日志审计:服务端日志、单车日志、用户日志全量查询

    五、API 接口设计规范

    客户端接口示例

    接口路径说明
    用户登录POST /client/login返回昵称和状态
    附近单车POST /client/nearby经纬度范围查询
    解锁单车POST /client/unlock创建骑行记录
    获取记录POST /client/getrecord历史订单

    单车设备接口

    接口路径说明
    状态检查POST /bike/check返回 lock/unlock
    位置更新POST /bike/update实时上报轨迹
    事故报警POST /bike/accident触发钉钉推送

    安全设计

    后台接口统一验证 Token:

    {"token": "AABBCC"}

    六、部署与运维

    项目采用 Docker 容器化部署,运行在云服务器上:

    • OpenResty:端口转发、负载均衡
    • MySQL 容器:数据持久化
    • Python Flask 容器:API 服务
    • Docker Compose:一键编排启动

    七、项目亮点总结

    1. 技术栈完整闭环:从硬件(ESP32/MPU6050/GPS)到 APP(Vue/Android),从服务端(Flask)到数据库(MySQL),再到大屏(Vue3/ECharts),覆盖全链路
    2. 工程化实践到位:连接池、日志分类、Docker 部署,具备生产环境可用性
    3. 安全与应急机制:事故报警 + 10 秒取消机制、防盗报警、钉钉实时推送
    4. 性能表现优异:实测 89.7 次/秒并发请求,攻击测试服务端稳定不崩溃

    欢迎技术交流。如需完整源代码与硬件文件,请联系

  • [摄影] 云上探校 – 沉浸式环游金初校园

    网站链接:点击此处进入金初校园

    金初校园一览:(高清图片,若未加载出来请稍作等待)

    后山操场
    操场
    教学楼

    更多超高清图片与4K视频欢迎与我联系,此处由于网站承载力有限故不放出。

  • [摄影] 云上探校 – 沉浸式环游一中校园

    网站链接:点击此处进入一中校园

    一中校园一览:(高清图片,若未加载出来请稍作等待)

    校园总览
    孔子像
    校园一隅

    更多超高清图片与4K视频欢迎与我联系,此处由于网站承载力有限故不放出。

  • [业余] ESP32 智能喷水降温系统

    项目亮点

    • [x] 网页操控:访问设备 IP 即可实时查看温度与自动化状态
    • [x] 手动/自动双模式:通过网页随时开关浇水(手动模式会临时退出自动化,避免浪费水)
    • [x] 智能温控:自动模式下,温度 ≥30℃ 自动开水,<30℃ 自动停水
    • [ ] 网页暂未添加 CSS,仅做功能演示,可根据需要自行美化

    起因:空调罢工,问题出在外机

    2024 年湖北的夏天格外难熬,家里空调制冷效果奇差,基本形同虚设。
    一番折腾后,通过 控制变量法 逐项排查,最终锁定真凶——外机背板散热不畅(被柜板挡住,热量排不出去)。

    临时想到的解决方案简单粗暴:用水泵朝外机喷水,强制降温

    继电器

    TB 采购水泵、继电器等模块,接通电源,能跑起来,第一步成功!


    新问题:一直喷水太浪费了

    手动开关不仅麻烦,人不在家时要么干烧要么浪费水。
    我开始思考如何让系统根据温度自动启停

    忽然想起去年做火箭姿态矫正时留下的 MPU6050 六轴传感器,它内部集成了一颗 NTC 温度模块。
    虽然原本是用来检测芯片温度的,但 MPU6050 自身发热极小,完全可以近似看作环境温度。
    于是把它从火箭上“拆借”过来,搭配 ESP32-C3 实现温控。


    硬件接线

    MPU6050 与 ESP32-C3 的接线非常简单(左:MPU6050,右:ESP32-C3):

    MPU6050ESP32-C3
    VCC3V3
    GNDGND
    SDAP8 (SDA)
    SCLP9 (SCL)
    硬件接线

    软件设计

    开发环境:Arduino IDE
    核心思路:ESP32-C3 启动一个轻量 Web 服务器,手机或电脑连上后即可看到实时温度与浇水状态,并可通过按钮手动控制或开启自动化。

    主要功能:

    • 访问根路径 / 返回控制页面
    • /dht 接口返回传感器数据(实时温度、浇水状态、自动状态)
    • /set 接口切换浇水开关(同时关闭自动模式)
    • /auto 接口切换自动模式
    • 自动化逻辑:温度 ≥30℃ 开水,<30℃ 停水

    以下为完整代码:

    #include <Adafruit_MPU6050.h>
    #include <Adafruit_Sensor.h>
    #include <WiFi.h>
    #include <ESPAsyncWebServer.h>
    
    AsyncWebServer server(80);   // 端口80,可直接通过IP访问
    
    // 网页 HTML(存储于 Flash)
    const char index_html[] PROGMEM = R"rawliteral(
    <!DOCTYPE HTML>
    <html>
    <head>
        <meta charset="utf-8">
        <title>空调浇水控制</title>
    </head>
    <body>
        <h2>空调浇水控制</h2>
        <div id="dht"></div>
        <button onclick="set()">开启/关闭浇水</button>
        <button onclick="autoset()">开启/关闭自动</button>
    </body>
    <script>
        function set() {
            var xhr = new XMLHttpRequest();
            xhr.open("GET", "/set?value=ESP32", true);
            xhr.send();
        }
        function autoset() {
            var xhr = new XMLHttpRequest();
            xhr.open("GET", "/auto?value=ESP32", true);
            xhr.send();
        }
        // 每秒更新一次数据
        setInterval(function () {
            var xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = function () {
                if (this.readyState == 4 && this.status == 200) {
                    document.getElementById("dht").innerHTML = this.responseText;
                }
            };
            xhttp.open("GET", "/dht", true);
            xhttp.send();
        }, 1000);
    </script>
    </html>
    )rawliteral";
    
    Adafruit_MPU6050 mpu;
    #define MPU6050_INTERVAL 100       // 传感器读取间隔(毫秒)
    unsigned long mpu6050Times = 0;
    float mpu6050Temp = 0;
    
    float xAcceleration, yAcceleration, zAcceleration;
    float xAccele, yAccele, zAccele;
    float xGyro = 0, yGyro = 0, zGyro = 0;
    float gravity = 9.8;
    
    bool iswater = false;  // 浇水状态
    bool isauto = true;    // 自动模式默认开启
    
    // 构造返回给网页的 HTML 数据
    String Merge_Data(void) {
        String dataBuffer = "<p>";
        dataBuffer += "<h1>传感器数据</h1>";
        dataBuffer += "<b>温度: </b>";
        dataBuffer += String(mpu6050Temp, 1) + " ℃";
        dataBuffer += "<br />";
        dataBuffer += "<b>当前浇水状态: </b>";
        dataBuffer += iswater ? "开启" : "关闭";
        dataBuffer += "<br />";
        dataBuffer += "<b>当前自动状态: </b>";
        dataBuffer += isauto ? "开启" : "关闭";
        dataBuffer += "<br /></p>";
        return dataBuffer;
    }
    
    // 手动切换浇水(同时关闭自动模式)
    void Config_Callback(AsyncWebServerRequest *request) {
        iswater = !iswater;
        isauto = false;
        request->send(200, "text/plain", "OK");
    }
    
    // 切换自动模式
    void Auto_Callback(AsyncWebServerRequest *request) {
        isauto = !isauto;
        request->send(200, "text/plain", "OK");
    }
    
    void setup() {
        Serial.begin(115200);
    
        // 连接 WiFi(请替换为实际 SSID 和密码)
        WiFi.begin("你的WiFi名", "你的WiFi密码");
        while (WiFi.status() != WL_CONNECTED) {
            delay(500);
            Serial.println("正在连接WiFi...");
        }
        Serial.println("WiFi 连接成功!");
        Serial.print("IP 地址: ");
        Serial.println(WiFi.localIP());
    
        pinMode(1, OUTPUT);   // GPIO1 控制继电器(水泵)
    
        // 配置 Web 服务器路由
        server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
            request->send_P(200, "text/html", index_html);
        });
        server.on("/dht", HTTP_GET, [](AsyncWebServerRequest *request) {
            request->send_P(200, "text/plain", Merge_Data().c_str());
        });
        server.on("/set", HTTP_GET, Config_Callback);
        server.on("/auto", HTTP_GET, Auto_Callback);
        server.begin();
        Serial.println("HTTP 服务器已启动");
    
        // 初始化 MPU6050
        if (!mpu.begin()) {
            Serial.println("未找到 MPU6050 芯片!");
            while (1) { delay(1000); }  // 停止运行
        }
        mpu.setAccelerometerRange(MPU6050_RANGE_16_G);
        mpu.setGyroRange(MPU6050_RANGE_250_DEG);
        mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
        Serial.println("MPU6050 初始化成功!");
    }
    
    void loop() {
        getMpu6050Data();   // 读取温度及姿态数据
    
        if (isauto) {
            // 自动模式:根据温度控制水泵
            if (mpu6050Temp >= 30.0) {
                digitalWrite(1, HIGH);
                iswater = true;
            } else {
                digitalWrite(1, LOW);
                iswater = false;
            }
        } else {
            // 手动模式:直接遵从按钮状态
            digitalWrite(1, iswater ? HIGH : LOW);
        }
    }
    
    void getMpu6050Data() {
        if (millis() - mpu6050Times >= MPU6050_INTERVAL) {
            mpu6050Times = millis();
    
            sensors_event_t a, g, temp;
            mpu.getEvent(&a, &g, &temp);
    
            mpu6050Temp = temp.temperature;
    
            xAcceleration = a.acceleration.x;
            yAcceleration = a.acceleration.y;
            zAcceleration = a.acceleration.z;
    
            xAccele = xAcceleration / gravity;   // 转换为 g 为单位
            yAccele = yAcceleration / gravity;
            zAccele = zAcceleration / gravity;
    
            xGyro = g.gyro.x;
            yGyro = g.gyro.y;
            zGyro = g.gyro.z;
    
            // 串口输出,便于调试(保留了姿态数据,方便后续扩展)
            Serial.print("温度: "); Serial.print(mpu6050Temp);
            Serial.print(" , x加速: "); Serial.print(xAccele);
            Serial.print(" , y加速: "); Serial.print(yAccele);
            Serial.print(" , z加速: "); Serial.print(zAccele);
            Serial.print(" , x角速度: "); Serial.print(xGyro);
            Serial.print(" , y角速度: "); Serial.print(yGyro);
            Serial.print(" , z角速度: "); Serial.println(zGyro);
        }
    }
    最终效果