mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-26 22:22:16 +03:00
Merge pull request #2 from avaksru/ver4dev
Модуль BLE ( bluetooth) сканер
This commit is contained in:
@@ -67,6 +67,10 @@
|
|||||||
"path": "src/modules/sensors/AnalogAdc",
|
"path": "src/modules/sensors/AnalogAdc",
|
||||||
"active": true
|
"active": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "src/modules/sensors/Ble",
|
||||||
|
"active": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "src/modules/sensors/Bme280",
|
"path": "src/modules/sensors/Bme280",
|
||||||
"active": true
|
"active": true
|
||||||
|
|||||||
248
src/modules/sensors/Ble/Ble.cpp
Normal file
248
src/modules/sensors/Ble/Ble.cpp
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
#include "Global.h"
|
||||||
|
#include "classes/IoTItem.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
#ifdef ESP32
|
||||||
|
#include <NimBLEDevice.h>
|
||||||
|
#include <decoder.h>
|
||||||
|
|
||||||
|
// Создаем переменную для хранения данных с датчиков bluetooth
|
||||||
|
StaticJsonDocument<JSON_BUFFER_SIZE * 4> BLEbuffer;
|
||||||
|
JsonObject extBLEdata = BLEbuffer.to<JsonObject>();
|
||||||
|
|
||||||
|
BLEScan *pBLEScan;
|
||||||
|
TheengsDecoder decoder;
|
||||||
|
StaticJsonDocument<512> doc;
|
||||||
|
|
||||||
|
class BleScan : public IoTItem, BLEAdvertisedDeviceCallbacks
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
//описание параметров передаваемых из настроек датчика из веба
|
||||||
|
int _scanDuration;
|
||||||
|
String _filter;
|
||||||
|
|
||||||
|
public:
|
||||||
|
//=======================================================================================================
|
||||||
|
std::string convertServiceData(std::string deviceServiceData)
|
||||||
|
{
|
||||||
|
int serviceDataLength = (int)deviceServiceData.length();
|
||||||
|
char spr[2 * serviceDataLength + 1];
|
||||||
|
for (int i = 0; i < serviceDataLength; i++)
|
||||||
|
sprintf(spr + 2 * i, "%.2x", (unsigned char)deviceServiceData[i]);
|
||||||
|
spr[2 * serviceDataLength] = 0;
|
||||||
|
return spr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onResult(BLEAdvertisedDevice *advertisedDevice)
|
||||||
|
{
|
||||||
|
JsonObject BLEdata = doc.to<JsonObject>();
|
||||||
|
String mac_adress_ = advertisedDevice->getAddress().toString().c_str();
|
||||||
|
mac_adress_.toUpperCase();
|
||||||
|
BLEdata["id"] = (char *)mac_adress_.c_str();
|
||||||
|
|
||||||
|
if (advertisedDevice->haveName())
|
||||||
|
{
|
||||||
|
BLEdata["name"] = (char *)advertisedDevice->getName().c_str();
|
||||||
|
}
|
||||||
|
if (advertisedDevice->haveManufacturerData())
|
||||||
|
{
|
||||||
|
char *manufacturerdata = BLEUtils::buildHexData(NULL, (uint8_t *)advertisedDevice->getManufacturerData().data(), advertisedDevice->getManufacturerData().length());
|
||||||
|
BLEdata["manufacturerdata"] = manufacturerdata;
|
||||||
|
free(manufacturerdata);
|
||||||
|
}
|
||||||
|
if (advertisedDevice->haveRSSI())
|
||||||
|
BLEdata["rssi"] = (int)advertisedDevice->getRSSI();
|
||||||
|
if (advertisedDevice->haveTXPower())
|
||||||
|
BLEdata["txpower"] = (int8_t)advertisedDevice->getTXPower();
|
||||||
|
if (advertisedDevice->haveServiceData())
|
||||||
|
{
|
||||||
|
int serviceDataCount = advertisedDevice->getServiceDataCount();
|
||||||
|
for (int j = 0; j < serviceDataCount; j++)
|
||||||
|
{
|
||||||
|
std::string service_data = convertServiceData(advertisedDevice->getServiceData(j));
|
||||||
|
BLEdata["servicedata"] = (char *)service_data.c_str();
|
||||||
|
std::string serviceDatauuid = advertisedDevice->getServiceDataUUID(j).toString();
|
||||||
|
BLEdata["servicedatauuid"] = (char *)serviceDatauuid.c_str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decoder.decodeBLEJson(BLEdata))
|
||||||
|
{
|
||||||
|
|
||||||
|
BLEdata.remove("manufacturerdata");
|
||||||
|
BLEdata.remove("servicedata");
|
||||||
|
|
||||||
|
String mac_address = BLEdata["id"].as<const char *>();
|
||||||
|
mac_address.replace(":", "");
|
||||||
|
|
||||||
|
if (_filter != "")
|
||||||
|
{
|
||||||
|
if (BLEdata[_filter])
|
||||||
|
{
|
||||||
|
for (JsonPair kv : BLEdata)
|
||||||
|
{
|
||||||
|
extBLEdata[mac_address][kv.key()] = BLEdata[kv.key()];
|
||||||
|
}
|
||||||
|
|
||||||
|
// дописываем время прихода пакета данных
|
||||||
|
extBLEdata[mac_address]["last"] = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (JsonPair kv : BLEdata)
|
||||||
|
{
|
||||||
|
extBLEdata[mac_address][kv.key()] = BLEdata[kv.key()];
|
||||||
|
}
|
||||||
|
// дописываем время прихода пакета данных
|
||||||
|
extBLEdata[mac_address]["last"] = millis();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
BleScan(String parameters) : IoTItem(parameters)
|
||||||
|
{
|
||||||
|
_scanDuration = jsonReadInt(parameters, "scanDuration");
|
||||||
|
_filter = jsonReadStr(parameters, "filter");
|
||||||
|
|
||||||
|
if (pBLEScan->isScanning() == false)
|
||||||
|
{
|
||||||
|
SerialPrint("i", F("BLE"), "Start Scanning...");
|
||||||
|
BLEDevice::init("");
|
||||||
|
pBLEScan = BLEDevice::getScan(); // create new scan
|
||||||
|
pBLEScan->setAdvertisedDeviceCallbacks(this);
|
||||||
|
pBLEScan->setActiveScan(false); // active scan uses more power, but get results faster
|
||||||
|
pBLEScan->setInterval(100);
|
||||||
|
pBLEScan->setWindow(99); // less or equal setInterval value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================================================================
|
||||||
|
|
||||||
|
// doByInterval()
|
||||||
|
void doByInterval()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (_scanDuration > 0)
|
||||||
|
{
|
||||||
|
BLEScanResults foundDevices = pBLEScan->start(_scanDuration, true);
|
||||||
|
int count = foundDevices.getCount();
|
||||||
|
SerialPrint("i", F("BLE"), "Devices found: " + String(count));
|
||||||
|
SerialPrint("i", F("BLE"), "Scan done!");
|
||||||
|
pBLEScan->clearResults();
|
||||||
|
}
|
||||||
|
for (JsonPair kv : extBLEdata)
|
||||||
|
{
|
||||||
|
String val = extBLEdata[kv.key()].as<String>();
|
||||||
|
SerialPrint("i", F("BLE"), _id + " " + kv.key().c_str() + " " + val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================================================================
|
||||||
|
|
||||||
|
~BleScan(){};
|
||||||
|
};
|
||||||
|
|
||||||
|
class BleSens : public IoTItem
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
//описание параметров передаваемых из настроек датчика из веба
|
||||||
|
String _MAC;
|
||||||
|
String _sensor;
|
||||||
|
|
||||||
|
public:
|
||||||
|
//=======================================================================================================
|
||||||
|
char *TimeToString(unsigned long t)
|
||||||
|
{
|
||||||
|
static char str[12];
|
||||||
|
long h = t / 3600;
|
||||||
|
t = t % 3600;
|
||||||
|
int m = t / 60;
|
||||||
|
int s = t % 60;
|
||||||
|
sprintf(str, "%02ld:%02d:%02d", h, m, s);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
BleSens(String parameters) : IoTItem(parameters)
|
||||||
|
{
|
||||||
|
_MAC = jsonReadStr(parameters, "MAC");
|
||||||
|
_sensor = jsonReadStr(parameters, "sensor");
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================================================================
|
||||||
|
|
||||||
|
// doByInterval()
|
||||||
|
void doByInterval()
|
||||||
|
{
|
||||||
|
if (_sensor == "last")
|
||||||
|
{
|
||||||
|
int valInt = extBLEdata[_MAC][_sensor].as<int>();
|
||||||
|
char *s;
|
||||||
|
s = TimeToString(millis() / 1000 - valInt / 1000);
|
||||||
|
value.isDecimal = 0;
|
||||||
|
if (valInt > 0)
|
||||||
|
{
|
||||||
|
value.valS = s;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value.valS = "";
|
||||||
|
}
|
||||||
|
regEvent(value.valS, _id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
String valStr = extBLEdata[_MAC][_sensor].as<String>();
|
||||||
|
if (valStr != "null")
|
||||||
|
{
|
||||||
|
if (value.isDecimal = isDigitDotCommaStr(valStr))
|
||||||
|
{
|
||||||
|
value.isDecimal = 1;
|
||||||
|
value.valD = valStr.toFloat();
|
||||||
|
regEvent(value.valD, _id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value.isDecimal = 0;
|
||||||
|
value.valS = valStr;
|
||||||
|
regEvent(value.valS, _id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value.isDecimal = 0;
|
||||||
|
value.valS = "";
|
||||||
|
regEvent(value.valS, _id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//=======================================================================================================
|
||||||
|
|
||||||
|
~BleSens(){};
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Заглушка для ESP8266
|
||||||
|
#ifdef ESP8266
|
||||||
|
class Ble : public IoTItem
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
Ble(String parameters) : IoTItem(parameters) {}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *getAPI_Ble(String subtype, String param)
|
||||||
|
{
|
||||||
|
if (subtype == F("BleScan"))
|
||||||
|
{
|
||||||
|
return new BleScan(param);
|
||||||
|
}
|
||||||
|
else if (subtype == F("BleSens"))
|
||||||
|
{
|
||||||
|
return new BleSens(param);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
64
src/modules/sensors/Ble/modinfo.json
Normal file
64
src/modules/sensors/Ble/modinfo.json
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"menuSection": "Сенсоры",
|
||||||
|
"configItem": [
|
||||||
|
{
|
||||||
|
"name": "bluetooth сканер",
|
||||||
|
"num": 1,
|
||||||
|
"type": "Reading",
|
||||||
|
"subtype": "BleScan",
|
||||||
|
"id": "BleScan",
|
||||||
|
"widget": "na",
|
||||||
|
"page": "",
|
||||||
|
"descr": "",
|
||||||
|
"int": 135,
|
||||||
|
"scanDuration": 10,
|
||||||
|
"filter": "servicedatauuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "bluetooth датчик",
|
||||||
|
"num": 1,
|
||||||
|
"type": "Reading",
|
||||||
|
"subtype": "BleSens",
|
||||||
|
"id": "BleSens",
|
||||||
|
"widget": "anydataDef",
|
||||||
|
"page": "Сенсоры",
|
||||||
|
"descr": "",
|
||||||
|
"needSave": 0,
|
||||||
|
"global": 0,
|
||||||
|
"round": 1,
|
||||||
|
"int": 60,
|
||||||
|
"MAC": "",
|
||||||
|
"sensor": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"about": {
|
||||||
|
"authorName": "AVAKS",
|
||||||
|
"authorContact": "https://t.me/@avaks_dev",
|
||||||
|
"authorGit": "https://github.com/avaksru",
|
||||||
|
"specialThanks": "@Serghei63",
|
||||||
|
"moduleName": "Ble",
|
||||||
|
"moduleVersion": "1.0",
|
||||||
|
"usedRam": {
|
||||||
|
"esp32_4mb": 1261449,
|
||||||
|
"esp8266_4mb": 0
|
||||||
|
},
|
||||||
|
"subTypes": ["BleSens", "BleScan"],
|
||||||
|
"title": "Сканер Bluetooth",
|
||||||
|
"moduleDesc": "Позволяет получить данные с Bluetooth часов и термометров Mijia, Xiaomi, Cleargrass, ...",
|
||||||
|
"propInfo": {
|
||||||
|
"round": "Округление после запятой.",
|
||||||
|
"int": "Интервал сканирования BLE окружения (BleScan) / Интервал отправки собранной телеметрии в MQTT (BleSens)",
|
||||||
|
"scanDuration": "Длительность сканирования ",
|
||||||
|
"filter": "Позволяет установить фильтр по параметру передаваемому датчиком. Данные будут считываться только с датчиков у которых есть передаваемый параметр указанный в фильтре",
|
||||||
|
"MAC": "MAC адрес беспроводного датчика",
|
||||||
|
"sensor": "Тип сенсора: температура / влажность / время / ... "
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defActive": false,
|
||||||
|
"usedLibs": {
|
||||||
|
"esp32_4mb": [
|
||||||
|
"https://github.com/h2zero/NimBLE-Arduino.git",
|
||||||
|
"https://github.com/avaksru/decoder.git"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user