Public Access
M3 step 4: the LoRa Scanner App, Sniffer and Captures
The Sniffer lists packets newest first (time, RSSI, SNR, and for Meshtastic the sender, receiver and hops), with the clear header and a hex dump on Enter (Q96); `p` picks an EU868 preset, kept in Settings (Q95). `c` starts a Capture: pcap with LoRaTap in /captures/lora, its own Clean-up category, recorded by a small Service so it carries on with the App closed (Q97, Q100). The Status Bar shows L while listening, bright on each packet, and CAP while capturing (Q101). StorageService gains raw appends for binary files. Debug Builds get `lora inject` to test all of this with no transmitter in range: a Capture made on the device reads back in TShark field for field. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
@@ -108,6 +108,7 @@ void RadioService::run() {
|
||||
void RadioService::startListening() {
|
||||
if (!ring_) {
|
||||
ring_.reset(new (std::nothrow) RadioPacket[kRing]);
|
||||
ringFirst_ = seq_ + 1;
|
||||
if (!ring_) {
|
||||
console.println("radio: not enough memory to listen");
|
||||
clients_ = 0;
|
||||
@@ -169,14 +170,33 @@ void RadioService::readPacket() {
|
||||
if (receive() != RADIOLIB_ERR_NONE) ++radioErrors_;
|
||||
++restarts_;
|
||||
|
||||
store(p);
|
||||
}
|
||||
|
||||
void RadioService::store(RadioPacket& p) {
|
||||
xSemaphoreTake(lock_, portMAX_DELAY);
|
||||
p.seq = seq_ + 1;
|
||||
if (ring_) ring_[p.seq % kRing] = p;
|
||||
seq_ = p.seq;
|
||||
xSemaphoreGive(lock_);
|
||||
++packets_;
|
||||
lastPacketMs_ = p.ms;
|
||||
}
|
||||
|
||||
#ifdef RORO_DEBUG
|
||||
void RadioService::inject(const uint8_t* data, size_t len, float rssi, float snr) {
|
||||
if (!listening_) return (void)console.println("lora inject: not listening");
|
||||
RadioPacket p;
|
||||
Config c = config();
|
||||
p.ms = millis();
|
||||
p.len = static_cast<uint8_t>(std::min(len, sizeof p.data));
|
||||
std::copy(data, data + p.len, p.data);
|
||||
p.rx = {c.frequencyHz, c.bandwidthKHz, c.spreadingFactor, rssi, snr, noise_, c.syncWord};
|
||||
store(p);
|
||||
console.printf("lora inject: #%lu, %u B\n", (unsigned long)p.seq, p.len);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Continuous receive. Only RX done raises DIO1; preambles and headers are only recorded in the
|
||||
// IRQ status, which sampleNoise() reads.
|
||||
int16_t RadioService::receive() {
|
||||
@@ -206,6 +226,12 @@ bool RadioService::packet(uint32_t seq, RadioPacket& out) const {
|
||||
return ok;
|
||||
}
|
||||
|
||||
uint32_t RadioService::available() const {
|
||||
uint32_t newest = seq_, first = ringFirst_;
|
||||
if (!listening_ || newest < first) return 0;
|
||||
return std::min<uint32_t>(newest - first + 1, kRing);
|
||||
}
|
||||
|
||||
void RadioService::listen(Client client, bool on) {
|
||||
if (on) clients_ |= client;
|
||||
else clients_ &= ~client;
|
||||
|
||||
Reference in New Issue
Block a user