sgslib 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/sgs/nmea.rb CHANGED
@@ -87,7 +87,7 @@ module SGS
87
87
  if @args.count < 12 or @args.count > 13
88
88
  return nil
89
89
  end
90
- gps = SGS::GPS.new
90
+ gps = GPS.new
91
91
  gps.is_valid if @args[2] == "A"
92
92
  hh = @args[1][0..1].to_i
93
93
  mm = @args[1][2..3].to_i
@@ -100,7 +100,8 @@ module SGS
100
100
  gps.time = Time.gm(yy, mn, dd, hh, mm, ss, us)
101
101
  pos = {"latitude" => ll_nmea(@args[3,4]),
102
102
  "longitude" => ll_nmea(@args[5,6])}
103
- gps.location = Location.parse pos
103
+ gps.location = Location.new
104
+ gps.location.parse_hash(pos)
104
105
  gps.sog = @args[7].to_f
105
106
  gps.cmg = Bearing.dtor @args[8].to_f
106
107
  gps
data/lib/sgs/otto.rb CHANGED
@@ -31,125 +31,397 @@
31
31
  # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
32
  #
33
33
  # ABSTRACT
34
+ # This daemon handles all serial I/O with the low-level board (Otto). Otto
35
+ # publishes various status messages at regular intervals, and has a series
36
+ # of registers which can be used to alter the low-level operational state.
37
+ # This daemon code has two threads. One thread listens for RPCs to update
38
+ # Otto register state, and the other listens for status messages from Otto.
39
+ # The class also has helper functions for converting between Otto data
40
+ # formats (usually 8bit) and internal formats (usually floating point).
34
41
  #
42
+ require 'serialport'
43
+ require 'msgpack'
35
44
 
36
45
  ##
37
46
  # Routines for interfacing with the low-level microcontroller.
38
47
  #
39
48
  module SGS
40
49
  class Otto < RedisBase
41
- attr_accessor :raw_rudder, :raw_sail, :raw_compass, :raw_awa, :raw_tc, :raw_ta
42
- attr_accessor :mode, :rudder_m, :rudder_c, :sail_m, :sail_c
50
+ attr_accessor :mode, :serial_port
43
51
  attr_accessor :bv_m, :bv_c, :bi_m, :bi_c, :bt_m, :bt_c, :sv_m, :sv_c
52
+ attr_reader :alarm_status
53
+ attr_reader :actual_rudder, :actual_sail
54
+ attr_reader :otto_mode, :otto_timestamp, :telemetry
44
55
 
56
+ #
57
+ # Updates to Otto are done by setting an 8bit register value, as below.
58
+ ALARM_CLEAR_REGISTER = 0
59
+ MISSION_CONTROL_REGISTER = 1
60
+ MODE_REGISTER = 2
61
+ BUZZER_REGISTER = 3
62
+ RUDDER_ANGLE_REGISTER = 4
63
+ SAIL_ANGLE_REGISTER = 5
64
+ COMPASS_HEADING_REGISTER = 6
65
+ MIN_COMPASS_REGISTER = 7
66
+ MAX_COMPASS_REGISTER =8
67
+ AWA_HEADING_REGISTER = 9
68
+ MIN_AWA_REGISTER = 10
69
+ MAX_AWA_REGISTER = 11
70
+ WAKE_DURATION_REGISTER = 12
71
+ NEXT_WAKEUP_REGISTER = 13
72
+ MAX_REGISTER = 14
73
+
74
+ #
75
+ # This is different from mission mode. This mode defines how Otto should
76
+ # operate. Inert means "do nothing". Diagnostic mode is for the low-level
77
+ # code to run self-checks and calibrations. Manual means that the upper
78
+ # level system controls the rudder and sail angle without any higher-level
79
+ # PID controller. Track compass means that the boat will try to keep the
80
+ # actual compass reading within certain parameters, and track AWA will
81
+ # try to maintain a specific "apparent wind angle".
45
82
  MODE_INERT = 0
46
- MODE_DIAGNOSTICS = 1
83
+ MODE_DIAG = 1
47
84
  MODE_MANUAL = 2
48
- MODE_TRACK_COMPASS = 3
49
- MODE_TRACK_AWA = 4
85
+ MODE_REMOTE = 3
86
+ MODE_TRACK_COMPASS = 4
87
+ MODE_TRACK_AWA = 5
50
88
 
51
- MODE_NAMES = [
52
- "Inert Mode", "Diagnostics Mode", "Manual Control Mode",
53
- "Compass-Tracking Mode", "AWA-Tracking Mode"
54
- ].freeze
89
+ #
90
+ # Define some tweaks for rudder and sail setting. Rudder goes from
91
+ # +/-40 degrees, with zero indicating a straight rudder. On Otto, this
92
+ # translates to 0 (for -40.0), 128 (for the zero position) and 255 (for
93
+ # +40 degrees of rudder). A fully trimmed-in sail is zero and a fully
94
+ # extended sail is 255 (0->100 from a function perspective).
95
+ RUDDER_MAX = 40.0
96
+ RUDDER_MIN = -40.0
97
+ RUDDER_M = 3.175
98
+ RUDDER_C = 128.0
99
+ SAIL_MAX = 100.0
100
+ SAIL_MIN = 0.0
101
+ SAIL_M = 2.55
102
+ SAIL_C = 0.0
55
103
 
56
104
  #
57
- # Set up some useful defaults. We assume rudder goes from 0 to 200 as does
58
- # the sail angle.
105
+ # Set up some useful defaults. We assume rudder goes from 0 to 255 as does
106
+ # the sail angle.
59
107
  def initialize
108
+ serial_port = nil
60
109
  #
61
- # Configure the Mx + C values for sail and rudder
62
- @rudder_m = 2.5
63
- @rudder_c = 100.0
64
- @sail_m = 2.0
65
- @sail_c = 0.0
110
+ # Set some defaults for the read-back parameters
111
+ # The following five parameters are reported back by Otto with a status
112
+ # message, and are read-only. @alarm_status is 16 bits while the other
113
+ # four are 8-bit values. The helper methods convert these 8-bit values
114
+ # into radians, etc. The telemetry parameters are used to capture
115
+ # telemetry data from Otto.
116
+ @alarm_status = 0
117
+ @actual_rudder = @actual_sail = @actual_awa = @actual_compass = 0
118
+ @telemetry = Array.new(16)
66
119
  #
67
- # Now set the rudder and sail to default positions (rudder is centered)
68
- rudder = 0.0
69
- sail = 0.0
120
+ # Mode is used by Otto to decide how to steer the boat and trim the
121
+ # sails.
122
+ @otto_mode = MODE_INERT
123
+ @otto_timestamp = 1000
70
124
  #
71
125
  # Set up some basic parameters for battery/solar readings
72
126
  @bv_m = @bi_m = @bt_m = @sv_m = 1.0
73
127
  @bv_c = @bi_c = @bt_c = @sv_c = 0.0
128
+ #
129
+ # RPC client / server
130
+ @rpc_client = @rpc_server = nil
74
131
  super
75
132
  end
76
133
 
77
134
  #
78
- # Main daemon function (called from executable)
135
+ # Main daemon function (called from executable). The job of
136
+ # this daemon is to accept commands from the Redis pub/sub
137
+ # stream and send them to the low-level device, recording the
138
+ # response and sending it back to the caller. Note that we need
139
+ # to do an initial sync with the device as it will ignore the
140
+ # usual serial console boot-up gumph awaiting our sync message.
79
141
  def self.daemon
