65.9K
CodeProject 正在变化。 阅读更多。
Home

DIY 蓝牙 LE 到 WiFi 网桥

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2024 年 3 月 5 日

CPOL

14分钟阅读

viewsIcon

15639

蓝牙 LE 扫描仪按计划从一个或多个 BLE 服务器收集数据并将其转发到 WiFi。

引言

蓝牙低功耗 (BLE) 是一种 2.4 GHz 无线通信技术,支持设备之间的本地域通信。它非常适合低功耗通信,但其通信范围仅限于大约 10 米——尽管可以通过增加功率和更复杂的天线系统来扩展。

远程安装可能在家庭或工业应用中有多个 BLE 设备用于传感数据。本项目将允许按预定时间表查询来自 BLE 设备的信息,并通过 WiFi 网络链路将其转发到远程服务器。

例如,温度、湿度、门窗开启、警报状态、漏水、燃气泄漏、用电量、用水量等都可以通过 BLE 设备进行传感。BLE-WiFi 网桥能够从多个设备收集这些数据,并将其转发到服务器等网络设备进行存储和/或进一步处理。

BLE WiFi 网桥概述

该网桥使用 ESP32 平台实现——一个小型、低成本的嵌入式平台,支持 BLE 和 WiFi 操作。该应用程序不需要开发板外部的任何硬件。

主要功能是可配置的 BLE 扫描仪,允许您定义多达 100 个不同的服务器特征(characteristics),以及每个特征的读取频率。在运行中,定义的服务器特征会被读取并移动到已连接 WiFi 的服务器。(参见之前的关于 IoT Edge Hub 的文章。)

Block Diagram

BLE 服务器和客户端

蓝牙通信规范非常广泛,如果打印出来可能会有一本书那么厚。在本篇文章中,我们从一个相对简化的层面开始——所以请准备好!

在本应用中,我们将 BLE 世界视为有两种设备——服务器 (SERVERS) 和客户端 (CLIENTS)。BLE 服务器托管某种测量和/或控制功能,这些功能通过一个或多个称为“特征”(Characteristics)的数据项来呈现——这些数据项是 BLE 客户端可以读取或写入的数据块。

特征的一些例子可能包括温度、湿度、继电器控制(开/关)、音量控制、时间、日期、GPS 位置等。

有些特征是“只读”的,有些是“只写”的,有些是“读/写”的。

一个服务器可能只有一个特征,也可能有数百个特征。在服务器内部,特征被组织成称为“服务”(services)的组。单个 BLE 客户端可以拥有一个或多个服务。在某种意义上,服务就像 BLE 服务器的“顶层目录”。在与 BLE 服务器通信时,您可以请求其服务的目录。

在每个服务下有多个特征——每个特征可以被视为一个微小文件——您可以在其中读取或写入一块数据。有些文件是“只读”的,有些是“只写”的,有些是“读/写”的——这取决于服务器如何定义每个特征。

蓝牙低功耗 (BLE) 概述

BLE 在 2.4 GHz 频段定义了 40 个通道用于射频通信。根据条件,数据速率从 125 kbps 到 2 mbps 不等,使用高斯频移键控调制。数据以数据包的形式发送,并通过频率跳变模式发送,以允许多个 BLE 设备共享频谱。提供 128 位 AES 编码的加密选项。

ESP32 SDK 提供了实现 BLE 设备的软件。BLE 由一个本地区域网络组成,该网络使用 BLE 协议 (链接) 通过 2.4 GHz 无线频率进行通信。从软件角度来看,我们需要处理的 BLE 的主要特性是:

  • 端点类型(客户端/服务器)
  • 带有特征的服务

本质上,BLE 服务器允许其他设备连接到它,并可能允许其他设备读取或写入特征。当另一个设备读取一个特征时,它可能是像温度这样的测量值,“提供”给连接的客户端。

当另一个设备写入一个特征时,它可能像打开或关闭继电器来打开或关闭灯一样,“提供”给连接的客户端。

完整的规范大约有 100 厘米厚的打印纸,所以我们不会在这讨论中深入探讨!

特征可能附带一个描述符——一个描述该特征的字符串。例如,一个代表测量温度的特征可能有一个描述符“temperature, F”。

在 BLE 中,一个或多个特征被分组到一个“服务”下。而一个单独的 BLE 服务器可能有一个或多个“服务”。因此,BLE 服务器提供的服务列表就像服务器的顶层目录。特征就像每个服务下的二级目录。

因此,一个希望读取特征的客户端的典型操作将是:

  • 连接到设备并查询其服务——它通过将服务的 UUID 与它正在寻找的服务的 UUID 进行匹配来找到一个服务。
  • 查询该服务下的特征列表——它找到一个或多个特征——每个特征都由一个 UUID 标识。客户端将希望将其正在寻找的特征的 UUID 与服务器提供的列表进行匹配。
  • 使用服务 UUID 和特征 UUID 读取所需特征的值。

现在又有一个话题要讨论了——什么是 UUID?事实证明,BLE 服务和特征都由 UUID 标识。它们使用一个长达 36 位数字的十六进制字符串进行唯一命名,称为 UUID(通用唯一标识符)。这些 UUID 在许多领域(不仅仅是 BLE)都用于需要为宇宙中的某物标记唯一名称的情况。这些可以以多种方式生成,但一种简单的方法是使用这个 特殊的网站

每个服务和每个特征在 BLE 中都必须有自己的 UUID。

现在,有一些服务和特征非常普遍,以至于被分配了相同的特殊 UUID——这些是 BLE 术语宇宙中称为 GATT(Generic Attribute Profile,通用属性配置文件)的一部分。您可以在 这个网站 上查找更多信息。对于这个 BLE 服务器,我们没有使用 GATT——尽管可能存在用于温度和湿度的 GATT。欢迎尝试!

BLE 广播

为了连接到设备,客户端必须知道要连接哪个设备。为了解决这个问题,BLE 定义了一种称为“广播”(advertising)的东西,即活动 BLE 服务器会定期“广播”自己,发送一个特殊的 BLE 无线电数据包。客户端可以监听这些数据包来发现其范围内可能有哪些 BLE 服务器。然后,它可以选择其中一个服务器进行连接。

每个特定的 BLE 设备都分配有一个唯一的数字(不是 UUID——但类似)。这个数字称为 MAC 地址(媒体访问控制)。有关更多信息,请参阅此 网站。基本上,MAC 地址是分配给某个硬件特定实例的 48 位唯一数字。以太网、WiFi 和蓝牙都使用这些 MAC 地址,通常由 6 个十六进制字节组成,用冒号分隔——看起来像这样:05:6c:22:1f:be:3a。每个 BLE 设备都应该附带自己的唯一 MAC 地址。因此,即使我们有 100 个完全相同的服务器——每个服务器都有一个唯一的 MAC 地址,我们可以用它来连接到 100 个相同服务器中的一个。

有一个非常方便的应用程序(我认为是 iPhone 和 Android 版),名为 BT Inspector,可以用来演示这一点。这是一个诊断性的 BLE 客户端,允许手机监听其范围内广播的 BLE 服务器。然后,您可以使用该应用程序尝试连接到服务器并查询其服务和特征。该应用程序还可以读取和写入特征。这是一个很棒的测试设备!

以下是使用 BT Inspector 的一些示例。第一项是扫描广播的 BLE 服务器。按下 **Scan** 按钮,您手机上的应用程序将开始监听广播数据包的 BLE 服务器。当收到这些数据包时,数据将显示在手机屏幕上,如下所示。请注意,此时,这些 BLE 设备尚未“连接”——应用程序只是显示范围内 BLE 服务器在其发送的广播数据包中发送的数据。

Shows BT Inspector scanning for advertising BLE servers

BLE 连接

当客户端通过解码广播数据包识别出特定的 BLE 服务器后,客户端可以尝试与该服务器协商连接。这可能涉及也可能不涉及身份验证过程,具体取决于服务器。在本篇文章中,我们不假设任何服务器设备需要身份验证。

建立连接后,客户端可以向服务器请求其可用服务的列表,并且对于每个服务,客户端可以请求可用特征的列表。

这里有一些 ESP32 代码,可以从客户端查询所有这些数据。您会看到代码尝试连接到服务器,如果成功,它会请求服务列表。然后,对于每个服务,它会向服务器请求与该服务相关的特征列表。这些信息会打印到 ESP32 的串行端口。

//----------------------------------------------------------------------
// Completely explore a server - list all services and all characteristics
//   This will connect to a server by MAC address (serverAddress) and
//   query all of its services. For each service, it will query all
//   of the associated characteristics.

void serverExplorer(BLEClient * pClient, BLEAddress serverAddress)
{
  pClient->connect(serverAddress);
  if (!pClient->isConnected())
  {
    Serial.println("Connection failed");
  }
  else
  {
    Serial.println("Connected");
    std::map<std::string, BLERemoteService*>* services = 
                          pClient->getServices(); // get list of services
  
    Serial.printf("Number of services found: %d\n",services->count);
    
    // print services
    int svcidx = 1;
    for (std::map<std::string, BLERemoteService*>::iterator it = services->begin(); 
         it!=services->end();++it)
    {
      Serial.printf("Service %d\n", svcidx++);
      delay(200);
      std::string svcName = it->first;
      std::string svcSvid = it->second->toString();
      Serial.print(svcName.c_str()); 
      Serial.print("=");
      Serial.println(svcSvid.c_str());
      BLERemoteService* p = it->second;
      BLEUUID svcUUID = p->getUUID();
      //std::string value = p->getValue(p->getUUID());
      //Serial.println(value.c_str());
      // get characteristics
      std::map<std::__cxx11::basic_string<char>, 
      BLERemoteCharacteristic*>* characteristics = p->getCharacteristics();
      for (std::map<std::__cxx11::basic_string<char>, 
           BLERemoteCharacteristic*>::iterator itch = characteristics->begin(); 
           itch != characteristics->end(); ++itch)
      {
        BLERemoteCharacteristic * rc = itch->second;
        BLEUUID charUUID = rc->getUUID();
        std::string cuuid = charUUID.toString();
        std::string val = p->getValue(charUUID);
        Serial.print('['); Serial.print(cuuid.c_str()); Serial.print("]="); 
                           Serial.println(val.c_str());
      }
    }
    
    pClient->disconnect();
  }
}

硬件架构

由于此应用程序仅使用 ESP32 开发板的内置硬件,因此大多数 ESP32(首选 WROOMWROVER)都可以工作。该应用程序会闪烁板载 LED,在不同的开发板上,LED 可能连接到不同的 GPIO 引脚。在源代码中,LED 被定义为 GPIO2,但如果您使用不同的平台,请检查这是否需要更改。

软件架构

三个主要组件

  • WiFi 通信——将数据传递到网络设备,NTP
  • BLE 通信——查找广播设备,连接,查询数据
  • 调度和控制,BLE 扫描和查询调度等。
  • 设置——读取配置文件和解析等。

WiFi 通信

对于 WiFi 部分,我们主要使用内置的 SDK 驱动程序来支持 WiFi、UDP 和 HTTPClient 功能。此外,还使用 NTP 客户端尝试从网络获取正确的日期/时间。

要将从 BLE 服务器读取的一些数据发布到已连接 WiFi 的服务器,会创建一个 HTTP 客户端,并将日志请求发送到远程 HTTP 服务器。这利用了 IoT Edge Hub(前面提到的文章)来捕获数据并将其添加到日志文件中。稍后,后端 IoT 处理器可以使用 FTP 从 IoT Edge Hub 访问此日志文件。后端处理器可以根据需要为 IoT 应用程序归档和/或处理 BLE 数据。

BLE 通信

ESP32 BLE SDK 用于创建 BLE 客户端设备。此客户端设备用于两项任务:

  • 广播**扫描**以查找感兴趣的 BLE 设备(在配置文件中引用)。
  • 按计划,读取多达 100 个 BLE 服务器**特征**,并将数据通过 WiFi 传输到 IoT Edge Hub。

配置文件中定义的 BLE 特征

要扫描的 BLE 服务器特征由存储在设备上的配置文件中的一个或多个行定义。该文件最多可以定义 100 个要从 BLE 设备扫描并传输到 IoT Edge Hub 的值。值可以按分钟为单位的计划定期扫描——因此有些值可以每分钟读取一次,有些可以每 10 或 15 分钟读取一次。读取周期也在配置文件中定义。

如果需要扫描的值超过 100 个——可以在源代码中增加定义的常量 MAXVALUES2READ

