rfbeam 0.4.10 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.streerc +1 -0
- data/.streerc~1f4cd14e3c0a9afdf972aa5f3982d36a89869b72 +2 -0
- data/.tool-versions +1 -1
- data/CHANGELOG.md +12 -0
- data/Gemfile.lock +2 -1
- data/Rakefile +8 -3
- data/cog.toml +24 -0
- data/lib/rfbeam/cli.rb +66 -15
- data/lib/rfbeam/kld7/cli_formatter.rb +15 -4
- data/lib/rfbeam/kld7/cli_output.rb +16 -7
- data/lib/rfbeam/kld7/constants.rb +61 -134
- data/lib/rfbeam/kld7/radar_messages.rb +46 -29
- data/lib/rfbeam/kld7/radar_parameters.rb +94 -50
- data/lib/rfbeam/kld7/streamer.rb +82 -0
- data/lib/rfbeam/version.rb +1 -1
- data/rfbeam.gemspec +3 -3
- data/streamer2.rb +55 -0
- data/streaming.rb +71 -0
- metadata +15 -10
- data/.streerc +0 -2
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'csv'
|
1
|
+
require "csv"
|
4
2
|
|
5
3
|
module RfBeam
|
6
4
|
module Kld7
|
@@ -12,26 +10,26 @@ module RfBeam
|
|
12
10
|
def rfft
|
13
11
|
request_frame_data(:rfft)
|
14
12
|
sleep MEASUREMENT_DELAY
|
15
|
-
data = read(1032).unpack(
|
13
|
+
data = read(1032).unpack("a4LS256S256")
|
16
14
|
header, length = data.shift(2)
|
17
|
-
|
15
|
+
unless header == "RFFT"
|
16
|
+
raise Error, "RFFT header response, header=#{header}"
|
17
|
+
end
|
18
18
|
raise Error, "RFFT payload length, length=#{length}" unless length == 1024
|
19
19
|
|
20
20
|
data
|
21
21
|
end
|
22
22
|
|
23
23
|
def reset
|
24
|
-
command = [
|
25
|
-
write command.pack(
|
24
|
+
command = ["RFSE", 0]
|
25
|
+
write command.pack("a4L")
|
26
26
|
check_response
|
27
27
|
end
|
28
28
|
alias rfse reset
|
29
29
|
|
30
30
|
def pdat(formatted: false)
|
31
31
|
request_frame_data(:pdat)
|
32
|
-
resp = read(102).unpack(
|
33
|
-
raise Error, "PDAT response = #{resp[0]}" unless resp[0] == 'PDAT'
|
34
|
-
|
32
|
+
resp = read(102).unpack("a4LSssSSssSSssSSssSSssSSssSSssSSssSSssSSssS")
|
35
33
|
return resp unless formatted
|
36
34
|
|
37
35
|
target_count = resp[1].to_i / 8
|
@@ -40,7 +38,9 @@ module RfBeam
|
|
40
38
|
resp.shift 2
|
41
39
|
resp.compact
|
42
40
|
detected_raw_targets = []
|
43
|
-
target_count.times
|
41
|
+
target_count.times do
|
42
|
+
detected_raw_targets << format_raw_target_data(resp.shift(4))
|
43
|
+
end
|
44
44
|
detected_raw_targets
|
45
45
|
end
|
46
46
|
|
@@ -48,34 +48,46 @@ module RfBeam
|
|
48
48
|
request_frame_data(:tdat)
|
49
49
|
sleep MEASUREMENT_DELAY
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
sleep 0.1
|
52
|
+
resp = read(16).unpack("a4LSssS")
|
53
|
+
unless resp[1].zero?
|
54
|
+
return { dist: resp[2], speed: resp[3], angle: resp[4], mag: resp[5] }
|
55
|
+
end
|
55
56
|
end
|
56
57
|
|
57
58
|
def ddat
|
58
59
|
request_frame_data(:ddat)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
60
|
+
flags = %w[Low High]
|
61
|
+
array = read(14).unpack("a4LC6")
|
62
|
+
{
|
63
|
+
label: array[0],
|
64
|
+
detection: array[2] == 1,
|
65
|
+
detection_str: DETECTION_FLAGS[:detection][array[2]],
|
66
|
+
micro_detection: DETECTION_FLAGS[:micro_detection][array[3]],
|
67
|
+
angle: DETECTION_FLAGS[:angle][array[4]],
|
68
|
+
direction: DETECTION_FLAGS[:direction][array[5]],
|
69
|
+
range: DETECTION_FLAGS[:range][array[6]],
|
70
|
+
speed: DETECTION_FLAGS[:speed][array[7]]
|
71
|
+
}
|
65
72
|
end
|
66
73
|
|
67
74
|
# Get the radar parameter structure
|
68
75
|
def grps
|
69
|
-
command = [
|
70
|
-
write command.pack(
|
76
|
+
command = ["GRPS", 0]
|
77
|
+
write command.pack("a4L")
|
71
78
|
check_response
|
72
|
-
read(50).unpack(
|
79
|
+
read(50).unpack("a4LA19C8c2C4cCCCCSCC")
|
73
80
|
end
|
74
81
|
|
75
82
|
def config
|
76
83
|
data = grps
|
77
|
-
output =
|
78
|
-
RADAR_PARAMETERS.
|
84
|
+
output = "\n"
|
85
|
+
RADAR_PARAMETERS.keys.each do |key|
|
86
|
+
output << formatted_parameter(
|
87
|
+
key,
|
88
|
+
data[RADAR_PARAMETERS[key].grps_index]
|
89
|
+
)
|
90
|
+
end
|
79
91
|
output
|
80
92
|
end
|
81
93
|
|
@@ -92,12 +104,17 @@ module RfBeam
|
|
92
104
|
private
|
93
105
|
|
94
106
|
def format_raw_target_data(array)
|
95
|
-
{
|
107
|
+
{
|
108
|
+
dist: array.shift,
|
109
|
+
speed: array.shift,
|
110
|
+
angle: array.shift,
|
111
|
+
mag: array.shift
|
112
|
+
}
|
96
113
|
end
|
97
114
|
|
98
115
|
def request_frame_data(type)
|
99
|
-
command = [
|
100
|
-
write command.pack(
|
116
|
+
command = ["GNFD", 4, FRAME_DATA_TYPES[type]]
|
117
|
+
write command.pack("a4LL")
|
101
118
|
check_response
|
102
119
|
end
|
103
120
|
end
|
@@ -1,7 +1,5 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module RfBeam
|
4
|
-
module
|
2
|
+
module KLD7
|
5
3
|
# -----------------
|
6
4
|
# Software Version, 'K-LD7_APP-RFB-XXXX'
|
7
5
|
# -----------------
|
@@ -20,11 +18,11 @@ module RfBeam
|
|
20
18
|
def base_frequency=(frequency = 1)
|
21
19
|
value =
|
22
20
|
case frequency
|
23
|
-
when 0, :low,
|
21
|
+
when 0, :low, "low"
|
24
22
|
0
|
25
|
-
when 1, :middle,
|
23
|
+
when 1, :middle, "middle"
|
26
24
|
1
|
27
|
-
when 2, :high,
|
25
|
+
when 2, :high, "high"
|
28
26
|
2
|
29
27
|
else
|
30
28
|
raise ArgumentError, "Invalid arg: '#{frequency}'"
|
@@ -43,8 +41,10 @@ module RfBeam
|
|
43
41
|
end
|
44
42
|
|
45
43
|
def max_speed=(speed = 1)
|
46
|
-
|
47
|
-
|
44
|
+
unless (0..3).include?(speed)
|
45
|
+
raise ArgumentError, "Invalid arg: '#{speed}'"
|
46
|
+
end
|
47
|
+
raise ArgumentError, "Expected an Integer" unless speed.is_a?(Integer)
|
48
48
|
|
49
49
|
set_parameter :rspi, speed, :uint32
|
50
50
|
end
|
@@ -60,8 +60,10 @@ module RfBeam
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def max_range=(range = 1)
|
63
|
-
|
64
|
-
|
63
|
+
unless (0..3).include?(range)
|
64
|
+
raise ArgumentError, "Invalid arg: '#{range}'"
|
65
|
+
end
|
66
|
+
raise ArgumentError, "Expected an Integer" unless range.is_a?(Integer)
|
65
67
|
|
66
68
|
set_parameter :rrai, range, :uint32
|
67
69
|
end
|
@@ -77,8 +79,10 @@ module RfBeam
|
|
77
79
|
end
|
78
80
|
|
79
81
|
def threshold_offset=(offset = 30)
|
80
|
-
|
81
|
-
|
82
|
+
unless (10..60).include?(offset)
|
83
|
+
raise ArgumentError, "Invalid arg: '#{offset}'"
|
84
|
+
end
|
85
|
+
raise ArgumentError, "Expected an Integer" unless offset.is_a?(Integer)
|
82
86
|
|
83
87
|
set_parameter :thof, offset, :uint32
|
84
88
|
end
|
@@ -95,7 +99,7 @@ module RfBeam
|
|
95
99
|
|
96
100
|
def tracking_filter=(type = 0)
|
97
101
|
raise ArgumentError, "Invalid arg: '#{type}'" unless (0..2).include?(type)
|
98
|
-
raise ArgumentError,
|
102
|
+
raise ArgumentError, "Expected an Integer" unless type.is_a?(Integer)
|
99
103
|
|
100
104
|
set_parameter :trft, type, :uint32
|
101
105
|
end
|
@@ -110,8 +114,10 @@ module RfBeam
|
|
110
114
|
end
|
111
115
|
|
112
116
|
def vibration_suppression=(value = 2)
|
113
|
-
|
114
|
-
|
117
|
+
unless (0..16).include?(value)
|
118
|
+
raise ArgumentError, "Invalid arg: '#{value}'"
|
119
|
+
end
|
120
|
+
raise ArgumentError, "Expected an Integer" unless value.is_a?(Integer)
|
115
121
|
|
116
122
|
set_parameter :visu, value, :uint32
|
117
123
|
end
|
@@ -126,8 +132,10 @@ module RfBeam
|
|
126
132
|
end
|
127
133
|
|
128
134
|
def min_detection_distance=(value = 0)
|
129
|
-
|
130
|
-
|
135
|
+
unless (0..100).include?(value)
|
136
|
+
raise ArgumentError, "Invalid arg: '#{value}'"
|
137
|
+
end
|
138
|
+
raise ArgumentError, "Expected an Integer" unless value.is_a?(Integer)
|
131
139
|
|
132
140
|
set_parameter :mira, value, :uint32
|
133
141
|
end
|
@@ -142,8 +150,10 @@ module RfBeam
|
|
142
150
|
end
|
143
151
|
|
144
152
|
def max_detection_distance=(value = 50)
|
145
|
-
|
146
|
-
|
153
|
+
unless (0..100).include?(value)
|
154
|
+
raise ArgumentError, "Invalid arg: '#{value}'"
|
155
|
+
end
|
156
|
+
raise ArgumentError, "Expected an Integer" unless value.is_a?(Integer)
|
147
157
|
|
148
158
|
set_parameter :mara, value, :uint32
|
149
159
|
end
|
@@ -158,8 +168,10 @@ module RfBeam
|
|
158
168
|
end
|
159
169
|
|
160
170
|
def min_detection_angle=(angle = -90)
|
161
|
-
|
162
|
-
|
171
|
+
unless (-90..90).include?(angle)
|
172
|
+
raise ArgumentError, "Invalid arg: '#{angle}'"
|
173
|
+
end
|
174
|
+
raise ArgumentError, "Expected an Integer" unless angle.is_a?(Integer)
|
163
175
|
|
164
176
|
set_parameter :mian, angle, :int32
|
165
177
|
end
|
@@ -174,8 +186,10 @@ module RfBeam
|
|
174
186
|
end
|
175
187
|
|
176
188
|
def max_detection_angle=(angle = 90)
|
177
|
-
|
178
|
-
|
189
|
+
unless (-90..90).include?(angle)
|
190
|
+
raise ArgumentError, "Invalid arg: '#{angle}'"
|
191
|
+
end
|
192
|
+
raise ArgumentError, "Expected an Integer" unless angle.is_a?(Integer)
|
179
193
|
|
180
194
|
set_parameter :maan, angle, :int32
|
181
195
|
end
|
@@ -190,8 +204,10 @@ module RfBeam
|
|
190
204
|
end
|
191
205
|
|
192
206
|
def min_detection_speed=(speed = 0)
|
193
|
-
|
194
|
-
|
207
|
+
unless (0..100).include?(speed)
|
208
|
+
raise ArgumentError, "Invalid arg: '#{speed}'"
|
209
|
+
end
|
210
|
+
raise ArgumentError, "Expected an Integer" unless speed.is_a?(Integer)
|
195
211
|
|
196
212
|
set_parameter :misp, speed, :uint32
|
197
213
|
end
|
@@ -206,8 +222,10 @@ module RfBeam
|
|
206
222
|
end
|
207
223
|
|
208
224
|
def max_detection_speed=(speed = 100)
|
209
|
-
|
210
|
-
|
225
|
+
unless (0..100).include?(speed)
|
226
|
+
raise ArgumentError, "Invalid arg: '#{speed}'"
|
227
|
+
end
|
228
|
+
raise ArgumentError, "Expected an Integer" unless speed.is_a?(Integer)
|
211
229
|
|
212
230
|
set_parameter :masp, speed, :uint32
|
213
231
|
end
|
@@ -222,8 +240,10 @@ module RfBeam
|
|
222
240
|
end
|
223
241
|
|
224
242
|
def detection_direction=(direction = 2)
|
225
|
-
|
226
|
-
|
243
|
+
unless (0..2).include?(direction)
|
244
|
+
raise ArgumentError, "Invalid arg: '#{direction}'"
|
245
|
+
end
|
246
|
+
raise ArgumentError, "Expected an Integer" unless direction.is_a?(Integer)
|
227
247
|
|
228
248
|
set_parameter :dedi, direction, :uint32
|
229
249
|
end
|
@@ -238,8 +258,10 @@ module RfBeam
|
|
238
258
|
end
|
239
259
|
|
240
260
|
def range_threshold=(value = 10)
|
241
|
-
|
242
|
-
|
261
|
+
unless (0..100).include?(value)
|
262
|
+
raise ArgumentError, "Invalid arg: '#{value}'"
|
263
|
+
end
|
264
|
+
raise ArgumentError, "Expected an Integer" unless value.is_a?(Integer)
|
243
265
|
|
244
266
|
set_parameter :rath, value, :uint32
|
245
267
|
end
|
@@ -254,8 +276,10 @@ module RfBeam
|
|
254
276
|
end
|
255
277
|
|
256
278
|
def angle_threshold=(value = 0)
|
257
|
-
|
258
|
-
|
279
|
+
unless (-90..90).include?(value)
|
280
|
+
raise ArgumentError, "Invalid arg: '#{value}'"
|
281
|
+
end
|
282
|
+
raise ArgumentError, "Expected an Integer" unless value.is_a?(Integer)
|
259
283
|
|
260
284
|
set_parameter :anth, value, :int32
|
261
285
|
end
|
@@ -270,8 +294,10 @@ module RfBeam
|
|
270
294
|
end
|
271
295
|
|
272
296
|
def speed_threshold=(value = 50)
|
273
|
-
|
274
|
-
|
297
|
+
unless (0..100).include?(value)
|
298
|
+
raise ArgumentError, "Invalid arg: '#{value}'"
|
299
|
+
end
|
300
|
+
raise ArgumentError, "Expected an Integer" unless value.is_a?(Integer)
|
275
301
|
|
276
302
|
set_parameter :spth, value, :uint32
|
277
303
|
end
|
@@ -286,8 +312,10 @@ module RfBeam
|
|
286
312
|
end
|
287
313
|
|
288
314
|
def digital_output1=(value = 0)
|
289
|
-
|
290
|
-
|
315
|
+
unless (0..4).include?(value)
|
316
|
+
raise ArgumentError, "Invalid arg: '#{value}'"
|
317
|
+
end
|
318
|
+
raise ArgumentError, "Expected an Integer" unless value.is_a?(Integer)
|
291
319
|
|
292
320
|
set_parameter :dig1, value, :uint32
|
293
321
|
end
|
@@ -302,8 +330,10 @@ module RfBeam
|
|
302
330
|
end
|
303
331
|
|
304
332
|
def digital_output2=(value = 1)
|
305
|
-
|
306
|
-
|
333
|
+
unless (0..4).include?(value)
|
334
|
+
raise ArgumentError, "Invalid arg: '#{value}'"
|
335
|
+
end
|
336
|
+
raise ArgumentError, "Expected an Integer" unless value.is_a?(Integer)
|
307
337
|
|
308
338
|
set_parameter :dig2, value, :uint32
|
309
339
|
end
|
@@ -318,8 +348,10 @@ module RfBeam
|
|
318
348
|
end
|
319
349
|
|
320
350
|
def digital_output3=(value = 2)
|
321
|
-
|
322
|
-
|
351
|
+
unless (0..4).include?(value)
|
352
|
+
raise ArgumentError, "Invalid arg: '#{value}'"
|
353
|
+
end
|
354
|
+
raise ArgumentError, "Expected an Integer" unless value.is_a?(Integer)
|
323
355
|
|
324
356
|
set_parameter :dig3, value, :uint32
|
325
357
|
end
|
@@ -334,8 +366,10 @@ module RfBeam
|
|
334
366
|
end
|
335
367
|
|
336
368
|
def hold_time=(time = 1)
|
337
|
-
|
338
|
-
|
369
|
+
unless (1..7200).include?(time)
|
370
|
+
raise ArgumentError, "Invalid arg: '#{time}'"
|
371
|
+
end
|
372
|
+
raise ArgumentError, "Expected an Integer" unless time.is_a?(Integer)
|
339
373
|
|
340
374
|
set_parameter :hold, time, :uint32
|
341
375
|
end
|
@@ -346,12 +380,16 @@ module RfBeam
|
|
346
380
|
# Micro Detection retrigger, 0 = Off (default), 1 = Retrigger
|
347
381
|
# -----------------
|
348
382
|
def micro_detection_retrigger
|
349
|
-
query_parameter RADAR_PARAMETERS[
|
383
|
+
query_parameter RADAR_PARAMETERS[
|
384
|
+
:set_micro_detection_retrigger
|
385
|
+
].grps_index
|
350
386
|
end
|
351
387
|
|
352
388
|
def micro_detection_retrigger=(value = 0)
|
353
|
-
|
354
|
-
|
389
|
+
unless (0..1).include?(value)
|
390
|
+
raise ArgumentError, "Invalid arg: '#{value}'"
|
391
|
+
end
|
392
|
+
raise ArgumentError, "Expected an Integer" unless value.is_a?(Integer)
|
355
393
|
|
356
394
|
set_parameter :mide, value, :uint32
|
357
395
|
end
|
@@ -366,8 +404,10 @@ module RfBeam
|
|
366
404
|
end
|
367
405
|
|
368
406
|
def micro_detection_sensitivity=(value = 4)
|
369
|
-
|
370
|
-
|
407
|
+
unless (0..9).include?(value)
|
408
|
+
raise ArgumentError, "Invalid arg: '#{value}'"
|
409
|
+
end
|
410
|
+
raise ArgumentError, "Expected an Integer" unless value.is_a?(Integer)
|
371
411
|
|
372
412
|
set_parameter :mids, value, :uint32
|
373
413
|
end
|
@@ -384,10 +424,14 @@ module RfBeam
|
|
384
424
|
def set_parameter(header, value, return_type = :uint32)
|
385
425
|
return_type =
|
386
426
|
case return_type
|
427
|
+
when :uint32
|
428
|
+
"L"
|
387
429
|
when :int32
|
388
|
-
|
430
|
+
"l"
|
431
|
+
when :uint32
|
432
|
+
"S"
|
389
433
|
else
|
390
|
-
|
434
|
+
"L"
|
391
435
|
end
|
392
436
|
command = [header.upcase.to_s, 4, value]
|
393
437
|
write command.pack("a4L#{return_type}")
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# rubocop:disable all
|
2
|
+
require "unicode_plot"
|
3
|
+
require "io/console"
|
4
|
+
require "stringio"
|
5
|
+
require "tty-screen"
|
6
|
+
|
7
|
+
module RfBeam
|
8
|
+
module KLD7
|
9
|
+
class Streamer
|
10
|
+
attr_accessor :radar
|
11
|
+
|
12
|
+
def initialize(radar)
|
13
|
+
@radar = radar
|
14
|
+
end
|
15
|
+
|
16
|
+
def monitor_keypress
|
17
|
+
loop do
|
18
|
+
key = STDIN.getch
|
19
|
+
if key.downcase == "q"
|
20
|
+
@stop_streaming = true
|
21
|
+
break
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def rfft
|
27
|
+
out = StringIO.new
|
28
|
+
def out.tty?
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
Thread.new { monitor_keypress }
|
33
|
+
|
34
|
+
loop do
|
35
|
+
out.truncate(0)
|
36
|
+
|
37
|
+
plot = rfft_plot(@radar)
|
38
|
+
plot.render(out)
|
39
|
+
|
40
|
+
lines = out.string.lines
|
41
|
+
lines.each { |line| $stdout.print "\r#{line}" }
|
42
|
+
$stdout.print "\e[0J"
|
43
|
+
$stdout.flush
|
44
|
+
break if @stop_streaming
|
45
|
+
|
46
|
+
n = lines.count
|
47
|
+
$stdout.print "\e[#{n}F"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def plot_data(data)
|
54
|
+
{
|
55
|
+
x: Array(-128...128),
|
56
|
+
series1: data.shift(256).map { |value| value / 100 },
|
57
|
+
series2: data.shift(256).map { |value| value.to_i / 100 }
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def rfft_plot(radar)
|
62
|
+
width = TTY::Screen.width * 0.65
|
63
|
+
data = plot_data(radar.rfft)
|
64
|
+
plot =
|
65
|
+
UnicodePlot.lineplot(
|
66
|
+
data[:x],
|
67
|
+
data[:series1],
|
68
|
+
name: "IF1/2 Averaged",
|
69
|
+
title: "Raw FFT",
|
70
|
+
height: 25,
|
71
|
+
width: width,
|
72
|
+
xlabel: "Speed (km/h)",
|
73
|
+
ylabel: "Signal (db)",
|
74
|
+
xlim: [-128, 128],
|
75
|
+
ylim: [0, 100]
|
76
|
+
)
|
77
|
+
UnicodePlot.lineplot!(plot, data[:x], data[:series2], name: "Threshold")
|
78
|
+
plot
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/rfbeam/version.rb
CHANGED
data/rfbeam.gemspec
CHANGED
@@ -10,15 +10,15 @@ Gem::Specification.new do |spec|
|
|
10
10
|
|
11
11
|
spec.summary = 'Ruby API and CLI for RFBeam doplar radar modules'
|
12
12
|
spec.description = 'Currently only tested with K-LD7 on MacOS & Raspian (bullseye)'
|
13
|
-
spec.homepage = 'https://
|
13
|
+
spec.homepage = 'https://github.com/robcarruthers/rfbeam'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
spec.required_ruby_version = '>= 3.1.2'
|
16
16
|
|
17
17
|
# spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
|
18
18
|
|
19
19
|
spec.metadata['homepage_uri'] = spec.homepage
|
20
|
-
spec.metadata['source_code_uri'] = 'https://
|
21
|
-
spec.metadata['changelog_uri'] = 'https://
|
20
|
+
spec.metadata['source_code_uri'] = 'https://github.com/robcarruthers/rfbeam'
|
21
|
+
spec.metadata['changelog_uri'] = 'https://github.com/robcarruthers/rfbeam/CHANGELOG.md'
|
22
22
|
|
23
23
|
# Specify which files should be added to the gem when it is released.
|
24
24
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
data/streamer2.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require "unicode_plot"
|
2
|
+
require "stringio"
|
3
|
+
require "io/console"
|
4
|
+
|
5
|
+
N = 1000
|
6
|
+
M = 50
|
7
|
+
|
8
|
+
def generate_random_data(n)
|
9
|
+
Array.new(n) { rand(-10.0..10.0) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def monitor_keypress
|
13
|
+
loop do
|
14
|
+
key = STDIN.getch
|
15
|
+
if key.downcase == "q"
|
16
|
+
@stop_streaming = true
|
17
|
+
break
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
out = StringIO.new
|
23
|
+
def out.tty?
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
Thread.new { monitor_keypress }
|
28
|
+
|
29
|
+
loop do
|
30
|
+
out.truncate(0)
|
31
|
+
|
32
|
+
plot =
|
33
|
+
UnicodePlot.lineplot(
|
34
|
+
generate_random_data(40),
|
35
|
+
name: "Series 0",
|
36
|
+
width: 120,
|
37
|
+
height: 30
|
38
|
+
)
|
39
|
+
UnicodePlot.lineplot!(
|
40
|
+
plot,
|
41
|
+
generate_random_data(40),
|
42
|
+
name: "Series 1",
|
43
|
+
color: :red
|
44
|
+
)
|
45
|
+
plot.render(out)
|
46
|
+
|
47
|
+
lines = out.string.lines
|
48
|
+
lines.each { |line| $stdout.print "\r#{line}" }
|
49
|
+
$stdout.print "\e[0J"
|
50
|
+
$stdout.flush
|
51
|
+
break if @stop_streaming
|
52
|
+
|
53
|
+
n = lines.count
|
54
|
+
$stdout.print "\e[#{n}F"
|
55
|
+
end
|
data/streaming.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# rubocop:disable all
|
2
|
+
require "unicode_plot"
|
3
|
+
require "io/console"
|
4
|
+
|
5
|
+
def generate_random_data(n)
|
6
|
+
Array.new(n) { rand(-10.0..10.0) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def update_data(plot, series1, series2)
|
10
|
+
plot.series_list[0].data.y = series1
|
11
|
+
plot.series_list[1].data.y = series2
|
12
|
+
plot.auto_calc_ylim
|
13
|
+
end
|
14
|
+
|
15
|
+
def start
|
16
|
+
Thread.new { monitor_keypress }
|
17
|
+
loop do
|
18
|
+
break if @stop_streaming
|
19
|
+
display_plot
|
20
|
+
sleep period
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def monitor_keypress
|
25
|
+
loop do
|
26
|
+
key = STDIN.getch
|
27
|
+
if key.downcase == "q"
|
28
|
+
@stop_streaming = true
|
29
|
+
break
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def plot_demo
|
35
|
+
out = StringIO.new
|
36
|
+
out.truncate(0)
|
37
|
+
plot =
|
38
|
+
UnicodePlot.lineplot(
|
39
|
+
generate_random_data(40),
|
40
|
+
name: "Series 0",
|
41
|
+
width: 40,
|
42
|
+
height: 10
|
43
|
+
)
|
44
|
+
|
45
|
+
UnicodePlot.lineplot!(
|
46
|
+
plot,
|
47
|
+
generate_random_data(40),
|
48
|
+
name: "Series 1",
|
49
|
+
color: :red
|
50
|
+
)
|
51
|
+
UnicodePlot.lineplot!(
|
52
|
+
plot,
|
53
|
+
generate_random_data(40),
|
54
|
+
name: "Series 2",
|
55
|
+
color: :blue
|
56
|
+
)
|
57
|
+
puts plot.render(out)
|
58
|
+
|
59
|
+
Thread.new { monitor_keypress }
|
60
|
+
|
61
|
+
loop do
|
62
|
+
break if @stop_streaming
|
63
|
+
|
64
|
+
lines = out.string.lines
|
65
|
+
lines.each { |line| $stdout.print "\r#{line}" }
|
66
|
+
$stdout.print "\e[0J"
|
67
|
+
$stdout.flush
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
plot_demo
|