Commit 9db4bdfd authored by Jeffrey Phillips Freeman's avatar Jeffrey Phillips Freeman 💥
Browse files

Added test classes for AprsKiss, and fixed a few bugs.

parent 0e79655b
require_relative '../kiss/constants' require_relative '../kiss/constants'
module APRS module Aprs
class APRSKiss class AprsKiss
protected protected
def initialize(data_stream) def initialize(data_stream)
...@@ -20,13 +20,13 @@ module APRS ...@@ -20,13 +20,13 @@ module APRS
if raw_frame[raw_slice] & 0x01 and ((raw_slice + 1) % 7) == 0 if raw_frame[raw_slice] & 0x01 and ((raw_slice + 1) % 7) == 0
i = (raw_slice.to_f + 1.0) / 7.0 i = (raw_slice.to_f + 1.0) / 7.0
# Less than 2 callsigns? # Less than 2 callsigns?
if 1.0 < i < 11.0 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] 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| chr(b) } text_as_array = raw_frame[raw_slice + 3..-1].map { |b| b.chr }
frame['text'] = text_as_array.join frame[:text] = text_as_array.join
frame['destination'] = identity_as_string(extract_callsign(raw_frame)) frame[:destination] = identity_as_string(extract_callsign(raw_frame))
frame['source'] = identity_as_string(__extract_callsign(raw_frame[7..-1])) frame[:source] = identity_as_string(extract_callsign(raw_frame[7..-1]))
frame['path'] = extract_path(i.to_i, raw_frame) frame[:path] = extract_path(i.to_i, raw_frame)
return frame return frame
end end
end end
...@@ -55,36 +55,36 @@ module APRS ...@@ -55,36 +55,36 @@ module APRS
private private
def self.extract_callsign(raw_frame) def self.extract_callsign(raw_frame)
callsign_as_array = raw_frame[0...6].map { |x| chr(x >> 1) } callsign_as_array = raw_frame[0...6].map { |x| (x >> 1).chr }
callsign = callsign_as_array.join.strip callsign = callsign_as_array.join.strip
ssid = (raw_frame[6] >> 1) & 0x0f ssid = (raw_frame[6] >> 1) & 0x0f
return {'callsign': callsign, 'ssid': ssid} return {:callsign => callsign, :ssid => ssid}
end end
private private
def self.identity_as_string(identity) def self.identity_as_string(identity)
if identity['ssid'] > 0 if identity[:ssid]
return [identity['callsign'], identity['ssid'].to_s].join('-') return [identity[:callsign], identity[:ssid].to_s].join('-')
else else
return identity['callsign'] return identity[:callsign]
end end
end end
private private
def self.encode_frame(frame) def self.encode_frame(frame)
enc_frame = encode_callsign(parse_identity_string(frame['destination'])) + encode_callsign(parse_identity_string(frame['source'])) enc_frame = encode_callsign(parse_identity_string(frame[:destination])) + encode_callsign(parse_identity_string(frame[:source]))
frame['path'].each do |p| frame[:path].each do |p|
enc_frame += encode_callsign(parse_identity_string(p)) enc_frame += encode_callsign(parse_identity_string(p))
end end
return enc_frame[0..-1] + [enc_frame[-1] | 0x01] + [KISS::SLOT_TIME] + [0xf0] + frame['text'].map { |c| ord(c) } return enc_frame[0..-1] + [enc_frame[-1] | 0x01] + [Kiss::SLOT_TIME] + [0xf0] + frame[:text].chars.map { |c| c.ord }
end end
private private
def self.encode_callsign(callsign) def self.encode_callsign(callsign)
call_sign = callsign['callsign'] call_sign = callsign[:callsign]
enc_ssid = (callsign['ssid'] << 1) | 0x60 enc_ssid = (callsign[:ssid] << 1) | 0x60
if call_sign.include? '*' if call_sign.include? '*'
call_sign.gsub!(/\*/,'') call_sign.gsub!(/\*/,'')
...@@ -95,7 +95,7 @@ module APRS ...@@ -95,7 +95,7 @@ module APRS
call_sign = [call_sign, ' '].join call_sign = [call_sign, ' '].join
end end
return call_sign.map { |p| ord(p) << 1 } + [enc_ssid] return call_sign.chars.map { |p| p.ord << 1 } + [enc_ssid]
end end
private private
...@@ -112,7 +112,7 @@ module APRS ...@@ -112,7 +112,7 @@ module APRS
ssid = 0 ssid = 0
end end
return {'callsign': call_sign, 'ssid': int(ssid)} return {:callsign => call_sign, :ssid => ssid.to_i}
end end
public public
...@@ -125,24 +125,24 @@ module APRS ...@@ -125,24 +125,24 @@ module APRS
@data_stream.close(*args, **kwargs) @data_stream.close(*args, **kwargs)
end end
public
def write(frame, *args, **kwargs)
@lock.synchronize do
encoded_frame = encode_frame(frame)
@data_stream.write(encoded_frame, *args, **kwargs)
end
end
public public
def read(*args, **kwargs) def read(*args, **kwargs)
@lock.synchronize do @lock.synchronize do
frame = @data_stream.read(*args, **kwargs) frame = @data_stream.read(*args, **kwargs)
if frame&.length if frame&.length
return decode_frame(frame) return AprsKiss.decode_frame(frame)
else else
return nil return nil
end end
end end
end end
public
def write(frame, *args, **kwargs)
@lock.synchronize do
encoded_frame = AprsKiss.encode_frame(frame)
@data_stream.write(encoded_frame, *args, **kwargs)
end
end
end end
end end
\ No newline at end of file
module KISS module Kiss
# KISS Special Characters # KISS Special Characters
# http://en.wikipedia.org/wiki/KISS_(TNC)#Special_Characters # http://en.wikipedia.org/wiki/KISS_(TNC)#Special_Characters
FEND = 0xC0 FEND = 0xC0
......
...@@ -2,8 +2,8 @@ require 'thread' ...@@ -2,8 +2,8 @@ require 'thread'
require 'abstraction' require 'abstraction'
require_relative 'constants' require_relative 'constants'
module KISS module Kiss
class KISSAbstract class KissAbstract
abstract abstract
protected protected
...@@ -113,7 +113,7 @@ module KISS ...@@ -113,7 +113,7 @@ module KISS
new_frames.each do |new_frame| new_frames.each do |new_frame|
if new_frame.length > 0 and new_frame[0] == 0 if new_frame.length > 0 and new_frame[0] == 0
if @strip_df_start if @strip_df_start
new_frame = KISSAbstract.strip_df_start(new_frame) new_frame = KissAbstract.strip_df_start(new_frame)
end end
@frame_buffer << new_frame @frame_buffer << new_frame
end end
...@@ -129,7 +129,7 @@ module KISS ...@@ -129,7 +129,7 @@ module KISS
end end
public public
def read def read(*args, **kwargs)
@lock.synchronize do @lock.synchronize do
if @frame_buffer.length == 0 if @frame_buffer.length == 0
fill_buffer fill_buffer
...@@ -146,10 +146,10 @@ module KISS ...@@ -146,10 +146,10 @@ module KISS
end end
public public
def write(frame_bytes, port=0) def write(frame_bytes, port=0, *args, **kwargs)
@lock.synchronize do @lock.synchronize do
kiss_packet = [FEND] + [KISSAbstract.command_byte_combine(port, DATA_FRAME)] + kiss_packet = [FEND] + [KissAbstract.command_byte_combine(port, DATA_FRAME)] +
KISSAbstract.escape_special_codes(frame_bytes) + [FEND] KissAbstract.escape_special_codes(frame_bytes) + [FEND]
write_interface(kiss_packet) write_interface(kiss_packet)
end end
......
require 'serialport' require 'serialport'
require_relative 'kiss_abstract' require_relative 'kiss_abstract'
module KISS module Kiss
class KISSSerial < KISSAbstract class KissSerial < KissAbstract
DEFAULT_READ_BYTES = 1000 DEFAULT_READ_BYTES = 1000
SERIAL_READ_TIMEOUT = -1 SERIAL_READ_TIMEOUT = -1
...@@ -31,7 +31,7 @@ module KISS ...@@ -31,7 +31,7 @@ module KISS
protected protected
def read_interface def read_interface
read_data = @serial.read(@read_bytes) read_data = @serial.read(@read_bytes)
read_data.map { |c| ord(c) } read_data.map { |c| c.ord }
end end
protected protected
......
require_relative '../lib/kiss/kiss_abstract'
module Kiss
class KissMock < KissAbstract
def initialize(strip_df_start=true)
super(strip_df_start)
@read_from_interface = []
@sent_to_interface = []
end
protected
def read_interface
if @read_from_interface.length == 0
return nil
end
return @read_from_interface.shift
end
protected
def write_interface(data)
@sent_to_interface << data
end
public
def clear_interface
@read_from_interface = []
@sent_to_interface = []
end
public
def add_read_from_interface(raw_frame)
@read_from_interface << raw_frame
end
public
def get_sent_to_interface
return @sent_to_interface
end
end
end
\ No newline at end of file
require 'test/unit'
require_relative 'kiss_mock'
require_relative '../lib/aprs/aprs_kiss'
module Aprs
DECODED_FRAME_KISS = {
'source': 'W2GMD-1',
'destination': 'OMG',
'path': ['WIDE1-1', 'WIDE2-2'],
'text': 'test_encode_frame'
}
ENCODED_FRAME_KISS = [192, 0, 158, 154, 142, 64, 64, 64, 96, 174, 100, 142, 154, 136, 64, 98, 174, 146, 136, 138, 98,
64, 98, 174, 146, 136, 138, 100, 64, 101, 3, 240, 116, 101, 115, 116, 95, 101, 110, 99, 111, 100,
101, 95, 102, 114, 97, 109, 101, 192]
DECODED_FRAME_KISS_INVALID = {
'source': 'KG6WTF',
'destination': 'S7TSUV',
'path': ['MTOSO-2', 'WIDE2*' 'qAR', 'KF6FIR-10'],
'text': '`17El#X-/kg6wtf@gosselinfamily.com'
}
ENCODED_FRAME_KISS_INVALID = [192, 0, 166, 110, 168, 166, 170, 172, 96, 150, 142, 108, 174, 168, 140, 96, 154, 168, 158,
166, 158, 64, 100, 174, 146, 136, 138, 100, 226, 130, 164, 224, 150, 140, 108, 140, 146, 164,
117, 3, 240, 96, 49, 55, 69, 108, 35, 88, 45, 47, 107, 103, 54, 119, 116, 102, 64, 103, 111,
115, 115, 101, 108, 105, 110, 102, 97, 109, 105, 108, 121, 46, 99, 111, 109, 192]
class TestKiss < Test::Unit::TestCase
def test_read
kiss_mock = Kiss::KissMock.new
aprs_kiss = AprsKiss.new(kiss_mock)
kiss_mock.clear_interface
kiss_mock.add_read_from_interface(ENCODED_FRAME_KISS)
translated_frame = nil
iter_left = 1000
while iter_left > 0 and not translated_frame
translated_frame = aprs_kiss.read
iter_left -= 1
end
assert_equal DECODED_FRAME_KISS, translated_frame
end
def test_write
kiss_mock = Kiss::KissMock.new
aprs_kiss = AprsKiss.new(kiss_mock)
kiss_mock.clear_interface
aprs_kiss.write(DECODED_FRAME_KISS)
all_raw_frames = kiss_mock.get_sent_to_interface
assert_equal ENCODED_FRAME_KISS, all_raw_frames[0]
end
end
end
\ No newline at end of file
require 'test/unit' require 'test/unit'
require_relative '../lib/kiss/kiss_abstract' require_relative 'kiss_mock'
module KISS module Kiss
# KG6WTF>S7TSUV,MTOSO-2,WIDE2*,qAR,KF6FIR-10:`17El#X-/kg6wtf@gosselinfamily.com # KG6WTF>S7TSUV,MTOSO-2,WIDE2*,qAR,KF6FIR-10:`17El#X-/kg6wtf@gosselinfamily.com
ENCODED_FRAME = [192, 0, 75, 71, 54, 87, 84, 70, 62, 83, 55, 84, 83, 85, 86, 44, 77, 84, 79, 83, 79, 45, 50, 44, 87, 73, ENCODED_FRAME = [192, 0, 75, 71, 54, 87, 84, 70, 62, 83, 55, 84, 83, 85, 86, 44, 77, 84, 79, 83, 79, 45, 50, 44, 87, 73,
68, 69, 50, 42, 44, 113, 65, 82, 44, 75, 70, 54, 70, 73, 82, 45, 49, 48, 58, 96, 49, 55, 69, 108, 35, 68, 69, 50, 42, 44, 113, 65, 82, 44, 75, 70, 54, 70, 73, 82, 45, 49, 48, 58, 96, 49, 55, 69, 108, 35,
...@@ -12,61 +12,23 @@ module KISS ...@@ -12,61 +12,23 @@ module KISS
88, 45, 47, 107, 103, 54, 119, 116, 102, 64, 103, 111, 115, 115, 101, 108, 105, 110, 102, 97, 109, 88, 45, 47, 107, 103, 54, 119, 116, 102, 64, 103, 111, 115, 115, 101, 108, 105, 110, 102, 97, 109,
105, 108, 121, 46, 99, 111, 109] 105, 108, 121, 46, 99, 111, 109]
class KISSMock < KISSAbstract class TestKiss < Test::Unit::TestCase
def initialize(strip_df_start=true)
super(strip_df_start)
@read_from_interface = []
@sent_to_interface = []
end
protected
def read_interface
if @read_from_interface.length == 0
return nil
end
return @read_from_interface.shift
end
protected
def write_interface(data)
@sent_to_interface << data
end
public
def clear_interface
@read_from_interface = []
@sent_to_interface = []
end
public
def add_read_from_interface(raw_frame)
@read_from_interface << raw_frame
end
public
def get_sent_to_interface
return @sent_to_interface
end
end
class TestKISS < Test::Unit::TestCase
def test_read def test_read
kiss_mock = KISSMock.new kiss_mock = KissMock.new
kiss_mock.add_read_from_interface(ENCODED_FRAME) kiss_mock.add_read_from_interface(ENCODED_FRAME)
translated_frame = kiss_mock.read translated_frame = kiss_mock.read
assert_equal DECODED_FRAME, translated_frame assert_equal DECODED_FRAME, translated_frame
end end
def test_write def test_write
kiss_mock = KISSMock.new kiss_mock = KissMock.new
kiss_mock.write(DECODED_FRAME) kiss_mock.write(DECODED_FRAME)
all_raw_frames = kiss_mock.get_sent_to_interface all_raw_frames = kiss_mock.get_sent_to_interface
assert_equal ENCODED_FRAME, all_raw_frames[0] assert_equal ENCODED_FRAME, all_raw_frames[0]
end end
def test_new_abstract_kiss def test_new_abstract_kiss
assert_raise(AbstractClassError) { KISSAbstract.new } assert_raise(AbstractClassError) { KissAbstract.new }
end end
end end
end end
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment