从另一个角度去解读Blinker,剖析精简源码,学习开源精神,菜鸟哥还是忍不住对它下手了

授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力。希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石。。。

快速导航

重点说一下,麻烦三连点赞,你的点赞是博主创作的前进动力

1、解读起因

经常有粉丝朋友问我:

  • 请问Blinker怎么开发?
  • Blinker的这个错误怎么解决?
  • Blinker找不到库怎么办?

  • 在这里插入图片描述
    所以,我还是通读了一下官方文档
  • 点灯科技Blinker

以及翻阅了一下 Arduino Blinker的源码库(设备端)

以及可能以后会翻阅的app源码(暂没看懂)

首先声明一下:

  • 针对对象:初学者
  • 博主不会手把手教你如何写Blinker的代码,官方文档其实已经讲解非常详细
  • 我的目的:抛砖引玉,从更高的角度去解读Blinker学习Blinker的设计思想。学习Blinker事半功倍。

2、解读点

博主以我最熟悉的Arduino ESP8266开发作为一个全局引入点,带领大家如何去解读Blinker的核心思想。

至于Arduino ESP8266的开发知识,这里不做详解,需要的同学麻烦去翻阅博主的8266博客专栏:

2.1 解读硬性要求

  • 必须下载Blinker Arduino库的源码,博主会加入不少注释
  • 必须打开官方文档(博主会时不时引入官方文档链接)
  • 必须打开IDE去验证代码,保证精简代码不会报错

3、解读过程

下手细节包括几个方面:

  • Blinker的产品理念
  • Blinker的组合套路
  • Blinker的实现细节

3.1 解读理念

3.1.1 官方说明

blinker是一个物联网接入方案,旨在让大家可以轻松畅快地DIY物联网设备。

  • 其由服务器端、app端、设备端组成,可以部署到几乎所有物联网平台。
  • app端支持ios、android
  • 设备端可以使用蓝牙、WiFi、NBiot/GPRS,可以应对大多数物联网场景需求。
  • 通过界面布局器,用户可自己拖拽布局设备控制界面,自由打造你的物联网设备

在这里插入图片描述

而从我去阅读官方文档以及库源码,我感觉最惊艳的一点就是:

  • 开发人员帮我们在底层对接了诸多硬件的代码实现,初学者只需要根据继续的需要引入对应的模块,然后调用一下Blinker的一些简单方法,便可实现以前需要写一大堆代码去实现的功能(说白了就是人家底层帮我们包装了一层,我们只需要简单对接api即可,提高了初学者的成就感)。

这里博主也简单画了一个图,让初学者能够简单理解一下:

  • 普通开发模式
    在这里插入图片描述
    这里分为底层核心库以及用户层代码。用户层代码,初学者需要不断针对性去对接底层核心库(基础代码),同时还需要关注业务代码的编写。对于初学者来说,还是比较吃力的。

  • Blinker开发模式
    在这里插入图片描述
    在原来基础上,Blinker封装了硬件细节,统一对外调用暴露的调用方法都叫Blinker(Blinker可能指8266、esp32、ble蓝牙等等,认真看,后面从源码层面去讲解为何能做到这点)。初学者只需要根据它提供的api去开发,便可快速上手物联网接入。

3.2 解读组合方式

在上面我们说了,在Blinker中任意的开发流程都以Blinker作为统一调用入口,那么初学者就会有一个疑问?

Blinker层是如何感知我是蓝牙还是WiFi又或者其他设备呢?

Blinker虽然为我们封装了很多技术细节,但是它肯定无法自动感知我们想要做什么。

作为开发者必须显式明确地告诉它我们的硬件开发方式以及需要的模块功能。

因此,Blinker提出的解决方案是 通过具体的编译宏定义来告诉Blinker应该集成哪些功能模块
在引入Blinker库之前,预先进行宏定义。

举个例子,当我们需要用到Ble开发的时候,使用到 宏定义 BLINKER_BLE

#define BLINKER_PRINT Serial
#define BLINKER_BLE

#include <Blinker.h>

// 新建组件对象
BlinkerButton Button1("btn-abc");
BlinkerNumber Number1("num-abc");

int counter = 0;

// 按下按键即会执行该函数
void button1_callback(const String & state) {
    
    
    BLINKER_LOG("get button state: ", state);
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}

// 如果未绑定的组件被触发,则会执行其中内容
void dataRead(const String & data)
{
    
    
    BLINKER_LOG("Blinker readString: ", data);
    counter++;
    Number1.print(counter);
}

void setup() {
    
    
    // 初始化串口
    Serial.begin(115200);

    #if defined(BLINKER_PRINT)
        BLINKER_DEBUG.stream(BLINKER_PRINT);
    #endif

    // 初始化有LED的IO
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);
    // 初始化blinker
    Blinker.begin();
    Blinker.attachData(dataRead);
    Button1.attach(button1_callback);
}

void loop() {
    
    
    Blinker.run();
}

可以看到两句最重要的代码:

// `首先`,在Blinker.h文件引入之前,预先告诉Blinker我们需要用到Ble的功能
#define BLINKER_BLE
// `然后`,Blinker.h文件就会根据具体的宏定义引入具体功能的头文件(这就是解读Blinker的核心思路)
#include <Blinker.h>
  • 所以到这一步,初学者应该意识到 任意的功能都不是凭空出现的,肯定有一定的前提条件。而Blinker的前提条件就是它定义了一系列的功能宏定义,读者可以根据自己的需求去研读某一个方面,博主这里主要是以ESP8266为案例(思路一样)。

在Blinker中定义了一系列的宏定义,而且宏定义之间允许组合使用(但是组合也是有前提的,一般是以某一个宏定义为基准,然后在基准宏定义之上叠加其他功能,比如WiFi + SmartConfig)

那么,我们有必要去了解一下Blinker提供的宏定义(可能这里总结不全,但是核心思路就是这样),这里博主做了一个简单的脑图:

在这里插入图片描述
那么,稍微简单讲解一下脑图构成。

在Blinker中,从设备角度来看,分为两大类:

  • 基础设备
    包括我们常用的Ble模块、ArduinoESP(8266/32)、ATESP(AT指令的通信方式(选学))

  • 专属设备
    包括NBIOT、GPRS等等

基于我们所选择的对接方式,我们需要声明对应的宏定义。
这里涉及到了N个宏定义,博主做了几个重要的颜色区分。

这里说明一下:

  • 绿色
    表示必选的,一般情况指的是通信方式或者专门的设备
    在这里插入图片描述

  • 橙色
    目前特指 Arduino For ESP8266 或者 ESP32的开发方式。这个配置是通过IDE编译选项中的目标板子去定义的,不需要我们在代码中显式声明。
    在这里插入图片描述

  • 浅蓝色
    表示在必选功能之上附加功能,比如WiFi模式下的SmartConfig
    在这里插入图片描述

注意名词说明:

ArduinoESP,特指Arduino For ESP8266 or Arduino For ESP32
ArduinoOther,特指除ESP8266或者ESP32之外的其他Arduino板子,比如Mega等。

3.2.1 绿色 —— 必选宏

必选,不是说选择所有,而是选择其中之一。

BLINKER_BLE —— ble蓝牙通信
  • ble蓝牙通信(ESP32、Ble蓝牙模块)
  • 不支持蓝牙2.0模块(HC05 / HC06 / BT06 /JDY30)
BLINKER_WIFI、BLINKER_MQTT —— WiFi通信
  • 两者都统称为 BLINKER_MQTT,也就是后续的项目直接使用 BLINKER_MQTT,废弃BLINKER_WIFI宏吧
  • Arduino For ESP8266 – 2.7.4 或以上release版本的 ESP8266 package
  • Arduino For ESP32 – 1.0.4 及以上版本的 ESP32 package
  • 对应开发文档:https://diandeng.tech/doc/arduino-support
BLINKER_PRO —— 略
BLINKER_PRO_ESP、BLINKER_WIFI_AUTO—— 略
BLINKER_AT_MQTT—— AT开发方式
BLINKER_WIFI_GATEWAY
BLINKER_WIFI_SUBDEVICE
BLINKER_NBIOT_SIM7020
BLINKER_NBIOT_SIM7000
BLINKER_PRO_SIM7020
BLINKER_GPRS_AIR202
BLINKER_PRO_AIR202
BLINKER_LOWPOWER_AIR202
BLINKER_QRCODE_NBIOT_SIM7020
BLINKER_QRCODE_NBIOT_SIM7000

