什么是 Blinker?

Blinker 是一套跨硬件、跨平台的物联网解决方案,提供 APP 端、设备端、服务器端支持,使用公有云服务进行数据传输存储。适用于智能家居、数据监测等场景。

硬件平台支持

Blinker 目前支持三大主流开发板:

平台 WiFi BLE NB-IoT GPRS
ESP32 ✅ 内置 ✅ SIM7020/SIM7000 ✅ Air202
ESP8266 ✅ 外接透传模块
Arduino R4 ✅ AT固件 - -

ESP32 凭借内置蓝牙和丰富的外设接口,是目前最推荐的入门选择。

通信模式

WiFi 和蓝牙不能同时启用,通过宏定义切换:

 1#define WIFIMODE   // 启用WiFi模式
 2//#define BLEMODE  // 启用蓝牙模式
 3
 4#if defined(WIFIMODE)
 5    #define BLINKER_WIFI
 6#endif
 7#if defined(BLEMODE)
 8    #define BLINKER_BLE
 9#endif
10
11#include <Blinker.h>  // 必须在通信模式宏定义之后

关键规则#include <Blinker.h> 必须放在通信模式宏定义之后,否则编译会出错。

WiFi 模式初始化:

1Blinker.begin(auth, ssid, pswd);

BLE 模式初始化(ESP32 内置蓝牙):

1Blinker.begin();

程序结构:九大标准模块

Blinker 标准程序按以下顺序组织:

  1. 程序版本备注 — 记录日期和功能
  2. 通信模式宏定义 — WIFIMODE / BLEMODE 切换
  3. 包含库#include <Blinker.h>
  4. 全局变量声明 — WiFi 信息、引脚、状态变量
  5. 组件声明 — 必须放在回调函数前面
  6. 回调函数 — APP 发来数据时由 Blinker.run() 调用
  7. 功能函数 — WiFi 掉线检测等
  8. setup() 初始化 — 开机后只执行一次
  9. loop() 主循环 — 循环执行到关机

这个结构清晰地分离了配置、声明和逻辑,是编写 Blinker 程序的基本骨架。

组件:APP 端的交互元素

Blinker 提供丰富的内置组件:

组件 类名 用途
按钮 BlinkerButton 开关、模式切换
滑块 BlinkerSlider 阈值、亮度、速度
数值 BlinkerNumber 显示传感器数据
文本 BlinkerText 显示字符串
RGB BlinkerRGB 颜色控制
摇杆 BlinkerJoystick 方向控制
开关 BlinkerSwitch 内置开关

声明示例:

1BlinkerButton Button1("b1");      // 键名 "b1",对应APP中组件名
2BlinkerSlider Slider1("s1");      // 键名 "s1"
3BlinkerNumber NUM1("abcd");       // 键名 "abcd"
4BlinkerText Text1("1234");        // 键名 "1234"

核心规则:组件声明必须放在回调函数前面,键名必须与 APP 中的组件名完全一致。

回调函数:设备与 APP 的数据桥梁

按钮回调

1void button1_callback(const String& state)
2{
3  if (state == "tap")      { b1_state = !b1_state; }  // 普通按键:反转
4  else if (state == "on")  { b1_state = true; }       // 开关:开启
5  else if (state == "off") { b1_state = false; }      // 开关:关闭
6  else if (state == "press")   { b1_state = true; }   // 长按:开启
7  else if (state == "pressup") { b1_state = false; }  // 松开:关闭
8  Button1.print(b1_state ? "on" : "off");  // 立即反馈到APP
9}

重要:不要简化按钮的五种处理,防止 APP 设置不同出现逻辑错误。

滑块回调

1void slider1_callback(int32_t value)
2{
3  s1_value = value;  // 赋值全局变量即可
4}

注意:滑块不可在回调函数里调用 print,否则拖不动。

注册回调

1void setup()
2{
3  Button1.attach(button1_callback);
4  Slider1.attach(slider1_callback);
5  Blinker.attachHeartbeat(heartbeat);
6  Blinker.attachDataStorage(dataStorage);
7}

心跳包:APP 获取设备数据的核心机制

心跳包是 APP 获取设备数据的主要方式,间隔约 30 秒一次

1void heartbeat()
2{
3  Button1.print(b1_state ? "on" : "off");   // 按钮:回调+心跳包双保险
4  Slider1.print(s1_value);                   // 滑块:仅心跳包
5  NUM1.print(100);                           // 数值:仅心跳包
6  Text1.print("Hello Blinker");              // 文本:仅心跳包
7  Blinker.notify("页面数据已刷新");           // APP内弹窗推送
8}

数据上报位置规则

数据类型 上报位置 原因
按钮状态 回调函数 + 心跳包 即时反馈 + 兜底
滑块值 仅心跳包 回调里 print 会拖不动
数值/文本 仅心跳包 统一管理

关键print 必须放心跳包回调或按钮回调,不能放 loop(),否则触发 MQTT NOT ALIVE OR MESSAGE LIMIT 错误。

数据存储与图表

生成传感器数据折线图表:

1void dataStorage()
2{
3  Blinker.dataStorage("data1", random(0, 120));
4}
5
6void setup()
7{
8  Blinker.attachDataStorage(dataStorage);
9}

实时数据(RT_DATA)

