Class: RTLSDR::Scanner
- Inherits:
-
Object
- Object
- RTLSDR::Scanner
- Defined in:
- lib/rtlsdr/scanner.rb
Overview
Frequency scanning and spectrum analysis
The Scanner class provides high-level frequency scanning capabilities for RTL-SDR devices. It automates the process of sweeping across frequency ranges, collecting samples, and analyzing signal characteristics. This is particularly useful for spectrum analysis, signal hunting, and surveillance applications.
Features:
- Configurable frequency range and step size
- Adjustable dwell time per frequency
- Synchronous and asynchronous scanning modes
- Peak detection with power thresholds
- Power sweep analysis
- Real-time result callbacks
- Thread-safe scanning control
Instance Attribute Summary collapse
-
#device ⇒ RTLSDR::Device
readonly
The RTL-SDR device being used for scanning.
-
#dwell_time ⇒ Float
readonly
Time to dwell on each frequency in seconds.
-
#end_freq ⇒ Integer
readonly
Ending frequency in Hz.
-
#start_freq ⇒ Integer
readonly
Starting frequency in Hz.
-
#step_size ⇒ Integer
readonly
Frequency step size in Hz.
Instance Method Summary collapse
-
#configure(start_freq: nil, end_freq: nil, step_size: nil, dwell_time: nil) ⇒ Scanner
Update scan configuration parameters.
-
#find_peaks(threshold: -60,, samples_per_freq: 1024) ⇒ Array<Hash>
Find signal peaks above a power threshold.
-
#frequencies ⇒ Array<Integer>
Get array of all frequencies to be scanned.
-
#frequency_count ⇒ Integer
Get total number of frequencies to be scanned.
-
#initialize(device, start_freq:, end_freq:, step_size: 1_000_000, dwell_time: 0.1) ⇒ Scanner
constructor
Create a new frequency scanner.
-
#inspect ⇒ String
Return string representation of scanner.
-
#power_sweep(samples_per_freq: 1024) ⇒ Array<Array>
Perform a power sweep across the frequency range.
-
#scan(samples_per_freq: 1024) {|Hash| ... } ⇒ Hash
Perform a frequency sweep scan.
-
#scan_async(samples_per_freq: 1024) {|Hash| ... } ⇒ Thread
Perform asynchronous frequency sweep scan.
-
#scanning? ⇒ Boolean
Check if a scan is currently in progress.
-
#stop ⇒ Boolean
Stop the current scan operation.
Constructor Details
#initialize(device, start_freq:, end_freq:, step_size: 1_000_000, dwell_time: 0.1) ⇒ Scanner
Create a new frequency scanner
66 67 68 69 70 71 72 73 |
# File 'lib/rtlsdr/scanner.rb', line 66 def initialize(device, start_freq:, end_freq:, step_size: 1_000_000, dwell_time: 0.1) @device = device @start_freq = start_freq @end_freq = end_freq @step_size = step_size @dwell_time = dwell_time @scanning = false end |
Instance Attribute Details
#device ⇒ RTLSDR::Device (readonly)
Returns The RTL-SDR device being used for scanning.
41 42 43 |
# File 'lib/rtlsdr/scanner.rb', line 41 def device @device end |
#dwell_time ⇒ Float (readonly)
Returns Time to dwell on each frequency in seconds.
49 50 51 |
# File 'lib/rtlsdr/scanner.rb', line 49 def dwell_time @dwell_time end |
#end_freq ⇒ Integer (readonly)
Returns Ending frequency in Hz.
45 46 47 |
# File 'lib/rtlsdr/scanner.rb', line 45 def end_freq @end_freq end |
#start_freq ⇒ Integer (readonly)
Returns Starting frequency in Hz.
43 44 45 |
# File 'lib/rtlsdr/scanner.rb', line 43 def start_freq @start_freq end |
#step_size ⇒ Integer (readonly)
Returns Frequency step size in Hz.
47 48 49 |
# File 'lib/rtlsdr/scanner.rb', line 47 def step_size @step_size end |
Instance Method Details
#configure(start_freq: nil, end_freq: nil, step_size: nil, dwell_time: nil) ⇒ Scanner
Update scan configuration parameters
Allows modification of scan parameters after the scanner has been created. Only non-nil parameters will be updated.
244 245 246 247 248 249 250 |
# File 'lib/rtlsdr/scanner.rb', line 244 def configure(start_freq: nil, end_freq: nil, step_size: nil, dwell_time: nil) @start_freq = start_freq if start_freq @end_freq = end_freq if end_freq @step_size = step_size if step_size @dwell_time = dwell_time if dwell_time self end |
#find_peaks(threshold: -60,, samples_per_freq: 1024) ⇒ Array<Hash>
Find signal peaks above a power threshold
Scans the frequency range and returns all frequencies where the signal power exceeds the specified threshold. Results are sorted by power in descending order (strongest signals first).
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/rtlsdr/scanner.rb', line 173 def find_peaks(threshold: -60, samples_per_freq: 1024) peaks = [] scan(samples_per_freq: samples_per_freq) do |result| power_db = 10 * Math.log10(result[:power] + 1e-10) if power_db > threshold peaks << { frequency: result[:frequency], power: result[:power], power_db: power_db, timestamp: result[:timestamp] } end end peaks.sort_by { |peak| -peak[:power] } end |
#frequencies ⇒ Array<Integer>
Get array of all frequencies to be scanned
81 82 83 |
# File 'lib/rtlsdr/scanner.rb', line 81 def frequencies (@start_freq..@end_freq).step(@step_size).to_a end |
#frequency_count ⇒ Integer
Get total number of frequencies to be scanned
88 89 90 |
# File 'lib/rtlsdr/scanner.rb', line 88 def frequency_count ((end_freq - start_freq) / step_size).to_i + 1 end |
#inspect ⇒ String
Return string representation of scanner
255 256 257 |
# File 'lib/rtlsdr/scanner.rb', line 255 def inspect "#<RTLSDR::Scanner #{@start_freq / 1e6}MHz-#{@end_freq / 1e6}MHz step=#{@step_size / 1e6}MHz dwell=#{@dwell_time}s>" # rubocop:disable Layout/LineLength end |
#power_sweep(samples_per_freq: 1024) ⇒ Array<Array>
Perform a power sweep across the frequency range
Scans all frequencies and returns an array of [frequency, power_db] pairs. This is useful for generating spectrum plots or finding the overall power distribution across a frequency band.
204 205 206 207 208 209 210 211 212 213 |
# File 'lib/rtlsdr/scanner.rb', line 204 def power_sweep(samples_per_freq: 1024) results = [] scan(samples_per_freq: samples_per_freq) do |result| power_db = 10 * Math.log10(result[:power] + 1e-10) results << [result[:frequency], power_db] end results end |
#scan(samples_per_freq: 1024) {|Hash| ... } ⇒ Hash
Perform a frequency sweep scan
Scans through all frequencies in the configured range, collecting samples and calling the provided block for each frequency. The block receives a hash with frequency, power, samples, and timestamp information.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/rtlsdr/scanner.rb', line 107 def scan(samples_per_freq: 1024, &block) raise ArgumentError, "Block required for scan" unless block_given? @scanning = true results = {} frequencies.each do |freq| break unless @scanning @device.center_freq = freq sleep(@dwell_time) samples = @device.read_samples(samples_per_freq) power = DSP.average_power(samples) result = { frequency: freq, power: power, samples: samples, timestamp: Time.now } results[freq] = result block.call(result) end @scanning = false results end |
#scan_async(samples_per_freq: 1024) {|Hash| ... } ⇒ Thread
Perform asynchronous frequency sweep scan
Same as #scan but runs in a separate thread, allowing the calling thread to continue execution while scanning proceeds in the background.
151 152 153 154 155 156 157 |
# File 'lib/rtlsdr/scanner.rb', line 151 def scan_async(samples_per_freq: 1024, &block) raise ArgumentError, "Block required for async scan" unless block_given? Thread.new do scan(samples_per_freq: samples_per_freq, &block) end end |
#scanning? ⇒ Boolean
Check if a scan is currently in progress
228 229 230 |
# File 'lib/rtlsdr/scanner.rb', line 228 def scanning? @scanning end |
#stop ⇒ Boolean
Stop the current scan operation
Sets the scanning flag to false, which will cause any active scan to terminate after the current frequency step completes.
221 222 223 |
# File 'lib/rtlsdr/scanner.rb', line 221 def stop @scanning = false end |