Skip to content

Instantly share code, notes, and snippets.

@sivar2311
Created September 24, 2023 18:56
Show Gist options
  • Save sivar2311/83236e4a8992cfbab62f3de1a69ccaf5 to your computer and use it in GitHub Desktop.
Save sivar2311/83236e4a8992cfbab62f3de1a69ccaf5 to your computer and use it in GitHub Desktop.
SinricPro BLE Device Counter
#ifndef _BLEDEVICECOUNTER_H_
#define _BLEDEVICECOUNTER_H_
#include <SinricProDevice.h>
#include <Capabilities/RangeController.h>
class BLEDeviceCounter
: public SinricProDevice
, public RangeController<BLEDeviceCounter> {
friend class RangeController<BLEDeviceCounter>;
public:
BLEDeviceCounter(const String &deviceId) : SinricProDevice(deviceId, "BLEDeviceCounter") {};
};
#endif
{
"name": "BLEDeviceCounter",
"description": "BLEDeviceCounter",
"deviceTypeId": "600d11ec94acbe29a9ce23e9",
"capabilities": [
{
"id": "5ff0b45f994fd31b7d5e89c2",
"range": {
"instanceId": "counter",
"locale": "en-US",
"rangeName": "counter",
"minimumValue": 0,
"maximumValue": 99999,
"precision": 1,
"unitOfMeasure": "600e7d6aa7a09c3f3230f998",
"presets": [],
"nonControllable": true
}
}
]
}
#include <Arduino.h>
#include <WiFi.h>
#include <SinricPro.h>
#include "BLEDeviceCounter.h"
#include <map>
#include "NimBLEDevice.h"
const char* wifiSSID = "";
const char* wifiPass = "";
const char* deviceId = "";
const char* appKey = "";
const char* appSecret = "";
const unsigned long removeThresholdInMs = 60000;
NimBLEScan* pBLEScan;
std::map<String, unsigned long> deviceList;
void addDeviceToList(const String& address, unsigned long timeStamp) {
deviceList[address] = timeStamp;
Serial.printf("Currently there are %d ble devices in the list\r\n", deviceList.size());
}
void removeDeviceFromList(const String& address) {
auto it = deviceList.find(address);
deviceList.erase(it);
}
void cleanUpBLEDeviceList(unsigned long ms) {
unsigned long currentMillis = millis();
std::vector<String> removeList;
for (auto device : deviceList) {
unsigned long lastHeard = device.second;
String address = device.first;
if (currentMillis - lastHeard > ms) removeList.push_back(address);
}
size_t deviceCountBeforeCleanUp = deviceList.size();
for (auto& address : removeList) {
removeDeviceFromList(address);
}
size_t removedDeviceCount = deviceCountBeforeCleanUp - deviceList.size();
if (removedDeviceCount) {
Serial.printf("Cleanup removed %d devices\r\n", removedDeviceCount);
Serial.printf("Currently there are %d devices in the list\r\n", deviceList.size());
}
}
class MyAdvertisedDeviceCallbacks : public NimBLEAdvertisedDeviceCallbacks {
void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
String address = advertisedDevice->getAddress().toString().c_str();
addDeviceToList(address, millis());
}
};
void setupBLE() {
NimBLEDevice::setScanFilterMode(CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE);
NimBLEDevice::setScanDuplicateCacheSize(200);
NimBLEDevice::init("");
}
void startBLEScan() {
pBLEScan = NimBLEDevice::getScan(); // create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks(), false);
pBLEScan->setActiveScan(false); // Set active scanning, this will get more data from the advertiser.
pBLEScan->setInterval(97); // How often the scan occurs / switches channels; in milliseconds,
pBLEScan->setWindow(37); // How long to scan during the interval; in milliseconds.
pBLEScan->setMaxResults(0); // do not store the scan results, use callback only.
pBLEScan->start(0, nullptr, false);
}
void setupWiFi() {
WiFi.begin(wifiSSID, wifiPass);
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(250);
}
Serial.println("connected!");
}
void setupSinricPro() {
BLEDeviceCounter& bleDeviceCounter = SinricPro[deviceId];
SinricPro.onConnected([](){ Serial.println("SinricPro connected!");});
SinricPro.begin(appKey, appSecret);
}
void reportBLEDeviceCount() {
cleanUpBLEDeviceList(removeThresholdInMs);
if (!SinricPro.isConnected()) return;
unsigned long currentMillis = millis();
static unsigned long lastReportTime;
static size_t lastReportDeviceCount;
if (lastReportTime && currentMillis - lastReportTime < 60000) return;
int devicesInList = deviceList.size();
if (lastReportDeviceCount == devicesInList) return;
lastReportDeviceCount = devicesInList;
lastReportTime = currentMillis;
Serial.printf("Reporting %d ble devices to SinricPro\r\n", devicesInList);
BLEDeviceCounter& bleDeviceCounter = SinricPro[deviceId];
bleDeviceCounter.sendRangeValueEvent("counter", devicesInList);
}
void setup() {
Serial.begin(115200);
setupWiFi();
setupBLE();
startBLEScan();
setupSinricPro();
}
void loop() {
SinricPro.handle();
reportBLEDeviceCount();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment