ESP32模拟某钉蓝牙打卡程序

By | 2022-04-21

具体原理:

修改esp32的蓝牙mac地址,模拟各种蓝牙设备
并且还可以按照指定的raw内容来返回扫描结果
比如模拟某钉的打卡机,实现蓝牙打卡。

使用方法:

首先,装一个叫 nRF Connect 的app,走到打卡机旁边,找到信号最强那个,记下他的mac地址,复制raw
然后修改 代码中的 bleMacbleRaw ,去掉最前面的0x,两个一组,前面加上0x,是不是很直观?
还是不能理解?那就举个🌰:
0x112233445566778899
就会变成:
{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}

将代码拷贝,重命名dingBle.ino然后用arduino开发环境编译上传到esp32就可以用了
App需要新一点的版本,例如Android下需要4.7.5以上的。

代码如下:

#include "BLEDevice.h"
#include "BLEUtils.h"
#include "esp_sleep.h"

#ifdef __cplusplus
extern "C" {
#endif

uint8_t temprature_sens_read();
//uint8_t g_phyFuns;

#ifdef __cplusplus
}
#endif

BLEAdvertising *pAdvertising;

uint8_t bleMac[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
// 0-30 前31组
uint8_t bleRaw[] = {0x02,0x01,0x06,0x17,0xFF,0x00,0x01,0xB5,0x00,0x02,0x25,0xEC,0xD7,0x44,0x00,0x00,0x01,0xAA,0x91,0x77,0x67,0xAF,0x01,0x10,0x00,0x00,0x00,0x03,0x03,0x3C,0xFE};
// 如果复制出来的raw超过31组 那么把它改为true并维护下面的数组
boolean rawMoreThan31 = false;
// 31-end
uint8_t bleRaw32[] = {0x0C,0x09,0x52,0x54,0x4B,0x5F,0x42,0x54,0x5F,0x34,0x2E,0x31,0x00};


void setup() {
  Serial.begin(115200);

  // esp32没有提供设置蓝牙mac地址的api 通过查看esp32的源代码
  // 此操作将根据蓝牙mac算出base mac
  if (UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR) {
    bleMac[5] -= 2;
  } else if (UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR) {
    bleMac[5] -= 1;
  }
  esp_base_mac_addr_set(bleMac);

  // 初始化
  BLEDevice::init("");

  // Create the BLE Server
  // BLEServer *pServer = BLEDevice::createServer(); // <-- no longer required to instantiate BLEServer, less flash and ram usage

  pAdvertising = BLEDevice::getAdvertising();

  // 设备信息设置成空白的
  BLEAdvertisementData oScanResponseData = BLEAdvertisementData();
  pAdvertising->setScanResponseData(oScanResponseData);

  // 里面有个 m_customScanResponseData = true; 和 m_customScanResponseData = true; 所以只能先随便设置一下
  BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
  pAdvertising->setAdvertisementData(oAdvertisementData);

  // 简单粗暴直接底层api重新设置一下抓到的raw
  esp_err_t errRc = ::esp_ble_gap_config_adv_data_raw(bleRaw, 31);
  if (errRc != ESP_OK) {
    Serial.printf("esp_ble_gap_config_adv_data_raw: %d\n", errRc);
  }
  // 超过31
  if (rawMoreThan31) {
    errRc = ::esp_ble_gap_config_scan_rsp_data_raw(bleRaw32, sizeof(bleRaw32));
    if (errRc != ESP_OK) {
      Serial.printf("esp_ble_gap_config_scan_rsp_data_raw: %d\n", errRc);
    }
  }

  pAdvertising->start();
}

void loop() {
  // 闪灯灯
  Serial.println("Sparkle");
  delay(1000);
  // 20分钟去待机避免忘了关
  if (millis() > 1200000) {
    esp_deep_sleep_start();
  }
}

本文学习来自:https://github.com/zanjie1999/dingBle