rfbeam 0.3.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 698385739f70574b698a117af8c749a21ebd75d9c3b0abaa39447ebd869324ef
4
- data.tar.gz: 11f47d264d76f5a5b968c8f7cb49152602359383e8a0cf20a16564a2b2e808f3
3
+ metadata.gz: 19f39170dee64099fe6806a345393beff434035df70fe525fa31b361468cac9e
4
+ data.tar.gz: 622aba1c5ab9f85fdb8cadf90f10339344306db39ab9299b2ef8b437d228d82d
5
5
  SHA512:
6
- metadata.gz: 58b01ae8497458e6e4f238afcc64a38cd925312e7893b4e65a854407f34694493b002e5721a9980129d586370cc51abfca5e5cd238a51cf33dfb890f40992479
7
- data.tar.gz: 48934f301cb4eb9ac2cdb695d08dfd544cc9e6ea16f130ab6b30b182c35ee1630d5ad2574c4bab081656f51ce4208857c92a2dfd6d2925639c303a3c66c0d1ae
6
+ metadata.gz: 57bd136ef560a32dab06e08c841b44e6e1b192525d9d3d44db1a88885c0b30b9b9b28ab28b1f408d628e191195373a012d31405ae24372fa4efd76ecbb3af46c
7
+ data.tar.gz: 5dc08c9c71c511e210a4c30599248bb5be53f1ccd7373af73edeb1ff35043dc76b90235bf46de93b9b755123af598225d6b96f06f6c0c5ab89bf4d1bc2e81d57
data/.rubocop.yml CHANGED
@@ -2,10 +2,16 @@ inherit_from:
2
2
  - node_modules/@prettier/plugin-ruby/rubocop.yml
3
3
 
4
4
  AllCops:
5
- TargetRubyVersion: 2.6
5
+ TargetRubyVersion: 3.2
6
6
 
7
7
  Layout/LineLength:
8
8
  Max: 120
9
9
 
10
+ Metrics/ModuleLength:
11
+ Enabled: false
12
+
13
+ Metrics/MethodLength:
14
+ Max: 20
15
+
10
16
  Documentation:
11
17
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,6 +1,16 @@
1
+ ## [0.4.0] - 2023-4-4
2
+
3
+ - rough CLI implementation
4
+ - Streaming rfft data, with plot output
5
+
6
+ ## [0.3.5] - 2023-4-1
7
+
8
+ - Updated Radar parameter accessors
9
+ - Added parameter setter arg validation and errors
10
+
1
11
  ## [0.3.4] - 2023-3-28
2
12
 
3
- - Added a formatted option to pdat
13
+ - Added a formatted option to pdat
4
14
 
5
15
  ## [0.3.2] - 2023-3-28
6
16
 
data/Gemfile CHANGED
@@ -10,3 +10,13 @@ gem "rake", "~> 13.0"
10
10
  gem "minitest", "~> 5.0"
11
11
 
12
12
  gem "rubocop", "~> 1.21"
13
+
14
+ gem "tty-table", "~> 0.12.0"
15
+
16
+ gem "tty-spinner", "~> 0.9.3"
17
+
18
+ gem "unicode_plot", "~> 0.0.5"
19
+
20
+ gem "tty-logger", "~> 0.6.0"
21
+
22
+ gem "tty-screen", "~> 0.8.1"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rfbeam (0.3.4)
4
+ rfbeam (0.4.0)
5
5
  activesupport (~> 6.1.0)
6
6
  rubyserial (~> 0.6.0)
7
7
  thor (~> 1.2.1)
@@ -17,6 +17,7 @@ GEM
17
17
  zeitwerk (~> 2.3)
18
18
  ast (2.4.2)
19
19
  concurrent-ruby (1.1.10)
20
+ enumerable-statistics (2.0.7)
20
21
  ffi (1.15.5)
21
22
  i18n (1.12.0)
22
23
  concurrent-ruby (~> 1.0)
@@ -25,6 +26,8 @@ GEM
25
26
  parallel (1.22.1)
26
27
  parser (3.1.3.0)
27
28
  ast (~> 2.4.1)
29
+ pastel (0.8.0)
30
+ tty-color (~> 0.5)
28
31
  rainbow (3.1.1)
29
32
  rake (13.0.6)
30
33
  regexp_parser (2.6.1)
@@ -44,10 +47,29 @@ GEM
44
47
  ruby-progressbar (1.11.0)
45
48
  rubyserial (0.6.0)
46
49
  ffi (~> 1.9, >= 1.9.3)
50
+ strings (0.2.1)
51
+ strings-ansi (~> 0.2)
52
+ unicode-display_width (>= 1.5, < 3.0)
53
+ unicode_utils (~> 1.4)
54
+ strings-ansi (0.2.0)
47
55
  thor (1.2.1)
56
+ tty-color (0.6.0)
57
+ tty-cursor (0.7.1)
58
+ tty-logger (0.6.0)
59
+ pastel (~> 0.8)
60
+ tty-screen (0.8.1)
61
+ tty-spinner (0.9.3)
62
+ tty-cursor (~> 0.7)
63
+ tty-table (0.12.0)
64
+ pastel (~> 0.8)
65
+ strings (~> 0.2.0)
66
+ tty-screen (~> 0.8)
48
67
  tzinfo (2.0.5)
49
68
  concurrent-ruby (~> 1.0)
50
69
  unicode-display_width (2.3.0)
70
+ unicode_plot (0.0.5)
71
+ enumerable-statistics (>= 2.0.1)
72
+ unicode_utils (1.4.0)
51
73
  zeitwerk (2.6.6)
52
74
 
53
75
  PLATFORMS
@@ -59,6 +81,11 @@ DEPENDENCIES
59
81
  rake (~> 13.0)
60
82
  rfbeam!
61
83
  rubocop (~> 1.21)
84
+ tty-logger (~> 0.6.0)
85
+ tty-screen (~> 0.8.1)
86
+ tty-spinner (~> 0.9.3)
87
+ tty-table (~> 0.12.0)
88
+ unicode_plot (~> 0.0.5)
62
89
 
63
90
  BUNDLED WITH
64
91
  2.4.10
data/README.md CHANGED
@@ -1,7 +1,11 @@
1
1
  # Rfbeam
2
2
 
3
- RfBeam is a simple, high-level interface to the RFBeam radar modules.
4
- The user can read and set the radar parameters and fetch raw or processed data frames from the sensor.
3
+ ![Gem](https://img.shields.io/gem/v/rfbeam?color=green&label=version)
4
+ ![Ruby](https://img.shields.io/static/v1?message=Ruby&color=red&logo=Ruby&logoColor=FFFFFF&label=v3.2.1)
5
+ ![Ruby](https://img.shields.io/gitlab/license/robcarruthers/rfbeam?color=orange)
6
+
7
+ RfBeam is a simple, high-level interface for the RFBeam radar modules.
8
+ The user can query process and raw detection data and set the radar parameters for the sensor.
5
9
 
6
10
  At this stage it only works on Linux and Mac with the K-LD7 module.
7
11
 
@@ -63,28 +67,29 @@ Returns a formatted String of all parameter settings. The only way to read param
63
67
 
64
68
  radar.config
65
69
 
66
- Software Version: K-LD7_APP-RFB-0103
67
- Base Frequency: Middle
68
- Max Speed: 25km/h
69
- Max Range: 10m
70
- Threshold offset: 30db
71
- Tracking Filter Type: standard
72
- Vibration Suppression: 2 , (0-16, 0 = No Suppression, 16 = High Suppression)
73
- Minimum Detection Distance: 0 , (0 - 100% of range setting)
74
- Maximum Detection Distance: 50 , (0 - 100% of range setting)
75
- Minimum Detection Angle: -90° , (-90° - 90°)
76
- Maximum Detection Angle: 90° , (0 - 100% of range setting)
77
- Maximum Detection Speed: 0 , (0 - 100% of speed setting)
78
- Maximum Detection Speed: 100 , (0 - 100% of speed setting)
79
- Detection Direction: 2Range Threshold: 10%, (0 - 100% of range setting)
80
- Angle Threshold: 0°, (-90° - 90°)
81
- Speed Threshold: 50%, (0 - 100% of speed setting)
82
- Digital output 1: Direction
83
- Digital output 2: Angle
84
- Digital output 3: Range
85
- Hold time: 1sec
86
- Micro Detection Retrigger: Off
87
- Micro Detection Sensitivity: 4 (0 - 9, 0 = Min, 9 = Max)
70
+ Software Version: K-LD7_APP-RFB-0103
71
+ Base Frequency: Low
72
+ Maximum Speed: 100km/h
73
+ Maximum Range: 100m
74
+ Threshold Offset: 30db
75
+ Tracking Filter Type: Long Visibility
76
+ Vibration Suppression: 16
77
+ Minimum Detection Distance: 0%
78
+ Maximum Detection Distance: 100%
79
+ Minimum Detection Angle: -10°
80
+ Maximum Detection Angle: 90°
81
+ Minimum Detection Speed: 0%
82
+ Maximum Detection Speed: 100%
83
+ Detection Direction: Both
84
+ Range Threshold: 10%
85
+ Angle Threshold: 0°
86
+ Speed Threshold: 50%
87
+ Digital Output 1: Direction
88
+ Digital Output 2: Angle
89
+ Digital Output 3: Range
90
+ Hold Time: 1s
91
+ Micro Detection Trigger: Off
92
+ Micro Detection Sensativity: 4
88
93
 
89
94
  ## Parameter setters
90
95
 
data/exe/rfbeam ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rfbeam'
4
+
5
+ RfBeam::CLI.start(ARGV)
data/lib/rfbeam/cli.rb ADDED
@@ -0,0 +1,130 @@
1
+ # rubocop:disable all
2
+ require 'thor'
3
+ require 'rfbeam'
4
+ require 'tty-table'
5
+ require 'tty-logger'
6
+ require 'tty-spinner'
7
+ require 'io/console'
8
+ require 'unicode_plot'
9
+
10
+ module RfBeam
11
+ class CLI < Thor
12
+
13
+ attr_accessor :radar, :logger
14
+
15
+ desc 'list', 'List available radar modules'
16
+ def list
17
+ devices = RfBeam.connected
18
+ @logger.warning 'No Radar modules found.' unless devices.count.positive?
19
+
20
+ table = TTY::Table.new( header: ['id', 'Path', 'Version'])
21
+
22
+ devices.each.with_index do |path, index|
23
+ table << ["R#{index}", path, @radar.sw_version]
24
+ end
25
+ puts table.render(:ascii)
26
+ end
27
+
28
+ desc 'config <radar_id>', 'Shows the parameter setting for the Radar module'
29
+ def config(radar_id)
30
+ init_radar(radar_id)
31
+ puts @radar.config
32
+ end
33
+
34
+ desc 'set_param <radar_id> <key> <value>', 'Set radar parameters, see readme for keys'
35
+ def set_param(radar_id, param, value)
36
+ return logger.warning("Invalid param: '#{param}'") unless RfBeam::K_ld7::RADAR_PARAMETERS.include?(param.to_sym)
37
+
38
+ init_radar radar_id
39
+ @radar.send("#{param}=", value.to_i)
40
+ logger.success "Set #{@radar.formatted_parameter(param.to_sym)}"
41
+ end
42
+
43
+ desc 'ddat <radar_id>', 'stream any valid detections, stop stream with q and enter'
44
+ option :stream, type: :boolean, aliases: '-s', desc: "Stream the data from the device"
45
+ def ddat(radar_id)
46
+ init_radar radar_id
47
+
48
+ if options[:stream]
49
+ Thread.new { monitor_keypress }
50
+ spinner = TTY::Spinner.new("[:spinner] :title ", format: :bouncing_ball)
51
+ loop do
52
+ break if @stop_streaming
53
+ spinner.spin
54
+ data = @radar.ddat
55
+ spinner.update title: "Searching... #{data}"
56
+ spinner.success @radar.tdat if data[2] == 1
57
+ end
58
+ spinner.stop
59
+ puts "\nTask Quit."
60
+ else
61
+ puts "\n#{@radar.ddat}"
62
+ end
63
+
64
+ end
65
+
66
+ desc 'pdat <radar_id>', 'Display Tracked Targets'
67
+ def pdat(radar_id)
68
+ init_radar radar_id
69
+ puts @radar.pdat
70
+ end
71
+
72
+ desc "rfft <radar_id>", "Display the dopplar radar data as a plot"
73
+ option :stream, type: :boolean, aliases: '-s', desc: "Stream the data from the device"
74
+ option :period, type: :numeric, aliases: '-p', default: 0.5, desc: "Update period (in seconds) for the streaming data"
75
+ def rfft(radar_id)
76
+ init_radar(radar_id)
77
+
78
+ if options[:stream]
79
+ streamer = RfBeam::KLD7::Streamer.new(@radar)
80
+ streamer.rfft
81
+ else
82
+ plot = rfft_plot(@radar)
83
+ p plot.render
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ def init_radar(id)
90
+ devices = RfBeam.connected
91
+ @logger = TTY::Logger.new
92
+ return @logger.warning 'No Radar modules found.' unless devices.count.positive?
93
+
94
+ @radar = RfBeam::K_ld7.new(devices[id.to_i])
95
+ end
96
+
97
+ def plot_data(data)
98
+ { x: Array(-128...128), series1: data.shift(256).map { |value| value / 100 }, series2: data.shift(256).map { |value| value.to_i / 100 } }
99
+ end
100
+
101
+ def monitor_keypress
102
+ loop do
103
+ key = STDIN.getch
104
+ if key.downcase == 'q'
105
+ @stop_streaming = true
106
+ break
107
+ end
108
+ end
109
+ end
110
+
111
+ def rfft_plot(radar)
112
+ speed = radar.max_speed
113
+ speed_label = radar.formatted_parameter(:max_speed)
114
+ xlim = [speed - speed * 2, speed]
115
+ data = plot_data(radar.rfft)
116
+ plot = UnicodePlot.lineplot(
117
+ data[:x],
118
+ data[:series1],
119
+ name: 'IF1/2 Averaged',
120
+ title: 'Raw FFT',
121
+ height: 25,
122
+ width: 120,
123
+ xlabel: "Speed (km/h), #{speed_label}",
124
+ ylabel: 'Signal (db)', xlim: [-128, 128],
125
+ ylim: [0, 100])
126
+ UnicodePlot.lineplot!(plot, data[:x], data[:series2], name: "Threshold")
127
+ plot
128
+ end
129
+ end
130
+ end
@@ -11,7 +11,7 @@ module RfBeam
11
11
  3 => 'Invalid RPST version',
12
12
  4 => 'Uart error (parity, framing, noise)',
13
13
  5 => 'Sensor busy',
14
- 6 => 'Timeout error',
14
+ 6 => 'Timeout error'
15
15
  }.freeze
16
16
 
17
17
  # The response delay was determined empirically and may need adjusting with baude rate
@@ -27,59 +27,39 @@ module RfBeam
27
27
  angle: %w[Left Right],
28
28
  direction: %w[Receding Approaching],
29
29
  range: %w[Far Near],
30
- speed: %w[Low High],
31
- }.freeze
32
-
33
- # GRPS - Parameter structure, used to map return values to readable strings
34
- PARAMETER_STRUCTURE = {
35
- base_frequency: ['Low', 'Middle', 'High'],
36
- max_speed: ['12.5km/h', '25km/h', '50km/h', '100km/h'],
37
- max_range: %w[5m 10m 30m 100m],
38
- threshold_offset: '10db - 60db',
39
- tracking_filter_type: ['standard', 'Fast Detection', 'Long Visibility'],
40
- vibration_suppression: '0-16, 0 = No Suppression, 16 = High Suppression',
41
- min_detection_distance: '0 - 100% of range setting',
42
- max_detection_distance: '0 - 100% of range setting',
43
- min_detection_angle: '-90° - 90°',
44
- max_detection_angle: '-90° - 90°',
45
- min_detection_speed: '0 - 100% of speed setting',
46
- max_detection_speed: '0 - 100% of speed setting',
47
- detection_direction: %w[receding approaching both],
48
- range_threshold: '0 - 100% of range setting',
49
- angle_threshold: '-90° - 90°',
50
- speed_threshold: '0 - 100% of speed setting',
51
- digital_output_1: %w[Direction Angle Range Speed Micro],
52
- digital_output_2: %w[Direction Angle Range Speed Micro],
53
- digital_output_3: %w[Direction Angle Range Speed Micro],
54
- hold_time: '1 - 7200s',
55
- micro_detection_trigger: %w[Off Retrigger],
56
- micro_detection_sensitivity: '0 - 9, 0 = Min, 9 = Max'
30
+ speed: %w[Low High]
31
+ }.freeze
32
+
33
+ Param = Data.define(:name, :grps_index, :description, :default, :units, :values) do |_param|
34
+ def initialize(name:, grps_index:, description: nil, default: nil, units: nil, values: [])
35
+ super(name:, grps_index:, description:, default:, units:, values:)
36
+ end
37
+ end
38
+
39
+ RADAR_PARAMETERS = {
40
+ sw_version: Param.new(name: 'Software Version', grps_index: 2, default: 'K-LD7_APP-RFB-XXXX'),
41
+ base_frequency: Param.new( name: 'Base Frequency', grps_index: 3, description: '0 = Low, 1 = Middle, 2 = High', default: 1, values: ['Low', 'Middle', 'High'] ),
42
+ max_speed: Param.new( name: 'Maximum Speed', grps_index: 4, description: '0 = 12km/h, 1 = 25km/h, 2 = 50km/h, 3 = 100km/h', default: 1, units: 'km/h', values: ['12.5', '25', '50', '100'] ),
43
+ max_range: Param.new( name: 'Maximum Range', grps_index: 5, description: '0 = 5m, 1 = 10m, 2 = 30m, 3 = 100m', default: 1, values: %w[5m 10m 30m 100m] ),
44
+ threshold_offset: Param.new( name: 'Threshold Offset', grps_index: 6, description: '10db - 60db', default: 30, units: 'db' ),
45
+ tracking_filter: Param.new( name: 'Tracking Filter Type', grps_index: 7, description: '0 = Standard, 2 = Fast Detection, 3 = Long Visibility', default: 0, values: ['standard', 'Fast Detection', 'Long Visibility'] ),
46
+ vibration_suppression: Param.new( name: 'Vibration Suppression', grps_index: 8, description: '0-16, 0 = No Suppression, 16 = High Suppression', default: 2 ),
47
+ min_detection_distance: Param.new( name: 'Minimum Detection Distance', grps_index: 9, description: '0 - 100% of range setting', default: 0, units: '%' ),
48
+ max_detection_distance: Param.new( name: 'Maximum Detection Distance', grps_index: 10, description: '0 - 100% of range setting', default: 50, units: '%' ),
49
+ min_detection_angle: Param.new( name: 'Minimum Detection Angle', grps_index: 11, description: '-90° - 90°', default: -90, units: '°' ),
50
+ max_detection_angle: Param.new( name: 'Maximum Detection Angle', grps_index: 12, description: '-90° - 90°', default: 90, units: '°' ),
51
+ min_detection_speed: Param.new( name: 'Minimum Detection Speed', grps_index: 13, description: '0 - 100% of speed setting', default: 0, units: '%' ),
52
+ max_detection_speed: Param.new( name: 'Maximum Detection Speed', grps_index: 14, description: '0 - 100% of speed setting', default: 100, units: '%' ),
53
+ detection_direction: Param.new( name: 'Detection Direction', grps_index: 15, description: '0 = Receding, 1 = Approaching, 2 = Both', default: 2, values: %w[Receding Approaching Both] ),
54
+ range_threshold: Param.new( name: 'Range Threshold', grps_index: 16, description: '0 - 100% of range setting', default: 10, units: '%' ),
55
+ angle_threshold: Param.new( name: 'Angle Threshold', grps_index: 17, description: '-90° - 90°', default: 0, units: '°' ),
56
+ speed_threshold: Param.new( name: 'Speed Threshold', grps_index: 18, description: '0 - 100% of speed setting', default: 50, units: '%' ),
57
+ digital_output1: Param.new( name: 'Digital Output 1', grps_index: 19, description: '0 = Direction, 1 = Angle, 2 = Range, 3 = Speed, 4 = Micro Detection', default: 0, values: %w[Direction Angle Range Speed Micro] ),
58
+ digital_output2: Param.new( name: 'Digital Output 2', grps_index: 20, description: '0 = Direction, 1 = Angle, 2 = Range, 3 = Speed, 4 = Micro Detection', default: 1, values: %w[Direction Angle Range Speed Micro] ),
59
+ digital_output3: Param.new( name: 'Digital Output 3', grps_index: 21, description: '0 = Direction, 1 = Angle, 2 = Range, 3 = Speed, 4 = Micro Detection', default: 2, values: %w[Direction Angle Range Speed Micro] ),
60
+ hold_time: Param.new( name: 'Hold Time', grps_index: 22, description: '1 - 7200s', default: 1, units: 's' ),
61
+ micro_detection_retrigger: Param.new( name: 'Micro Detection Trigger', grps_index: 23, description: '0 = Off, 1 = Retrigger', default: 0, values: %w[Off Retrigger] ),
62
+ micro_detection_sensativity: Param.new( name: 'Micro Detection Sensativity', grps_index: 24, description: '0 - 9, 0 = Min, 9 = Max', default: 4 )
57
63
  }.freeze
58
-
59
- # PARAMETERS = {
60
- # sw_version: { grps_index: 2, default: 'K-LD7_APP-RFB-XXXX' },
61
- # base_frequency: { grps_index: 3, description: '0 = Low, 1 = Middle, 2 = High', default: '1 - Middle', values: ['Low', 'Middle', 'High'] },
62
- # max_speed: { grps_index: 4, description: '0 = 12km/h, 1 = 25km/h, 2 = 50km/h, 3 = 100km/h, default: 1', values: ['12.5km/h', '25km/h', '50km/h', '100km/h'] },
63
- # max_range: { grps_index: 5, description: '0 = 5m, 1 = 10m, 2 = 30m, 3 = 100m, default: 1', values: %w[5m 10m 30m 100m] },
64
- # threshold_offset: { grps_index: 6, description: '10db - 60db, default: 30', values: '10db - 60db' },
65
- # tracking_filter_type: { grps_index: 7, description: '0 = Standard, 2 = Fast Detection, 3 = Long Visibility, default: 0', values: ['standard', 'Fast Detection', 'Long Visibility'] },
66
- # vibration_suppression: { grps_index: 8, description: '0-16, 0 = No Suppression, 16 = High Suppression, default: 2' },
67
- # min_detection_distance: { grps_index: 3, description: '0 - 100% of range setting, default: 0' },
68
- # max_detection_distance: { grps_index: 10, description: '0 - 100% of range setting, default: 50' },
69
- # min_detection_angle: { grps_index: 11, description: '-90° - 90°, default: -90' },
70
- # max_detection_angle: { grps_index: 12, description: '-90° - 90°, default: 90' },
71
- # min_detection_speed: { grps_index: 13, description: '0 - 100% of speed setting, default: 0' },
72
- # max_detection_speed: { grps_index: 14, description: '0 - 100% of speed setting, default: 100' },
73
- # detection_direction: { grps_index: 15, description: '0 = Receding, 1 = Approaching, 2 = Both, default: 2', values: %w[receding approaching both] },
74
- # range_threshold: { grps_index: 16, description: '0 - 100% of range setting, default: 10', values: '0 - 100% of range setting' },
75
- # angle_threshold: { grps_index: 17, description: '-90° - 90°, default: 0' },
76
- # speed_threshold: { grps_index: 18, description: '0 - 100% of speed setting, default: 50' },
77
- # digital_output_1: { grps_index: 19, description: '0 = Direction, 1 = Angle, 2 = Range, 3 = Speed, 4 = Micro Detection, default: 0', values: %w[Direction Angle Range Speed Micro] },
78
- # digital_output_2: { grps_index: 20, description: '0 = Direction, 1 = Angle, 2 = Range, 3 = Speed, 4 = Micro Detection, default: 1', values: %w[Direction Angle Range Speed Micro] },
79
- # digital_output_3: { grps_index: 21, description: '0 = Direction, 1 = Angle, 2 = Range, 3 = Speed, 4 = Micro Detection, default: 2', values: %w[Direction Angle Range Speed Micro] },
80
- # hold_time: { grps_index: 22, description: '1 - 7200s, default: 1', values: '1 - 7200s' },
81
- # micro_detection_trigger: { grps_index: 23, description: '0 = Off, 1 = Retrigger, default: 0' },
82
- # micro_detection_sensitivity: { grps_index: 24, description: '0 - 9, 0 = Min, 9 = Max, default: 4' }'
83
- # }
84
64
  end
85
65
  end
@@ -0,0 +1,94 @@
1
+ require 'csv'
2
+
3
+ module RfBeam
4
+ module KLD7
5
+ def detection?
6
+ data = ddat
7
+ (data[2] == 1)
8
+ end
9
+
10
+ def rfft
11
+ request_frame_data(:rfft)
12
+
13
+ resp = read(1032).unpack('a4LS256S256')
14
+ resp.shift 2
15
+ resp
16
+ end
17
+
18
+ def pdat(formatted: false)
19
+ request_frame_data(:pdat)
20
+ resp = read(102).unpack('a4LSssSSssSSssSSssSSssSSssSSssSSssSSssSSssS')
21
+ return resp unless formatted
22
+
23
+ target_count = resp[1].to_i / 8
24
+ return [] unless target_count > 0
25
+
26
+ resp.shift 2
27
+ resp.compact
28
+ detected_raw_targets = []
29
+ target_count.times { detected_raw_targets << format_raw_target_data(resp.shift(4)) }
30
+ detected_raw_targets
31
+ end
32
+
33
+ def tdat
34
+ request_frame_data(:tdat)
35
+
36
+ sleep 0.1
37
+ resp = read(16).unpack('a4LSssS')
38
+ return { dist: resp[2], speed: resp[3], angle: resp[4], mag: resp[5] } unless resp[1].zero?
39
+ end
40
+
41
+ def ddat
42
+ request_frame_data(:ddat)
43
+ flags = %w[Low High]
44
+ array = read(14).unpack('a4LC6')
45
+ { label: array[0],
46
+ detection: DETECTION_FLAGS[:detection][array[2]],
47
+ micro_detection: DETECTION_FLAGS[:micro_detection][array[3]],
48
+ angle: DETECTION_FLAGS[:angle][array[4]],
49
+ direction: DETECTION_FLAGS[:direction][array[5]],
50
+ range: DETECTION_FLAGS[:range][array[6]],
51
+ speed: DETECTION_FLAGS[:speed][array[7]]
52
+ }
53
+ end
54
+
55
+ # Get the radar parameter structure
56
+ def grps
57
+ command = ['GRPS', 0]
58
+ write command.pack('a4L')
59
+ check_response
60
+ read(50).unpack('a4LA19C8c2C4cCCCCSCC')
61
+ end
62
+
63
+ def config
64
+ data = grps
65
+ output = "\n"
66
+ RADAR_PARAMETERS.keys.each do |key|
67
+ output << formatted_parameter(key, data[RADAR_PARAMETERS[key].grps_index])
68
+ end
69
+ output
70
+ end
71
+
72
+ def formatted_parameter(param, value = nil)
73
+ param = RADAR_PARAMETERS[param]
74
+ if value.nil?
75
+ data = grps
76
+ value = data[param.grps_index]
77
+ end
78
+ param_str_value = param.values.empty? ? value.to_s : param.values[value]
79
+ "#{param.name}: #{param_str_value}#{param.units}\n"
80
+ end
81
+
82
+ private
83
+
84
+ def format_raw_target_data(array)
85
+ { dist: array.shift, speed: array.shift, angle: array.shift, mag: array.shift }
86
+ end
87
+
88
+ def request_frame_data(type)
89
+ command = ['GNFD', 4, FRAME_DATA_TYPES[type]]
90
+ write command.pack('a4LL')
91
+ check_response
92
+ end
93
+ end
94
+ end