在配置文件中,要扫描的值包括以下信息:

  • 一个标识标签——用于识别值以便将来处理——例如,“TEMP-Garage”可以用来标识监测车库温度的 BLE 设备。
  • 计划周期——每次读取参数之间的时间间隔(分钟数)——可以从 1 到 1440(每分钟一次到每天一次)。
  • BLE 设备的广播名称,或 BLE 设备的 MAC 地址(格式为 xx:xx:xx:xx:xx:xx)
  • BLE 设备上包含所需特征的服务的 UUID
  • 要读取的 BLE 设备上特征的 UUID

示例如下(将扫描 VALUE1...VALUE100):

VALUE1=TempF,15,DIY TempHumidity Sensor,b7972d95-e930-4144-beb0-6a6e8b9a3d23,
20b5e09a-f998-47f0-aae3-4b361ebc8233
VALUE2=Time-Date,15,DIY TempHumidity Sensor,b7972d95-e930-4144-beb0-6a6e8b9a3d23,
711d51a8-f76b-4c24-ad4a-8a3059d2489b
VALUE3=Humidity,15,DIY TempHumidity Sensor,b7972d95-e930-4144-beb0-6a6e8b9a3d23,
5ed64822-1dc1-4ebd-8e23-f0847e380841

BLE 网桥初始化任务

BLE 网桥首次启动时会执行一些初始化任务。这些任务设置了开始操作所需的各种硬件设备和软件结构。这些在应用程序的 setup() 函数中完成。

ESP32 开发板通常有一个内置 LED。对于此应用程序,LED 用于指示某些活动——它被称为“舒适” LED——表示应用程序正在做某事。舒适 LED 用于:

  • 启动初始化处理期间亮起
  • 在广告扫描接收 BLE 广告数据包时闪烁
  • 从 BLE 设备读取特征时亮起
  • 当 BLE 网桥空闲且无事可做时,以 1 秒间隔闪烁

这是初始化任务的代码——setup() 函数。

您将看到以下部分:

  • 初始化并点亮舒适 LED
  • 初始化实时时钟 (RTC) 为 2024 年 1 月 1 日 00:00:00
  • 初始化诊断串行端口并输出启动标识消息
  • 尝试挂载片上文件系统 SPIFFS——如果无法完成,应用程序将停止并闪烁错误代码。
  • 从 SPIFFS 读取配置文件——这是一个文件 /config.ini,存储在 SPIFFS 的根文件夹中,包含 5 到 105 行——一个文本文件,看起来像这样:
    WIFISSID=MySsid
    WIFIPWD=MyWiFiPassword
    IOTHUBADDR=192.168.5.3
    BLENAME=BLE WIFI Bridge V1.1
    VALUE1=TempF,15,DIY TempHumidity Sensor,b7972d95-e930-4144-beb0-6a6e8b9a3d23,
    20b5e09a-f998-47f0-aae3-4b361ebc8233
    VALUE2=Time-Date,15,DIY TempHumidity Sensor,
    b7972d95-e930-4144-beb0-6a6e8b9a3d23,711d51a8-f76b-4c24-ad4a-8a3059d2489b
    VALUE3=Humidity,15,DIY TempHumidity Sensor,
    b7972d95-e930-4144-beb0-6a6e8b9a3d23,5ed64822-1dc1-4ebd-8e23-f0847e380841
    # EOF
    • 前两行定义了要连接的 WiFi 网络的 ssid 和密码。
    • 第三行是数据要存储的 IoT Edge Hub 的 IP 地址。
    • 第四行是要创建的用于扫描 BLE 服务器数据的 BLE 客户端的名称。
    • 1 到 100 行定义了要按计划读取的 BLE 特征。
    • 连接到 WiFi——如果无法完成,应用程序将停止并闪烁错误代码。
    • 尝试从 NTP 获取当前日期/时间。
    • 创建 BLE 客户端并开始扫描 BLE 广告数据包。
    • 初始化 ESP32 看门狗定时器,以便在应用程序崩溃时重置 ESP32。
    • 初始化一些操作所需的杂项应用程序变量。