3.2.2 浅蓝色—— 附加宏

记住,可选宏必须依赖于必选宏之上

先有必选宏,再有附加宏,它们的依赖关系麻烦去查阅脑图

BLINKER_APCONFIG —— webSocket 局域网配网

这里的AP配网并不是走webserver配网而是走websocket局域网配网方式。

BLINKER_ESP_SMARTCONFIG —— smartconfig配网
BLINKER_MIOT_LIGHT—— 小米小爱
BLINKER_MIOT_OUTLET—— 小米小爱
BLINKER_MIOT_MULTI_OUTLET—— 小米小爱
BLINKER_MIOT_SENSOR —— 小米小爱
BLINKER_DUEROS_LIGHT —— 百度小度
BLINKER_DUEROS_OUTLET —— 百度小度
BLINKER_DUEROS_MULTI_OUTLET —— 百度小度
BLINKER_DUEROS_SENSOR —— 百度小度
BLINKER_ALIGENIE_LIGHT —— 天猫精灵
BLINKER_ALIGENIE_OUTLET —— 天猫精灵
BLINKER_ALIGENIE_MULTI_OUTLET —— 天猫精灵
BLINKER_ALIGENIE_SENSOR —— 天猫精灵

3.3 解读源码细节

建议读者找一个代码工具导入Blinker库,优先推荐VScode或者IntellJ
在这里插入图片描述

  • 全局入口文件
    整个库的入口文件,在这里会导入我们所需要的业务入口文件(按需接入对应的硬件模块

  • 业务入口文件
    真正实现硬件模块对接代码的地方。

博主查阅了Blinker.h文件,通过自己的理解以及官方文档,给出以下源码解析,同时也希望读者参考我上面提供的百度脑图去阅读。

/**
 对应开发文档: https://diandeng.tech/doc/arduino-support?keyword=BLINKER_PRO

 目前Blinker设备包括两大类:
 - 普通设备(BLINKER_BLE 和 BLINKER_WIFI)
   ---- 初学者玩好
 - 专属设备 (PRO)
   ---- https://diandeng.tech/doc/prodevice
   ---- 专属设备是开发者开发后,可用于生产销售的设备(成熟产品,非个人DIY),初学者暂时不用考虑)

 普通设备Blinker开发顺序:
 1、选择通信接入方式
    --- Bluetooth4.x (BLE)
    --- WiFi
 2、选择该通信方式下的模块
    --- ESP8266、ESP32

 专属设备Blinker开发顺序:
 1、直接选择对应的专属宏
 **/

#ifndef BLINKER_H
#define BLINKER_H

// BLINKER_BLE(ble蓝牙通信)
// 注意点:
// --- 不支持蓝牙2.0模块(HC05 / HC06 / BT06 /JDY30)
#if defined(BLINKER_BLE)

    // BLINKER_ALIGENIE_LIGHT
    // BLINKER_ALIGENIE_OUTLET
    // BLINKER_ALIGENIE_SWITCH
    // BLINKER_ALIGENIE_SENSOR
    // 属于天猫精灵的专用宏,所以不要乱组合(https://diandeng.tech/doc/tmallgenie)
    #if defined(BLINKER_ALIGENIE_LIGHT) || defined(BLINKER_ALIGENIE_OUTLET) || \
        defined(BLINKER_ALIGENIE_SWITCH)|| defined(BLINKER_ALIGENIE_SENSOR)
        #error This code is intended to run on the BLINKER_MQTT mode! Please check your mode setting.    
    #endif

    // BLINKER_DUEROS_LIGHT
    // BLINKER_DUEROS_OUTLET
    // BLINKER_DUEROS_SWITCH
    // BLINKER_DUEROS_SENSOR
    // 属于百度小度的专用宏,所以不要乱组合(https://diandeng.tech/doc/dueros)
    #if defined(BLINKER_DUEROS_LIGHT) || defined(BLINKER_DUEROS_OUTLET) || \
        defined(BLINKER_DUEROS_SWITCH)|| defined(BLINKER_DUEROS_SENSOR)
        #error This code is intended to run on the BLINKER_MQTT mode! Please check your mode setting.
    #endif

    #if defined(ESP32)
        // ESP32下的Ble功能模块,会根据ArduinoIDE编译选项的目标板子来选择
        #include "BlinkerESP32BLE.h"
        BlinkerESP32BLE     Blinker;
    #else
        // 普通Ble模块
        #include "BlinkerSerialBLE.h"
        BlinkerSerialBLE    Blinker;
    #endif

// BLINKER_WIFI/BLINKER_MQTT(WiFi通信)
#elif defined(BLINKER_WIFI) || defined(BLINKER_MQTT)

    // 这句话宏的意思就是两者都统称为 BLINKER_MQTT,也就是后续的项目直接使用 BLINKER_MQTT,废弃BLINKER_WIFI宏吧。。。。。
    #if defined(BLINKER_WIFI)
        #undef BLINKER_WIFI
        #define BLINKER_MQTT
    #endif

    #include "BlinkerAssistant.h"

    // Arduino For ESP8266 -- 2.7.4 或以上release版本的 ESP8266 package
    // Arduino For ESP32 -- 1.0.4 及以上版本的 ESP32 package
    // 对应开发文档:https://diandeng.tech/doc/arduino-support
    #if (defined(ESP8266) || defined(ESP32)) && !defined(BLINKER_MQTT_AT)
        #include "BlinkerESPMQTT.h"
        BlinkerESPMQTT      Blinker;     
    #else
        #define BLINKER_ESP_AT
        #define BLINKER_MQTT_AT
        #undef BLINKER_MQTT
        #include "BlinkerSerialESPMQTT.h"

        BlinkerSerialESPMQTT      Blinker;  
    #endif

// 专属设备 初学者暂时不用考虑
#elif defined(BLINKER_PRO)
    #if defined(BLINKER_ALIGENIE_LIGHT) || defined(BLINKER_ALIGENIE_OUTLET) || \
        defined(BLINKER_ALIGENIE_SWITCH)|| defined(BLINKER_ALIGENIE_SENSOR)
        #error This code is intended to run on the BLINKER_MQTT mode! Please check your mode setting.
    #endif    

    #if defined(BLINKER_DUEROS_LIGHT) || defined(BLINKER_DUEROS_OUTLET) || \
        defined(BLINKER_DUEROS_SWITCH)|| defined(BLINKER_DUEROS_SENSOR)
        #error This code is intended to run on the BLINKER_MQTT mode! Please check your mode setting.
    #endif

    #define BLINKER_ALIGENIE
    #define BLINKER_DUEROS

    #ifndef BLINKER_ESP_SMARTCONFIG
        #ifndef BLINKER_APCONFIG
            #define BLINKER_ESP_SMARTCONFIG
        #endif
    #endif

    #if defined(ESP8266) || defined(ESP32)
        #include "BlinkerESPPRO.h"
        
        BlinkerESPPRO       Blinker; 
    #else
        #error This code is intended to run on the ESP8266/ESP32 platform! Please check your Tools->Board setting.
    #endif

// BLINKER_PRO_ESP / BLINKER_WIFI_AUTO (开启smartconfig配网)
// 注意点:
// ----- 这两个宏用于专属设备
// ----- 这两个宏专用于 ESP8266或者ESP32平台
#elif defined(BLINKER_PRO_ESP) || defined(BLINKER_WIFI_AUTO)
    #include "BlinkerAssistant.h"
    // 如果宏定义为 BLINKER_WIFI_AUTO 追加 BLINKER_PRO_ESP宏定义
    // 目的:复合配网模式
    #if defined(BLINKER_WIFI_AUTO)
        #define BLINKER_PRO_ESP
    #endif

    #if defined(ESP8266) || defined(ESP32)
        #include "BlinkerESPPROESP.h"
        BlinkerESPPROESP    Blinker; 
    #else
        #error This code is intended to run on the ESP8266/ESP32 platform! Please check your Tools->Board setting.
    #endif

// AT For 8266
// 对应开发文档:
// --- https://diandeng.tech/doc/getting-start-wifi-at
// --- https://diandeng.tech/doc/at-mode-support)
#elif defined(BLINKER_AT_MQTT)
    #define BLINKER_ESP_AT
    #if defined(ESP8266) || defined(ESP32)
        #include "BlinkerESPMQTTAT.h"
        BlinkerESPMQTTAT    Blinker; 
    #else
        #error This code is intended to run on the ESP8266/ESP32 platform! Please check your Tools->Board setting.
    #endif

#elif defined(BLINKER_WIFI_GATEWAY)
    #include "BlinkerAssistant.h"
    #if defined(ESP8266) || defined(ESP32)
        #include "BlinkerESPGateway.h"
        BlinkerESPGateway    Blinker; 
    #else
        #error This code is intended to run on the ESP8266/ESP32 platform! Please check your Tools->Board setting.
    #endif

#elif defined(BLINKER_WIFI_SUBDEVICE)
    #include "BlinkerAssistant.h"
    #if defined(ESP8266) || defined(ESP32)
        #include "BlinkerESPSubDevice.h"
        BlinkerESPSubDevice     Blinker;
    #else
        #error This code is intended to run on the ESP8266/ESP32 platform! Please check your Tools->Board setting.
    #endif

// 专属设备:NBIoT AT模块 NB73
#elif defined(BLINKER_NBIOT_WH)
    #ifndef BLINKER_NB73_NBIOT
    #define BLINKER_NB73_NBIOT
    #endif
    #include "BlinkerSerialWHNBIoT.h"
    BlinkerSerialWHNBIoT    Blinker;

// 专属设备:NBIoT AT模块 SIM7020C
#elif defined(BLINKER_NBIOT_SIM7020)
    #include "BlinkerSerialSIMNBIoT.h"
    BlinkerSerialSIMNBIoT   Blinker;

// 专属设备:NBIoT AT模块 SIM7000
#elif defined(BLINKER_NBIOT_SIM7000)
    #ifndef BLINKER_WITHOUT_SSL
        #define BLINKER_WITHOUT_SSL
    #endif
    #include "BlinkerSerialSIM7000NBIoT.h"
    BlinkerSerialSIM7000NBIoT   Blinker;

// 专属设备:SIM7020
#elif defined(BLINKER_PRO_SIM7020)
    #include "BlinkerSIMPRO.h"
    BlinkerSIMPRO   Blinker;

// 专属设备: GPRS AT模块 AIR202
#elif defined(BLINKER_GPRS_AIR202)
    #include "BlinkerSerialLUATGPRS.h"
    BlinkerSerialLUATGPRS   Blinker;

// 专属设备
#elif defined(BLINKER_PRO_AIR202)
    #include "BlinkerLUATPRO.h"
    BlinkerLUATPRO  Blinker;

// 专属设备
#elif defined(BLINKER_LOWPOWER_AIR202)
    #include "BlinkerLowPowerGPRS.h"
    BlinkerLowPowerGPRS Blinker;

// 专属设备
#elif defined(BLINKER_QRCODE_NBIOT_SIM7020)
    #include "BlinkerQRCodeSIMNBIOT.h"
    BlinkerQRCodeSerialSIMNBIoT Blinker;

// 专属设备
#elif defined(BLINKER_QRCODE_NBIOT_SIM7000)
    #ifndef BLINKER_WITHOUT_SSL
        #define BLINKER_WITHOUT_SSL
    #endif
    #include "BlinkerQRCodeSIM7000NBIOT.h"
    BlinkerQRCodeSerialSIM7000NBIoT Blinker;

//
#elif defined(BLINKER_HTTP)
    #include "BlinkerESPHTTP.h"
    BlinkerESPHTTP      Blinker;   

#else
    #error Please set a mode BLINKER_BLE/BLINKER_WIFI/BLINKER_MQTT ! Please check your mode setting.

#endif

// 导入组件库
#include "BlinkerWidgets.h"

// ESP多任务(ESP8266/ESP32 中启用多任务)
#if defined(BLINKER_ESP_TASK)
#if defined(ESP8266)
    // 目前ESP8266多任务支持还有点问题, 暂不支持使用
    #error ESP8266 TASK NOT SUPPORT!
// #if defined(ESP32)
#elif defined(ESP32)
    #include <freertos/FreeRTOS.h>
    #include <freertos/task.h>
    #include <Arduino.h>

    // #if CONFIG_AUTOSTART_ARDUINO

    #if CONFIG_FREERTOS_UNICORE
    #define ARDUINO_RUNNING_CORE 0
    #else
    #define ARDUINO_RUNNING_CORE 1
    #endif

    void blinkerLoopTask(void *pvParameters)
    {
    
    
        for(;;) {
    
    
            Blinker.run();
            vTaskDelay(1);
        }
    }

    extern "C" void BLINKER_TAST_INIT()
    {
    
    
        // initArduino();
        // #if defined(BLINKER_MQTT)
        //     Blinker.beginMQTT();
        // #endif
        xTaskCreatePinnedToCore(blinkerLoopTask, 
                                "blinkerLoopTask", 
                                8192, 
                                NULL, 
                                3, 
                                NULL, 
                                ARDUINO_RUNNING_CORE);
    }

    // #endif
#else
    #error This code is intended to run on the ESP8266/ESP32 platform! Please check your Tools->Board setting.
#endif

#endif

#ifndef LED_BUILTIN
    #if defined(ESP8266) || defined(ESP32)
        #define LED_BUILTIN 2
    #else
        #define LED_BUILTIN 13
    #endif
#endif

#endif

对于初学者,我们一般更针对蓝牙或者WiFi模块,所以我们可以做两方面的精简:

  • 剔除专属设备依赖
  • 剔除ESP多任务

这样整个Blinker可以更加精简为:

/**
 对应开发文档: https://diandeng.tech/doc/arduino-support?keyword=BLINKER_PRO

 目前Blinker设备包括两大类:
 - 普通设备(BLINKER_BLE 和 BLINKER_WIFI)
   ---- 初学者玩好
 - 专属设备 (PRO)
   ---- https://diandeng.tech/doc/prodevice
   ---- 专属设备是开发者开发后,可用于生产销售的设备(成熟产品,非个人DIY),初学者暂时不用考虑)

 普通设备Blinker开发顺序:
 1、选择通信接入方式
    --- Bluetooth4.x (BLE)
    --- WiFi
 2、选择该通信方式下的模块
    --- ESP8266、ESP32

 专属设备Blinker开发顺序:
 1、直接选择对应的专属宏
 **/

#ifndef BLINKER_H
#define BLINKER_H

// BLINKER_BLE(ble蓝牙通信)
// 注意点:
// --- 不支持蓝牙2.0模块(HC05 / HC06 / BT06 /JDY30)
#if defined(BLINKER_BLE)

    // BLINKER_ALIGENIE_LIGHT
    // BLINKER_ALIGENIE_OUTLET
    // BLINKER_ALIGENIE_SWITCH
    // BLINKER_ALIGENIE_SENSOR
    // 属于天猫精灵的专用宏,所以不要乱组合(https://diandeng.tech/doc/tmallgenie)
    #if defined(BLINKER_ALIGENIE_LIGHT) || defined(BLINKER_ALIGENIE_OUTLET) || \
        defined(BLINKER_ALIGENIE_SWITCH)|| defined(BLINKER_ALIGENIE_SENSOR)
        #error This code is intended to run on the BLINKER_MQTT mode! Please check your mode setting.    
    #endif

    // BLINKER_DUEROS_LIGHT
    // BLINKER_DUEROS_OUTLET
    // BLINKER_DUEROS_SWITCH
    // BLINKER_DUEROS_SENSOR
    // 属于百度小度的专用宏,所以不要乱组合(https://diandeng.tech/doc/dueros)
    #if defined(BLINKER_DUEROS_LIGHT) || defined(BLINKER_DUEROS_OUTLET) || \
        defined(BLINKER_DUEROS_SWITCH)|| defined(BLINKER_DUEROS_SENSOR)
        #error This code is intended to run on the BLINKER_MQTT mode! Please check your mode setting.
    #endif

    #if defined(ESP32)
        // ESP32下的Ble功能模块,会根据ArduinoIDE编译选项的目标板子来选择
        #include "BlinkerESP32BLE.h"
        BlinkerESP32BLE     Blinker;
    #else
        // 普通Ble模块
        #include "BlinkerSerialBLE.h"
        BlinkerSerialBLE    Blinker;
    #endif

// BLINKER_WIFI/BLINKER_MQTT(WiFi通信)
#elif defined(BLINKER_WIFI) || defined(BLINKER_MQTT)

    // 这句话宏的意思就是两者都统称为 BLINKER_MQTT,也就是后续的项目直接使用 BLINKER_MQTT,废弃BLINKER_WIFI宏吧。。。。。
    #if defined(BLINKER_WIFI)
        #undef BLINKER_WIFI
        #define BLINKER_MQTT
    #endif

    #include "BlinkerAssistant.h"

    // Arduino For ESP8266 -- 2.7.4 或以上release版本的 ESP8266 package
    // Arduino For ESP32 -- 1.0.4 及以上版本的 ESP32 package
    // 对应开发文档:https://diandeng.tech/doc/arduino-support
    #if (defined(ESP8266) || defined(ESP32)) && !defined(BLINKER_MQTT_AT)
        #include "BlinkerESPMQTT.h"
        BlinkerESPMQTT      Blinker;     
    #else
        #define BLINKER_ESP_AT
        #define BLINKER_MQTT_AT
        #undef BLINKER_MQTT
        #include "BlinkerSerialESPMQTT.h"

        BlinkerSerialESPMQTT      Blinker;  
    #endif

// AT For 8266
// 对应开发文档:
// --- https://diandeng.tech/doc/getting-start-wifi-at
 // --- https://diandeng.tech/doc/at-mode-support)
#elif defined(BLINKER_AT_MQTT)
    #define BLINKER_ESP_AT
    #if defined(ESP8266) || defined(ESP32)
        #include "BlinkerESPMQTTAT.h"
        BlinkerESPMQTTAT    Blinker; 
    #else
        #error This code is intended to run on the ESP8266/ESP32 platform! Please check your Tools->Board setting.
    #endif

#elif defined(BLINKER_HTTP)
    #include "BlinkerESPHTTP.h"
    BlinkerESPHTTP      Blinker;   

#else
    #error Please set a mode BLINKER_BLE/BLINKER_WIFI/BLINKER_MQTT ! Please check your mode setting.

#endif

// 导入组件库
#include "BlinkerWidgets.h"

// 定义点灯引脚
#ifndef LED_BUILTIN
    #if defined(ESP8266) || defined(ESP32)
        #define LED_BUILTIN 2
    #else
        #define LED_BUILTIN 13
    #endif
#endif

#endif

那么肯定有疑问?

Blinker是如何和我们本地硬件交互在一起呢?说白了就是App如何和硬件打交道?

在Blinker.h文件中,最后有一句非常重要的头文件引入:

// 导入组件库
#include "BlinkerWidgets.h"

这里就是引入了App与设备之间交互的关键点。
App作为可视化虚拟设备,而对应的物理硬件设备就是BlinkerWidget库里面定义的组件,通过这些组件才能打通和App的视觉交互。

它们之间的关联关键点就是name属性。每个name属性都需要是唯一的,然后在Blinker App也有一个对应name的控件与之关联。

在这里插入图片描述
这里涵盖了大多数的功能模块,比如滑动条、颜色选择器、开关、字符串显示等等。

具体每个控件支持的功能请查阅官方文档,里面都写得比较详细,缺乏的文档就可以直接看看源码去学习吧:

4、重新认识Blinker

从上面的讲解来说,我们可以概括正常Blinker开发流程是这样的:

  • 第一步
    选择对应的通信方式或者直接选择专属设备

  • 第二步(可选)
    选择对应通信方式下的附加技能

  • 第三步
    选择对应的操作组件(widget)

4.1 使用Arduino & 蓝牙接入

说明:https://diandeng.tech/doc/arduino-support

  • 第一步
    选择 BLINKER_BLE

  • 第二步 略

  • 第三步 选择 BlinkerButtonBlinkerNumber 控件

代码如下:

#define BLINKER_PRINT Serial
#define BLINKER_BLE

#include <Blinker.h>

// 新建组件对象
BlinkerButton Button1("btn-abc");
BlinkerNumber Number1("num-abc");

int counter = 0;

// 按下按键即会执行该函数
void button1_callback(const String & state) {
    
    
    BLINKER_LOG("get button state: ", state);
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}

// 如果未绑定的组件被触发,则会执行其中内容
void dataRead(const String & data)
{
    
    
    BLINKER_LOG("Blinker readString: ", data);
    counter++;
    Number1.print(counter);
}

void setup() {
    
    
    // 初始化串口
    Serial.begin(115200);

    #if defined(BLINKER_PRINT)
        BLINKER_DEBUG.stream(BLINKER_PRINT);
    #endif

    // 初始化有LED的IO
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);
    // 初始化blinker
    Blinker.begin();
    Blinker.attachData(dataRead);
    Button1.attach(button1_callback);
}