80
- loop do
81
- sleep 300
142
+ puts "Low-level (Otto) communication subsystem starting up..."
143
+ otto = new
144
+ config = Config.load
145
+ otto.serial_port = SerialPort.new config.otto_device, config.otto_speed
146
+ otto.serial_port.read_timeout = 10000
147
+ #
148
+ # Start by getting a sync message from Otto.
149
+ otto.synchronize()
150
+ #
151
+ # Run the communications service with Otto. Two threads are used, one for
152
+ # reading and one for writing. Don't let the command stack get too big.
153
+ t1 = Thread.new { otto.reader_thread }
154
+ t2 = Thread.new { otto.writer_thread }
155
+ t1.join
156
+ t2.join
157
+ end
158
+
159
+ #
160
+ # Build a C include file based on the current register definitions
161
+ def self.build_include(fname)
162
+ otto = new
163
+ File.open(fname, "w") do |f|
164
+ f.puts "/*\n * Autogenerated by #{__FILE__}.\n * DO NOT HAND-EDIT!\n */"
165
+ constants.sort.each do |c|
166
+ if c.to_s =~ /REGISTER$/
167
+ cval = Otto.const_get(c)
168
+ str = "#define SGS_#{c.to_s}"
169
+ str += "\t" if str.length < 32
170
+ str += "\t#{cval}"
171
+ f.puts str
172
+ end
173
+ end
174
+ end
175
+ end
176
+
177
+ #
178
+ # Synchronize with the low-level board by sending CQ messages until
179
+ # they respond. When Mother boots up, the serial console is shared with
180
+ # Otto so a lot of rubbish is sent to the low-level board. To notify
181
+ # Otto that we are now talking sense, we send @@CQ! and Otto responds
182
+ # with +CQOK. Note that this function, which is always called before any
183
+ # of the threads, is bidirectional in terms of serial I/O.
184
+ def synchronize
185
+ index = 0
186
+ backoffs = [1, 1, 1, 1, 2, 2, 3, 5, 10, 10, 20, 30, 60]
187
+ puts "Attempting to synchronize with Otto..."
188
+ while true do
189
+ begin
190
+ @serial_port.puts "@@CQ!"
191
+ resp = read_data
192
+ break if resp =~ /^\+CQOK/ or resp =~ /^\+OK/
193
+ sleep backoffs[index]
194
+ index += 1 if index < (backoffs.count - 1)
195
+ end
196
+ end
197
+ puts "Synchronization complete!"
198
+ end
199
+
200
+ #
201
+ # Thread to read status messages from Otto and handle them
202
+ def reader_thread
203
+ puts "Starting OTTO reader thread..."
204
+ while true
205
+ data = read_data
206
+ next if data.nil? or data.length == 0
207
+ case data[0]
208
+ when '$'
209
+ #
210
+ # Status message (every second)
211
+ parse_status(data[1..])
212
+ when '@'
213
+ #
214
+ # Otto elapsed time (every four seconds)
215
+ parse_tstamp(data[1..])
216
+ when '!'
217
+ #
218
+ # Otto mode state (every four seconds)
219
+ parse_mode(data[1..])
220
+ when '>'
221
+ #
222
+ # Telemetry data (every two seconds)
223
+ parse_telemetry(data[1..])
224
+ when '*'
225
+ #
226
+ # Message for the debug log
227
+ parse_debug(data[1..])
228
+ end
229
+ end
230
+ end
231
+
232
+ #
233
+ # Thread to write commands direct to Otto.
234
+ def writer_thread
235
+ puts "Starting OTTO writer thread..."
236
+ #
237
+ # Now listen for Redis PUB/SUB requests and act on each one.
238
+ myredis = Redis.new
239
+ while true
240
+ channel, request = myredis.brpop("otto")
241
+ request = MessagePack.unpack(request)
242
+ puts "Req:[#{request.inspect}]"
243
+ params = request['params']
244
+ next if request['method'] != "set_local_register"
245
+ puts "PARAMS: #{params}"
246
+ cmd = "R%d=%X\r\n" % params
247
+ puts "Command: #{cmd}"
248
+ @serial_port.write cmd
249
+ puts "> Sending command: #{str}"
250
+ @serial_port.puts "#{str}"
251
+ end
252
+ end
253
+
254
+ #
255
+ # Read data from the serial port
256
+ def read_data
257
+ begin
258
+ data = @serial_port.readline.chomp
259
+ rescue EOFError => error
260
+ puts "Otto Read Timeout!"
261
+ data = nil
262
+ end
263
+ data
264
+ end
265
+
266
+ #
267
+ # Parse a status message from Otto. In the form:
268
+ # 0001:C000:0000
269
+ def parse_status(status)
270
+ puts "OTTO PARSE: #{status}"
271
+ args = status.split /:/
272
+ @alarm_status = args[0].to_i(16)
273
+ wc = args[1].to_i(16)
274
+ rs = args[2].to_i(16)
275
+ @actual_awa = (wc >> 8) & 0xff
276
+ @actual_compass = (wc & 0xff)
277
+ @actual_rudder = (rs >> 8) & 0xff
278
+ @actual_sail = (rs & 0xff)
279
+ p self
280
+ self.save_and_publish
281
+ end
282
+
283
+ #
284
+ # Parse a timestamp message from Otto. In the form: "000FE2" 24 bits
285
+ # representing the elapsed seconds since Otto restarted.
286
+ def parse_tstamp(tstamp)
287
+ newval = tstamp.to_i(16)
288
+ if newval < @otto_timestamp
289
+ puts "ALARM! Otto rebooted (or something)..."
82
290
  end
291
+ @otto_timestamp = newval
292
+ end
293
+
294
+ #
295
+ # Parse a mode state message from Otto. In the form: "00". An eight bit
296
+ # quantity.
297
+ def parse_mode(mode)
298
+ @otto_mode = mode.to_i(16)
299
+ end
300
+
301
+ #
302
+ # Parse a telemetry message from Otto. In the form: "7327" where the first
303
+ # character is the channel (0->9) and the remaining 12 bits are the value.
304
+ def parse_telemetry(telemetry)
305
+ data = telemetry.to_i(16)
306
+ chan = (data >> 12) & 0xf
307
+ @telemetry[chan] = data & 0xfff
308
+ end
309
+
310
+ #
311
+ # Parse a debug message from the low-level code. Basically just append it
312
+ # to a log file.
313
+ def parse_debug(debug_data)
314
+ puts "DEBUG: [#{debug_data}].\n"
315
+ end
316
+
317
+ #
318
+ # Clear an alarm setting
319
+ def alarm_clear(alarm)
320
+ set_register(ALARM_CLEAR_REGISTER, alarm)
321
+ end
322
+
323
+ #
324
+ # Set the Otto mode
325
+ def mode=(val)
326
+ set_register(MODE_REGISTER, val) if @otto_mode != val
83
327
  end
84
328
 
85
329
  #
86
330
  # Set the required rudder angle. Input values range from +/- 40.0 degrees
87
331
  def rudder=(val)
88
- val = -40.0 if val < -40.0
89
- val = 40.0 if val > 40.0
90
- @raw_rudder = (@rudder_m * val.to_f + @rudder_c).to_i
332
+ val = RUDDER_MIN if val < RUDDER_MIN
333
+ val = RUDDER_MAX if val > RUDDER_MAX
334
+ val = (RUDDER_M * val.to_f + RUDDER_C).to_i
335
+ if val != @actual_rudder
336
+ @actual_rudder = val
337
+ set_register(RUDDER_ANGLE_REGISTER, val)
338
+ end
339
+ mode = MODE_MANUAL
91
340
  end
92
341
 
93
342
  #
94
343
  # Return the rudder angle in degrees
95
344
  def rudder
96
- (@raw_rudder.to_f - @rudder_c) / @rudder_m
345
+ (@actual_rudder.to_f - RUDDER_C) / RUDDER_M
97
346
  end
98
347
 
99
348
  #
100
- # Set the required sail angle. Input values range from 0 -> 90 degrees.
349
+ # Set the required sail angle. Input values range from 0 -> 100.
101
350
  def sail=(val)
102
- val = 0.0 if val < 0.0
103
- val = 100.0 if val > 100.0
104
- @raw_sail = (@sail_m * val.to_f + @sail_c).to_i
351
+ val = SAIL_MIN if val < SAIL_MIN
352
+ val = SAIL_MAX if val > SAIL_MAX
353
+ val = (SAIL_M * val.to_f + SAIL_C).to_i
354
+ if val != @actual_sail
355
+ @actual_sail = val
356
+ set_register(SAIL_ANGLE_REGISTER, val)
357
+ end
358
+ mode = MODE_MANUAL
105
359
  end
106
360
 
107
361
  #
108
362
  # Return the sail setting (0.0 -> 100.0)
109
363
  def sail
110
- (@raw_sail.to_f - @sail_c) / @sail_m
364
+ (@actual_sail.to_f - SAIL_C) / SAIL_M
111
365
  end
112
366
 
113
367
  #
114
368
  # Return the compass angle (in radians)
115
369
  def compass
116
- @raw_compass.to_f * Math::PI / 128.0
370
+ Bearing.xtor(@actual_compass)
117
371
  end
118
372
 
119
373
  #
120
374
  # Return the apparent wind angle (in radians)
121
375
  def awa
122
- @raw_awa.to_f * Math::PI / 128.0
376
+ @actual_awa -= 256 if @actual_awa > 128
377
+ Bearing.xtor(@actual_awa)
123
378
  end
124
379
 
125
380
  #
126
- # Set the required compass reading. Input values range from 0 -> 359 degrees
381
+ # Return the actual wind direction (in radians)
382
+ def wind
383
+ Bearing.xtor(@actual_compass + @actual_awa)
384
+ end
385
+
386
+ #
387
+ # Set the required compass reading (in radians)
127
388
  def track_compass=(val)
128
- while val < 0.0
129
- val += 360.0
389
+ val = Bearing.rtox(val)
390
+ if @track_compass.nil? or @track_compass != val
391
+ @track_compass = val
392
+ set_register(COMPASS_HEADING_REGISTER, val)
130
393
  end
131
- val %= 360.0
132
- @raw_tc = (val.to_f * 128.0 / Math::PI).to_i
394
+ mode = MODE_TRACK_COMPASS
133
395
  end
134
396
 
135
397
  #
136
398
  # Return the compass value for tracking.
137
399
  def track_compass
138
- @raw_tc.to_f * Math::PI / 128.0
400
+ Bearing.xtor(@track_compass)
139
401
  end
140
402
 
141
403
  #
142
- # Set the required AWA for tracking.
404
+ # Set the required AWA for tracking (in radians).
143
405
  def track_awa=(val)
144
- val = -180.0 if val < -180.0
145
- val = 180.0 if val > 180.0
146
- @raw_ta = (val.to_f * 128.0 / Math::PI).to_i
406
+ val = Bearing.rtox(val)
407
+ if @track_awa.nil? or @track_awa != val
408
+ @track_awa = val
409
+ set_register(AWA_HEADING_REGISTER, val)
410
+ end
411
+ mode = MODE_TRACK_AWA
147
412
  end
148
413
 
149
414
  #
150
- # Return the current tracking AWA.
415
+ # Return the current tracking AWA (in radians).
151
416
  def track_awa
152
- @raw_ta.to_f * Math::PI / 128.0
417
+ Bearing.xtor(@track_awa)
418
+ end
419
+
420
+ #
421
+ # RPC client call to set register - sent to writer function above
422
+ def set_register(regno, value)
423
+ @rpc_client = RPCClient.new("otto") unless @rpc_client
424
+ @rpc_client.set_local_register(regno, value)
153
425
  end
154
426
  end
155
427
  end
@@ -75,7 +75,7 @@ module SGS
75
75
  # Initialize a Redis variable.
76
76
  def self.var_init(var, val, idx = nil)
77
77
  cls = new
78
- SGS::RedisBase.redis.setnx cls.make_redis_name(var, :idx => idx), self.to_redis(var, val, idx)
78
+ RedisBase.redis.setnx cls.make_redis_name(var, :idx => idx), self.to_redis(var, val, idx)
79
79
  end
80
80
 
81
81
  #
@@ -96,8 +96,8 @@ module SGS
96
96
  # It's an array - iterate and read the values.
97
97
  lval.size.times do |idx|
98
98
  idx_val = lval[idx]
99
- lval[idx] = redis_read_var var, idx_val.class, :idx => idx
100
- end
99
+ lval[idx] = redis_read_var var, idx_val.class, :idx => idx
100
+ end
101
101
  elsif lval.kind_of? Location
102
102
  #
103
103
  # ::FIXME:: Yes. this is a hack.
@@ -141,7 +141,7 @@ module SGS
141
141
  #
142
142
  # Inside a multi-block, set all the variables and increment
143
143
  # the count.
144
- SGS::RedisBase.redis.multi do |pipeline|
144
+ RedisBase.redis.multi do |pipeline|
145
145
  var_list.each do |key, value|
146
146
  pipeline.set key, value
147
147
  end
@@ -157,7 +157,7 @@ module SGS
157
157
  # class name), you can remember the last received count and decide if
158
158
  # there is fresh data. Or, you can just act anyway.
159
159
  def publish
160
- SGS::RedisBase.redis.publish self.class.redis_handle, count.to_s
160
+ RedisBase.redis.publish self.class.redis_handle, count.to_s
161
161
  end
162
162
 
163
163
  #
@@ -182,7 +182,7 @@ module SGS
182
182
  #
183
183
  # Retrieve the count
184
184
  def count
185
- SGS::RedisBase.redis.get count_name
185
+ RedisBase.redis.get count_name
186
186
  end
187
187
 
188
188
  #
@@ -195,7 +195,7 @@ module SGS
195
195
  # Get an instance variable value from a Redis value.
196
196
  def redis_read_var(var, klass, opts = {})
197
197
  redis_name = make_redis_name var, opts
198
- redis_val = SGS::RedisBase.redis.get redis_name
198
+ redis_val = RedisBase.redis.get redis_name
199
199
  redis_val = nil if redis_val == ""
200
200
  if redis_val
201
201
  if not klass or klass == NilClass
@@ -211,9 +211,9 @@ module SGS
211
211
  when klass == Float
212
212
  redis_val = redis_val.to_f
213
213
  when klass == FalseClass
214
- redis_val = false
214
+ redis_val = (redis_val == "true" or redis_val == "TRUE")
215
215
  when klass == TrueClass
216
- redis_val = true
216
+ redis_val = (redis_val == "true" or redis_val == "TRUE")
217
217
  end
218
218
  end
219
219
  redis_val
data/lib/sgs/report.rb CHANGED
@@ -32,15 +32,20 @@
32
32
  #
33
33
  # ABSTRACT
34
34
  #
35
+ require 'serialport'
35
36
 
36
37
  ##
37
38
  # Routines for handling sailboat navigation and route planning.
38
39
  #
39
40
  module SGS
40
- class Report < RedisBase
41
+ class Report
41
42
  #
42
43
  # Main daemon function (called from executable)
43
44
  def self.daemon
45
+ puts "Reporting subsystem starting up..."
46
+ config = Config.load
47
+ sp = SerialPort.new config.comm_device, config.comm_speed
48
+ sp.read_timeout = 10000
44
49
  loop do
45
50
  sleep 300
46
51
  end
data/lib/sgs/rpc.rb CHANGED
@@ -55,9 +55,8 @@ module SGS
55
55
  'method' => name,
56
56
  'params' => args
57
57
  }
