#pragma once #include #include #include namespace roro { // Follows one access point's signal over repeated scans, for finding where it is. class SignalTracker { public: static constexpr int kNoSignal = -127; static constexpr uint32_t kLostAfterMs = 5000; static constexpr uint32_t kFastestClickMs = 60; static constexpr uint32_t kSlowestClickMs = 1200; explicit SignalTracker(size_t historySize) : size_(historySize) {} void seen(int rssi, uint32_t nowMs) { push(rssi); latest_ = rssi; lastSeenMs_ = nowMs; everSeen_ = true; } void missed() { push(kNoSignal); } // a scan that didn't see it bool lost(uint32_t nowMs) const { return !everSeen_ || nowMs - lastSeenMs_ >= kLostAfterMs; } int latest() const { return latest_; } const std::deque& history() const { return history_; } // Time between clicks: fast when the signal is strong (close), slow when faint. static uint32_t clickIntervalMs(int rssi) { if (rssi >= -35) return kFastestClickMs; if (rssi <= -95) return kSlowestClickMs; float t = (rssi + 95) / 60.0f; // 0 at -95 dBm, 1 at -35 dBm return static_cast(kSlowestClickMs - t * (kSlowestClickMs - kFastestClickMs)); } private: void push(int v) { history_.push_back(v); if (history_.size() > size_) history_.pop_front(); } size_t size_; std::deque history_; int latest_ = kNoSignal; uint32_t lastSeenMs_ = 0; bool everSeen_ = false; }; } // namespace roro