class Apex::AprsKiss
Public Class Methods
new(data_stream)
click to toggle source
# File lib/apex/aprs_kiss.rb, line 7 def initialize(data_stream) @data_stream = data_stream @lock = Mutex.new end
Private Class Methods
decode_frame(raw_frame)
click to toggle source
# File lib/apex/aprs_kiss.rb, line 13 def self.decode_frame(raw_frame) frame = {} frame_len = raw_frame.length if frame_len > 16 (0...frame_len - 2).each do |raw_slice| # Is address field length correct? if raw_frame[raw_slice] & 0x01 != 0 and ((raw_slice + 1) % 7) == 0 i = (raw_slice.to_f + 1.0) / 7.0 # Less than 2 callsigns? if 1.0 < i and i < 11.0 if raw_frame[raw_slice + 1] & 0x03 == 0x03 and [0xf0, 0xcf].include? raw_frame[raw_slice + 2] text_as_array = raw_frame[raw_slice + 3..-1].map { |b| b.chr } frame[:text] = text_as_array.join frame[:destination] = identity_as_string(extract_callsign(raw_frame)) frame[:source] = identity_as_string(extract_callsign(raw_frame[7..-1])) frame[:path] = extract_path(i.to_i, raw_frame) return frame end end end end end return nil end
encode_callsign(callsign)
click to toggle source
# File lib/apex/aprs_kiss.rb, line 107 def self.encode_callsign(callsign) call_sign = callsign[:callsign] enc_ssid = (callsign[:ssid] << 1) | 0x60 if call_sign.include? '*' call_sign.gsub!(/\*/, '') enc_ssid |= 0x80 end while call_sign.length < 6 call_sign = [call_sign, ' '].join end return call_sign.chars.map { |p| p.ord << 1 } + [enc_ssid] end
encode_frame(frame)
click to toggle source
# File lib/apex/aprs_kiss.rb, line 96 def self.encode_frame(frame) enc_frame = encode_callsign(parse_identity_string(frame[:destination])) + encode_callsign(parse_identity_string(frame[:source])) frame[:path].each do |path| enc_frame += encode_callsign(parse_identity_string(path)) end return enc_frame[0...-1] + [enc_frame[-1] | 0x01] + [Kiss::SLOT_TIME] + [0xf0] + frame[:text].chars.map { |c| c.ord } end
extract_callsign(raw_frame)
click to toggle source
# File lib/apex/aprs_kiss.rb, line 78 def self.extract_callsign(raw_frame) callsign_as_array = raw_frame[0...6].map { |x| (x >> 1).chr } callsign = callsign_as_array.join.strip ssid = (raw_frame[6] >> 1) & 0x0f ssid = (ssid == nil or ssid == 0 ? nil : ssid) return {:callsign => callsign, :ssid => ssid} end
extract_path(start, raw_frame)
click to toggle source
# File lib/apex/aprs_kiss.rb, line 61 def self.extract_path(start, raw_frame) full_path = [] (2...start).each do |i| path = identity_as_string(extract_callsign(raw_frame[i * 7..-1])) if path and path.length > 0 if raw_frame[i * 7 + 6] & 0x80 != 0 full_path << [path, '*'].join else full_path << path end end end full_path end
identity_as_string(identity)
click to toggle source
# File lib/apex/aprs_kiss.rb, line 87 def self.identity_as_string(identity) if identity[:ssid] and identity[:ssid] > 0 return [identity[:callsign], identity[:ssid].to_s].join('-') else return identity[:callsign] end end
parse_identity_string(identity_string)
click to toggle source
# File lib/apex/aprs_kiss.rb, line 125 def self.parse_identity_string(identity_string) # If we are parsing a spent token then first lets get rid of the astresick suffix. if identity_string[-1] == '*' identity_string = identity_string[0..-1] end if identity_string.include? '-' call_sign, ssid = identity_string.split('-') else call_sign = identity_string ssid = 0 end return {:callsign => call_sign, :ssid => ssid.to_i} end
valid_frame(raw_frame)
click to toggle source
# File lib/apex/aprs_kiss.rb, line 40 def self.valid_frame(raw_frame) frame_len = raw_frame.length if frame_len > 16 (0...frame_len - 2).each do |raw_slice| # Is address field length correct? if raw_frame[raw_slice] & 0x01 != 0 and ((raw_slice + 1) % 7) == 0 i = (raw_slice.to_f + 1.0) / 7.0 # Less than 2 callsigns? if 1.0 < i and i < 11.0 if raw_frame[raw_slice + 1] & 0x03 == 0x03 and [0xf0, 0xcf].include? raw_frame[raw_slice + 2] return true end end end end end return false end
Public Instance Methods
close(*args, **kwargs)
click to toggle source
# File lib/apex/aprs_kiss.rb, line 147 def close(*args, **kwargs) @data_stream.close(*args, **kwargs) end
connect(*args, **kwargs)
click to toggle source
# File lib/apex/aprs_kiss.rb, line 142 def connect(*args, **kwargs) @data_stream.connect(*args, **kwargs) end
read(*args, **kwargs)
click to toggle source
# File lib/apex/aprs_kiss.rb, line 152 def read(*args, **kwargs) @lock.synchronize do frame = @data_stream.read(*args, **kwargs) if frame and frame.length > 0 return AprsKiss.decode_frame(frame) else return nil end end end
write(frame, *args, **kwargs)
click to toggle source
# File lib/apex/aprs_kiss.rb, line 164 def write(frame, *args, **kwargs) @lock.synchronize do encoded_frame = AprsKiss.encode_frame(frame) if AprsKiss.valid_frame(encoded_frame) @data_stream.write(encoded_frame, *args, **kwargs) end end end