58
- SGS::RedisBase.redis.lpush(@channel, request.to_msgpack)
59
- channel, response = SGS::RedisBase.redis.brpop(uuid, timeout=60)
60
- MessagePack.unpack(response)['result']
58
+ puts "RPC CLIENT SENDING MESSAGE! request: #{request.inspect}, channel: #{@channel}"
59
+ RedisBase.redis.lpush(@channel, request.to_msgpack)
61
60
  end
62
61
  end
63
62
 
@@ -70,7 +69,7 @@ module SGS
70
69
  def start
71
70
  puts "Starting RPC server for #{@channel}"
72
71
  loop do
73
- channel, request = SGS::RedisBase.redis.brpop(@channel)
72
+ channel, request = RedisBase.redis.brpop(@channel)
74
73
  request = MessagePack.unpack(request)
75
74
 
76
75
  puts "Working on request: #{request['id']}"
@@ -84,8 +83,8 @@ module SGS
84
83
  'id' => request['id']
85
84
  }
86
85
 
87
- SGS::RedisBase.redis.rpush(request['id'], MessagePack.pack(reply))
88
- SGS::RedisBase.redis.expire(request['id'], 30)
86
+ RedisBase.redis.rpush(request['id'], MessagePack.pack(reply))
87
+ RedisBase.redis.expire(request['id'], 30)
89
88
  end
90
89
  end
91
90
  end
data/lib/sgs/version.rb CHANGED
@@ -33,5 +33,5 @@
33
33
  # ABSTRACT
34
34
  #
35
35
  module SGS
36
- VERSION = "1.5.0"
36
+ VERSION = "1.6.0"
37
37
  end
data/lib/sgs/waypoint.rb CHANGED
@@ -39,7 +39,7 @@
39
39
  module SGS
40
40
  #
41
41
  # Waypoint, Attractor, and Repellor definitions
42
- class Waypoint < RedisBase
42
+ class Waypoint
43
43
  attr_accessor :location, :normal, :range, :name, :attractor
44
44
  attr_reader :bearing, :distance
45
45
 
@@ -58,7 +58,7 @@ module SGS
58
58
  def parse(data)
59
59
  @@count += 1
60
60
  @name = data["name"] || "Waypoint ##{@@count}"
61
- @location = SGS::Location.parse(data)
61
+ @location = Location.parse(data)
62
62
  @normal = data["normal"] || 0.0
63
63
  @range = data["range"] || 0.1
64
64
  end
data/lib/sgslib.rb CHANGED
@@ -31,13 +31,10 @@
31
31
  # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
32
  #
33
33
  # ABSTRACT
34
- #
34
+ # Include all of the various components.
35
35
 
36
36
  ##
37
37
  #
38
- require 'date'
39
- require 'logger'
40
-
41
38
  require "sgs/version"
42
39
  require 'sgs/redis_base'
43
40
  require 'sgs/config'
data/sgslib.gemspec CHANGED
@@ -34,14 +34,16 @@ Gem::Specification.new do |spec|
34
34
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
35
  spec.require_paths = ["lib"]
36
36
 
37
- spec.required_ruby_version = '>= 1.9.2'
37
+ spec.required_ruby_version = '>= 2.7.6'
38
38
 
39
39
  spec.add_development_dependency "bundler", "~> 2.2"
40
40
  spec.add_development_dependency "rake", ">= 12.3.3"
41
41
  spec.add_development_dependency "rspec", "~> 3.0"
42
42
 
43
- spec.add_runtime_dependency "logger", "~> 1.4"
44
- spec.add_runtime_dependency "msgpack", "~> 1.3"
45
-
46
- spec.add_dependency "redis", "~> 4.7"
43
+ spec.add_runtime_dependency "redis", "~> 5.0"
44
+ spec.add_runtime_dependency "serialport", "~> 1.3"
45
+ spec.add_runtime_dependency "msgpack", "~> 1.6"
46
+ spec.add_runtime_dependency "json"
47
+ spec.add_runtime_dependency "securerandom"
48
+ spec.add_runtime_dependency "yaml"
47
49
  end