void loop() {
    
    
    Blinker.run();
}

4.2 使用esp8266 & WiFi接入

说明:https://diandeng.tech/doc/getting-start-8266

  • 第一步
    选择 BLINKER_WIFI

  • 第二步 略

  • 第三步 选择 BlinkerButtonBlinkerNumber 控件

#define BLINKER_PRINT Serial
#define BLINKER_WIFI

#include <Blinker.h>

char auth[] = "Your Device Secret Key";
char ssid[] = "Your WiFi network SSID or name";
char pswd[] = "Your WiFi network WPA password or WEP key";

// 新建组件对象
BlinkerButton Button1("btn-abc");
BlinkerNumber Number1("num-abc");

int counter = 0;

// 按下按键即会执行该函数
void button1_callback(const String & state) {
    
    
    BLINKER_LOG("get button state: ", state);
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}

// 如果未绑定的组件被触发,则会执行其中内容
void dataRead(const String & data)
{
    
    
    BLINKER_LOG("Blinker readString: ", data);
    counter++;
    Number1.print(counter);
}

void setup() {
    
    
    // 初始化串口
    Serial.begin(115200);

    #if defined(BLINKER_PRINT)
        BLINKER_DEBUG.stream(BLINKER_PRINT);
    #endif

    // 初始化有LED的IO
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);
    // 初始化blinker
    Blinker.begin(auth, ssid, pswd);
    Blinker.attachData(dataRead);
    Button1.attach(button1_callback);
}

