💡 划重点

  • 一眼知状态:红绿黄三色直观显示会议室“正在使用”“空闲”“即将使用”
  • 零操作查询:无需打开手机或电脑,走到门口就能看清
  • 自动同步飞书日历:会议预约、取消、变更实时生效
  • 成本极低:全套物料 65 元以内,适合批量部署
  • 可扩展上报:通过 MQTT 将占用数据推送至大屏、管理后台

需求洞察

目标用户

开放式办公室中的员工、行政前台、临时来访客人。

真实痛点

  1. 会议室预约多、变动快,门关着无法判断是有人占用还是忘了取消。
  2. 员工频繁打开飞书或 OA 查会议室日历,打断工作流。
  3. 常出现“以为空闲推门而入,却发现有人在开会”的尴尬。
  4. 小型公司无专业会议室管理系统,行政难以实时掌握使用率。

为什么值得做

市面上智能会议屏或占用传感器单价动辄数百元,布线复杂。本项目利用 ESP32 + WS2812 灯带,配合飞书日历 API 和 MQTT,用 65 元即可把一个普通会议室变得“可视化”,且安装极简。对于 3 间以上会议室的团队,成本优势巨大,同时可沉淀会议室利用率数据,为行政决策提供依据。

方案设计

感知层

控制层

- 空闲:绿色

- 当前有会议:红色

- 距下一场开始 ≤ 10 分钟:黄色

执行层

日志/联网层

物料清单

物料 数量 用途 估算单价 (元)
ESP32-C3 迷你开发板 1 主控,Wi‑Fi 15
WS2812 灯环 (8 或 12 颗) 1 状态指示灯 8
轻触按键 1 切换显示模式 1
电阻 10kΩ 1 按键下拉 0.1
5V 1A USB 电源适配器 1 供电 8
Micro‑USB 供电线 1 连接电源 2
杜邦线 + 排针 若干 接线 2
亚克力外壳 + 磁吸贴 1 装饰与安装 15
合计 51.1

总成本约 51 元,留有约 14 元余量应对器件价格波动或增加蜂鸣器、光敏电阻等扩展件。

接线与结构

- 说明:GPIO0 内置上拉,按键按下为低电平,代码侦测下降沿,无需外加电阻即可使用。但若不放心可额外并联 10kΩ 下拉,保证悬空状态稳定。此处采用板载上拉,物料清单中不强制加电阻。

结构示意

ESP32 与灯环固定在亚克力底板上,灯环面向前方,按键从侧面或底部引出。亚克力外壳半透明白色,灯光柔和扩散。

核心代码

(Arduino 骨架,可编译上传)


#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <Adafruit_NeoPixel.h>
#include <PubSubClient.h>

#define LED_PIN     13
#define NUM_LEDS    12
#define BUTTON_PIN  0

const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASS";
const char* feishu_url = "https://open.feishu.cn/open-apis/calendar/v4/calendars/YOUR_CALENDAR_ID/events?start_time=...";
const char* mqtt_server = "192.168.1.100";

Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
WiFiClient espClient;

unsigned long lastFetch = 0;
int roomState = 0;  // 0=空闲, 1=即将, 2=使用中
int displayMode = 0; // 按键切换模式

void setup() {
  Serial.begin(115200);
  strip.begin();
  strip.setBrightness(30);
  strip.show();
  attachInterrupt(BUTTON_PIN, []() {
    static unsigned long lastPress = 0;
    if (millis() - lastPress > 300) {
      displayMode = (displayMode + 1) % 3;
    }
    lastPress = millis();
  }, FALLING);
  
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) delay(500);
}

void setColor(int r, int g, int b) {
  for(int i=0; i<NUM_LEDS; i++) strip.setPixelColor(i, r, g, b);
  strip.show();
}

void fetchCalendar() {
  HTTPClient http;
  http.begin(feishu_url);
  int code = http.GET();
  if (code == 200) {
    String payload = http.getString();
    DynamicJsonDocument doc(4096);
    deserializeJson(doc, payload);
    // 解析 items, 判断当前会议状态
    // 示例逻辑:
    // if (currentMeeting) roomState = 2;
    // else if (nextMeetingStart - now < 600) roomState = 1;
    // else roomState = 0;
  }
  http.end();
}

void loop() {
  if (!client.connected()) {
    client.publish("room/state", "online");
  }
  client.loop();

  if (millis() - lastFetch > 60000) {
    fetchCalendar();
    lastFetch = millis();
  }

  switch(roomState) {
    case 0: setColor(0, 255, 0); break;   // 绿
    case 1: setColor(255, 200, 0); break; // 黄
    case 2: setColor(255, 0, 0); break;   // 红
  }
  // 按键模式可叠加闪烁效果,此处略
}

*注:飞书 URL 需要根据真实日历 ID 和鉴权 token 拼接,建议使用“自建应用”获取 tenant_access_token,并在请求头中带入。*

*完整获取 token 和解析逻辑可在实际项目中补充。*

调试步骤

  1. 硬件连通性测试

上传空程序,逐个点亮 WS2812 的 R、G、B,确认焊接无误。

  1. Wi‑Fi 连接

串口打印连接状态,确保能 ping 通外网。

  1. 飞书 API 连通

先用 Postman 或 curl 验证能否获取日历事件,再将 URL 填入代码,观察串口打印的 JSON。

  1. 时间解析与灯色切换

手动修改系统时间或使用 NTP 同步,测试三种状态灯色变化。

  1. 按键测试

按下按键是否正确改变 displayMode,并观察灯效变化。

  1. MQTT 上报

使用 MQTT 客户端订阅房间主题,确认状态消息准确。

设计图

三色灯智能会议室状态结构flow
1
感知输入
2
控制处理
3
执行反馈
4
数据上报