#include #include #include #include #include #include #include #include #include "Tone32.h" //#include "SparkLine.h" // ssd1306 display SSD1306Wire display(0x3c, 5, 4); #define SSD1306_128_64 // Pin where the + of an LED is connected. #define LED_PIN 0 // Pin where the + of a piezo buzzer is connected. #define BUZZER_PIN 2 // Tone to play. #define BEEP_NOTE NOTE_C6 // Tone duration in milliseconds. #define BEEP_DURATION_MS 100 // Scan update time, 5 seems to be a good value. #define SCAN_TIME_SECONDS 5 // When to forget old senders. #define FORGET_AFTER_MINUTES 20 BLEScan *scanner; std::map seenNotifiers; /** * UI related functions */ void displayBootscreen() { Serial.println("Show bootscreen"); display.clear(); display.setColor(WHITE); display.setTextAlignment(TEXT_ALIGN_CENTER); display.fillRect(4, 8, 121, 24); display.drawRect(4, 32, 121, 19); display.setFont(ArialMT_Plain_10); display.drawString(64, 35, "Exposure API Scanner"); display.setColor(BLACK); display.setFont(ArialMT_Plain_24); display.drawString(64, 7, "COVID-19"); display.display(); } /** * Called when a new exposure notifier is seen. */ void onNewNotifierFound() { Serial.println("BEEP"); digitalWrite(LED_PIN, HIGH); tone(BUZZER_PIN, BEEP_NOTE, BEEP_DURATION_MS, 0); digitalWrite(LED_PIN, LOW); } class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks { /** * Called when a BLE device is discovered. */ void onResult(BLEAdvertisedDevice advertisedDevice) override { if (!advertisedDevice.haveServiceUUID() || !advertisedDevice.getServiceUUID().equals(BLEUUID((uint16_t) 0xfd6f)) ) { return; } if (!seenNotifiers.count(advertisedDevice.getAddress().toString())) { // New notifier found. Serial.printf("+ %s \r\n", advertisedDevice.getAddress().toString().c_str()); onNewNotifierFound(); } else { // We've already seen this one. Serial.printf("... %s \r\n", advertisedDevice.getAddress().toString().c_str()); } // Remember, with time. seenNotifiers[advertisedDevice.getAddress().toString()] = millis(); } }; /** * Remove notifiers last seen over FORGET_AFTER_MINUTES ago. */ void forgetOldNotifiers() { for (auto const ¬ifier : seenNotifiers) { if (notifier.second + (FORGET_AFTER_MINUTES * 60 * 1000) < millis()) { Serial.printf("- %s \r\n", notifier.first.c_str()); seenNotifiers.erase(notifier.first); } } } void setup() { Serial.begin(115200); Serial.println("Hi."); // Initialize pins. pinMode(LED_PIN, OUTPUT); pinMode(BUZZER_PIN, OUTPUT); // Initialize display Serial.println("Init Display"); display.init(); displayBootscreen(); // Initialize scanner. BLEDevice::init("ESP"); scanner = BLEDevice::getScan(); scanner->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); scanner->setActiveScan(true); // Active scan uses more power, but gets results faster. scanner->setInterval(100); scanner->setWindow(99); Serial.println("Scanning ..."); } void loop() { Serial.println("-----"); // Scan. scanner->start(SCAN_TIME_SECONDS, false); // Cleanup. scanner->clearResults(); forgetOldNotifiers(); Serial.printf("Count: %d \r\n", seenNotifiers.size()); // Serial.printf("Show data on SSD1306 display"); display.clear(); display.setColor(WHITE); display.setTextAlignment(TEXT_ALIGN_CENTER); display.setFont(ArialMT_Plain_10); display.drawRect(0, 0, 128, 64); // UI Outline display.fillRect(0, 0, 128, 14); // UI Header display.drawString(64, 0, "Exposure API Counter"); if (seenNotifiers.size() == 1) { display.drawString(64, 48, "Device in last " + String(FORGET_AFTER_MINUTES) +"min."); } else { display.drawString(64, 48, "Devices in last " + String(FORGET_AFTER_MINUTES) +"min."); } //display.drawString(64, 48, "Device(s) in last " + String(FORGET_AFTER_MINUTES) +"min."); display.setFont(ArialMT_Plain_24); display.drawString(64, 20, String(seenNotifiers.size())); display.setColor(BLACK); // HEADER TITLE display.setFont(ArialMT_Plain_10); display.drawString(64, 0, "Exposure API Counter"); display.display(); }