//--------------------------------------------------
void setup() 
{
  char tmpbuf[256];
  char tmpname[32];

  //--- initialize the comfort (signal) LED
  pinMode(SIGNALLED, OUTPUT);
  ledmode=HIGH;
  // turn comfort LED on for the setup processing
  digitalWrite(SIGNALLED,ledmode);

  //--- initialize the RTC
  rtc.setTime(0,0,0,1,1,2024);

  //--- initialize the diagnostic serial port
  Serial.begin(115200);
  Serial.println(SIGNON);
    
  //--- initialize SPIFFS (file system)
  if(!SPIFFS.begin(true))
  {
    print("An Error has occurred while mounting SPIFFS");
    blink(ERR_NOSPIFFS);
    //return; what to do here?  We can't do much without the file system
  }
  
  //--- read the configuration file
  readKey(CONFIGFN,"WIFISSID=",wifissid,63);
  readKey(CONFIGFN,"WIFIPWD=",wifipwd,63);
  readKey(CONFIGFN,"IOTHUBADDR=",iothubip,63);
  readKey(CONFIGFN,"BLENAME=", btlebridgename, 63);
  // values to read
  nValues=0;
  for (int i = 1; i < MAXVALUES2READ; i++)
  {
    // VALUE1=15,11:22:33:44:55:66,b7972d95-e930-4144-beb0-6a6e8b9a3d23,
    // 20b5e09a-f998-47f0-aae3-4b361ebc8233
    // VALUEn=minutes,deviceId,ServiceUuid,CharacteristicUuid
    sprintf(tmpname,"VALUE%d=",i);
    readKey(CONFIGFN,tmpname, tmpbuf, 255); // try to read it
    if (tmpbuf[0] != '\0') // found "VALUEn="
    {
      // yes, found one, allocate and initialize an entry to read it and keep track of it
      Serial.print("\nParsing value: "); Serial.println(tmpbuf);
      vals2read[nValues] = new ValueToRead();
      char* result = vals2read[nValues]->set(tmpbuf);
      Serial.println(result);
      Serial.println(vals2read[nValues]->toString());
      nValues++;
    }
  }
  Serial.printf("%d values read from config file\n",nValues);
  
  //--- connect to WiFi
  if (!connectToWiFi()) blink(ERR_NOWIFI);
  
  //--- see if we can get date/time from WiFi - Network Time Protocol (NTP)
  getNtpTime();

  //--- initialize BLE client and start scanning for BLE advertising packets
  BLEDevice::init(btlebridgename);
  pBLEScan = BLEDevice::getScan();     //create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true);       // active scan uses more power, 
                                       // but get results faster
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(99);             // less or equal setInterval value
  pClient = BLEDevice::createClient(); // create client to use for connecting, 
                                       // reading values

  //--- Initialize watch-dog-timer to reset the BLE bridge if it goes off line
  esp_task_wdt_init(WDT_TIMEOUT, true);// enable WDT so the ESP32 restarts 
                                       // after 10 seconds
  esp_task_wdt_add(NULL);              // enable WDT for this task

  //--- initialize some application variables
  minuteCounter = -1;
  timeForScan = true;
  
  lastMin = rtc.getMinute();

  //--- LED off at end of setup
  LEDOFF;
}

BLE 网桥操作任务

在操作模式下,BLE 网桥有一些任务是一秒钟执行一次,一些是一分钟执行一次,还有一些是按需执行的。

以下任务在操作模式下定义:

  • 闪烁舒适 LED——以每秒 1 次的速率执行。
  • 扫描要读取的值——每分钟检查一次是否有 BLE 值需要读取。
    • 对于配置文件中找到的每个 BLE 值——检查当前分钟数是否能被该值的读取周期整除。如果是,则读取该值并将其添加到队列以发送到 IoT Edge Hub。
    • 有时,没有要读取的值——所以在那些分钟里什么也没有发生。其他分钟,可能有多个值需要读取。
    • 每小时一次,再次扫描 BLE 广告数据包。在 setup() 函数完成后以及在启动时也执行此操作。
  • 扫描广告数据包——每小时一次。
    • 启动时和每小时,我们启动 BLE 客户端扫描广告数据包。
    • 如果发现数据包,则调用 MyAdvertisedDeviceCallbacks() 中的回调函数。
    • 此回调函数将遍历要读取的值列表(从配置文件中获取)。如果收到的广告数据包的广播名称或 MAC 地址与我们感兴趣的设备之一匹配,我们就可以将其标记为可供读取。如果为我们未收到任何广告数据包的设备定义了值,那么我们必须假设该设备不可用,并在接下来的一个小时内忽略它。每个小时,我们将再次扫描——如果找到它,我们将激活对该值的扫描。
  • WiFi 重连——按需——如果 WiFi 由于某种原因断开连接,我们将尝试重新连接。这可能会发生在临时电源中断、信号干扰或阻塞的情况下。
//--------------------------------------------------
// Operational tasks
void loop() 
{
  LEDOFF;
  for (;;)
  {
    int currentSec = rtc.getSecond();
    if (currentSec != lastSec)
    {
      //--- one second tasks
      lastSec = currentSec;
      ledmode ^= 1;
      digitalWrite(SIGNALLED,ledmode);
      // The ESP32 has a watch-dog timer (WDT). 
      // This is a timer that counts from a starting
      // point down to 0. By calling esp_task_wdt_reset(),  
      // you can reset the WDT back to its
      // starting point. This is "kicking the WDT". 
      //
      // If for some reason, the WDT doesn't get reset before it gets down to 0, then
      // the ESP32 will be reset and it will reboot.
      //
      // This is a "last ditch" effort to recover the application in case it should run
      // into some unexpected dead state such that the WDT isn't getting kicked in time.
      esp_task_wdt_reset(); // reset watch-dog timer
    }
        
    // keep track of minutes going by in a variable minuteCounter  
    int currentMin = rtc.getMinute();
    if (currentMin != lastMin)
    {
      //--- one minute tasks
      LEDON;
      lastMin = currentMin;
      minuteCounter++;
      Serial.print("Minute processing: ");
      Serial.println(minuteCounter);

      if ((minuteCounter % 60) == 59) timeForScan = true; // rescan BLE each hour
      
      // now read all devices that are due for this minute
      for (int i = 0; i < nValues; i++)
      {
        ValueToRead* p = vals2read[i];
        long mod = minuteCounter % p->minutesBetweenReads;
        if ((mod == 0) && (p->deviceAddr[0] != '\0'))
        {
          // it's the right minute to read the value,
          // and we have seen the device advertise in a BLE scan

          readValue(pClient, p, buf,256);
          String ttag = rtc.getTime("%Y/%m/%d,%H:%M:%S");
          sprintf(buf,"%s,%s,%s",(char*)ttag.c_str(), p->valueTag,buf);
          int sts = measuredData.push(buf);
          if (sts == 0) Serial.println("Measurement queue overflow");
        }
      }
      LEDOFF;
    }

    //-- on demand task - rescan for BLE devices
    if (timeForScan)
    {
      BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
      Serial.print("Devices found: ");
      Serial.println(foundDevices.getCount());
      Serial.println("Scan done!");
      pBLEScan->clearResults();   
    
      timeForScan = false;
    }

    //--- on demand task - if WiFi disconnects, try to reconnect
    if (WiFi.status() != WL_CONNECTED)
    {
      // WiFi is disconnected, so try a reconnect
      delay(200);
      connectToWiFi();
      if (wifiIsConnected) getNtpTime();
      lastMin = rtc.getMinute();
    }

    // push any queued data to the IoT hub
    if (measuredData.isEmpty() == 0)
    {
      // send any queued measurement data to server
      buf1[0] = '\0';
      int sts = measuredData.pop(buf1,384);
      if (sts && (strlen(buf1)>0))
      {
        sts = forwardValueToIotHub(buf1);
        if (!sts) 
        {
          measuredData.push(buf1); // didn't go, push it back to try later
          Serial.println("Send to IoT hub failed");
        }
      }
    }

    // set RTC
    if (timeFromIotHub != "")
    {
      Serial.print("Set time: "); Serial.println(timeFromIotHub);
      String ttag = rtc.getTime("%Y/%m/%d,%H:%M:%S");
      Serial.println(ttag);
      timeFromIotHub = "";
    }    
  }
}

代码可在 Github 上获取。

后续任务

对于未来的附加功能,正在考虑以下几点:

  • 如果由于某种原因无法将数据发送到 WiFi IoT Edge 服务器(WiFi 离线、IoT Edge 服务器离线)——将数据保存在备份日志文件中,并在恢复正常后尝试重新发送。
  • 如果无法从 NTP 确定日期/时间,尝试从 IoT Edge 服务器获取——或在 IoT Edge 服务器应用程序中实现一个 NTP 服务器。
  • 实现一些“警报”指示器——以便某些值可以触发一些即时响应——例如,如果触发了漏水传感器或烟雾探测器,我们可能希望在 IoT Edge Hub 中以更高的优先级处理。

历史

  • 版本 1.0,2024 年 3 月
© . All rights reserved.