void loop() {
    
    
    Blinker.run();
}

4.3 使用esp32 & 蓝牙接入

说明:https://diandeng.tech/doc/arduino-support

  • 第一步
    选择 BLINKER_BLE

  • 第二步 略

  • 第三步 选择 BlinkerButtonBlinkerNumber 控件

#define BLINKER_PRINT Serial
#define BLINKER_BLE

#include <Blinker.h>

// 新建组件对象
BlinkerButton Button1("btn-abc");
BlinkerNumber Number1("num-abc");

int counter = 0;

// 按下按键即会执行该函数
void button1_callback(const String & state) {
    
    
    BLINKER_LOG("get button state: ", state);
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}

// 如果未绑定的组件被触发,则会执行其中内容
void dataRead(const String & data)
{
    
    
    BLINKER_LOG("Blinker readString: ", data);
    counter++;
    Number1.print(counter);
}

void setup() {
    
    
    // 初始化串口
    Serial.begin(115200);

    #if defined(BLINKER_PRINT)
        BLINKER_DEBUG.stream(BLINKER_PRINT);
    #endif

    // 初始化有LED的IO
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);
    // 初始化blinker
    Blinker.begin();
    Blinker.attachData(dataRead);
    Button1.attach(button1_callback);
}

void loop() {
    
    
    Blinker.run();
}