实时数据每秒以上一次,适用于高频刷新场景。不支持文本组件,只支持数值组件

 1void rtData()
 2{
 3  Blinker.sendRtData("data1", (int32_t)random(0, 120));
 4  Blinker.sendRtData("data2", random(0, 120) / (float)1.5);
 5  Blinker.printRtData();  // 刷新到 APP
 6}
 7
 8void setup()
 9{
10  Blinker.attachRTData(rtData);
11}

WiFi 掉线检测

WiFi 模式下必须实现掉线重启检测:

 1void wifiOfflineMonitor()
 2{
 3  if (Blinker.connect()) {
 4    offline_millis = 0;
 5    offline_flag = false;
 6  }
 7  else if (!Blinker.connect() && millis() > 180000) {
 8    offline_flag = true;
 9  }
10  
11  if (millis() > 180000 && offline_millis && millis() - offline_millis >= 180000) {
12    ESP.restart();  // 掉线超三分钟重启
13  }
14}

loop() 中调用:

1void loop()
2{
3  Blinker.run();
4  wifiOfflineMonitor();
5}

调试与日志

1void setup()
2{
3  Serial.begin(115200);
4  BLINKER_DEBUG.stream(Serial);     // 调试信息输出到串口
5  BLINKER_DEBUG.debugAll();         // 开启所有调试信息
6  BLINKER_LOG("版本信息");           // 打印日志
7}

常见错误排查

错误 原因 解决
MQTT NOT ALIVE OR MESSAGE LIMIT print 放在 loop() 中 移到心跳包回调或按钮回调
按钮状态不更新 APP 按钮类型与代码不匹配 保留五种状态处理
滑块拖动不灵敏 回调里调用了 print 滑块 print 只放心跳包
WiFi 连不上 非 2.4GHz / 密码错误 检查频段和密码
授权码错误 引号/空格问题 从点灯 APP 复制

ESP32 Web 配网

ESP32_Blinker_NET 是一个完整的 Web 配网示例项目,支持通过网页配置 WiFi 和 Blinker 授权码。

工作流程

  1. 开机读取 EEPROM 中的 WiFi 配置
  2. 有配置则尝试连接,无配置则进入配网模式
  3. 手机连接热点 ESP32_Config,访问 192.168.4.1
  4. 在 Web 页面选择 WiFi、输入密码和授权码
  5. 保存后 ESP32 重启,自动连接

核心代码

 1WIFIConnect wifiManager("ESP32_Config");
 2
 3void setup() {
 4    Serial.begin(115200);
 5    wifiManager.begin();
 6    if (wifiManager.isConnected()) {
 7        Blinker.begin(
 8            wifiManager.getAuth().c_str(),
 9            wifiManager.getSSID().c_str(), ""
10        );
11    }
12}
13
14void loop() {
15    wifiManager.loop();
16    if (wifiManager.isConnected()) Blinker.run();
17}

完整模板代码

以下是一个包含按钮、滑块、数值、文本、数据存储、心跳包、APP弹窗七大功能的完整模板:

 1#define NOTE "Blinker 完整模板"
 2
 3#define WIFIMODE
 4
 5#if defined(WIFIMODE)
 6    #define BLINKER_WIFI
 7#endif
 8
 9#include <Blinker.h>
10
11char ssid[] = "WiFi名称";
12char pswd[] = "WiFi密码";
13char auth[] = "授权码";
14
15#define RELAYPIN_1 2
16bool b1_state = false;
17int s1_value = 0;
18
19BlinkerButton Button1("b1");
20BlinkerSlider Slider1("s1");
21BlinkerNumber NUM1("abcd");
22BlinkerText Text1("1234");
23
24void button1_callback(const String& state)
25{
26  if (state == "tap")      { b1_state = !b1_state; }
27  else if (state == "on")  { b1_state = true; }
28  else if (state == "off") { b1_state = false; }
29  else if (state == "press")   { b1_state = true; }
30  else if (state == "pressup") { b1_state = false; }
31  Button1.print(b1_state ? "on" : "off");
32  digitalWrite(RELAYPIN_1, !b1_state);
33}
34
35void slider1_callback(int32_t value) { s1_value = value; }
36
37void heartbeat()
38{
39  Button1.print(b1_state ? "on" : "off");
40  Slider1.print(s1_value);
41  NUM1.print(100);
42  Text1.print("Hello Blinker");
43  Blinker.notify("页面数据已刷新");
44}
45
46void dataStorage() { Blinker.dataStorage("data1", random(0, 120)); }
47
48void setup()
49{
50  Serial.begin(115200);
51  BLINKER_DEBUG.stream(Serial);
52  BLINKER_DEBUG.debugAll();
53
54  pinMode(RELAYPIN_1, OUTPUT);
55  Blinker.begin(auth, ssid, pswd);
56
57  Button1.attach(button1_callback);
58  Slider1.attach(slider1_callback);
59  Blinker.attachDataStorage(dataStorage);
60  Blinker.attachHeartbeat(heartbeat);
61}
62
63void loop() { Blinker.run(); }

总结

Blinker 以其简洁的 API、丰富的组件和跨平台支持,极大降低了物联网开发门槛。掌握以下核心要点即可快速上手:

  1. 宏定义在前,头文件在后 — 通信模式决定编译路径
  2. 组件声明在回调前 — 否则绑定失败
  3. print 不放 loop() — 否则触发 MQTT 限流
  4. 滑块回调不 print — 否则拖不动
  5. 按钮保留五种状态 — 防止 APP 模式不匹配
  6. WiFi 掉线要检测 — 三分钟无响应自动重启

遵循这些规范,你就能用 Blinker 快速搭建出稳定可靠的物联网应用。