#pragma once #include #include #include "app.h" #include "list_model.h" #include "services/clock_service.h" #include "services/lora_capture_service.h" #include "services/radio_service.h" #include "settings.h" #include "ui/theme.h" namespace roro { // The LoRa Scanner (docs/milestones/M3.md). Sniffer: the packets the radio hears, newest first, // with the Meshtastic header read (Q96) and a hex dump on Enter; p picks the preset (Q95), c starts // or stops a Capture (Q97). The radio listens while the App is open (Q100). Tab: Sweep, the band's // RSSI as bars with peak hold and a waterfall (Q98); it pauses the Sniffer while shown (Q99). class LoraScannerApp : public App { public: LoraScannerApp(RadioService& radio, LoraCaptureService& capture, Settings& settings, ClockService& clock) : radio_(radio), capture_(capture), settings_(settings), clock_(clock) {} void onEnter() override; void onExit() override; bool onKey(const KeyEvent& e) override; void update(uint32_t nowMs) override; void draw(Canvas& c) override; private: enum class View { Packets, Details, Presets, Sweep }; static constexpr int kListRows = 7; void drawPackets(Canvas& c); void drawDetails(Canvas& c); void drawPresets(Canvas& c); void drawSweep(Canvas& c); void showSweep(bool on); void openDetails(); std::string timeOf(const RadioPacket& p) const; bool meshtasticSettings() const; void say(const std::string& text); // a line in the footer for a few seconds RadioService& radio_; LoraCaptureService& capture_; Settings& settings_; ClockService& clock_; View view_ = View::Packets; ListModel packets_{kListRows}; ListModel presets_{kListRows + 1}; uint32_t shownSeq_ = 0; // the newest packet at the last redraw uint32_t selectedSeq_ = 0; // what the selection points at, kept as packets arrive bool followNewest_ = true; // until the user moves the selection off the top std::vector details_; int detailsTop_ = 0; uint32_t lastDrawMs_ = 0; std::string message_; uint32_t messageMs_ = 0; // Sweep, only while shown: peak hold per step, and the waterfall, newest row first. static constexpr int kWaterfallRows = 36; uint32_t shownSweep_ = 0; std::vector peak_; std::vector waterfall_; // kWaterfallRows x steps uint16_t sweepSteps_ = 0; }; } // namespace roro