4.4 NB-IoT支持

  • 第一步
    选择 BLINKER_NBIOT_SIM7020

  • 第二步 略

  • 第三步 选择 BlinkerButtonBlinkerNumber 控件

#define BLINKER_NBIOT_SIM7020

#include <Blinker.h>

char auth[] = "Your Device Secret Key";

// 新建组件对象
BlinkerButton Button1("btn-abc");
BlinkerNumber Number1("num-abc");

int counter = 0;

// 按下按键即会执行该函数
void button1_callback(const String & state) {
    
    
    BLINKER_LOG("get button state: ", state);
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}

// 如果未绑定的组件被触发,则会执行其中内容
void dataRead(const String & data)
{
    
    
    BLINKER_LOG("Blinker readString: ", data);
    counter++;
    Number1.print(counter);
}

void setup() {
    
    
    // 初始化串口
    Serial.begin(115200);
    BLINKER_DEBUG.stream(Serial);

    // 初始化有LED的IO
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);
    // 初始化blinker
    Blinker.begin(auth, D6, D7, 9600);
    Blinker.attachData(dataRead);
    Button1.attach(button1_callback);
}

void loop() {
    
    
    Blinker.run();
}

猜你喜欢

转载自blog.csdn.net/dpjcn1990/article/details/110704782