Commit 6223b219 authored by Jeffrey Phillips Freeman's avatar Jeffrey Phillips Freeman 💥
Browse files

Made some changes to convert the project into the aprs gem.

parent 4388fd22
......@@ -9,14 +9,14 @@ Gem::Specification.new do |spec|
spec.authors = ['Jeffrey Phillips Freeman']
spec.email = ['jeffrey.freeman@syncleus.com']
spec.summary = %q{Ruby library for APRS communications.}
spec.summary = %q{library for APRS communications.}
spec.description = %q{Ruby library for APRS communications.}
spec.homepage = 'https://github.com/Syncleus/aprs'
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
# to allow pushing to a single host or delete this section to allow pushing to any host.
if spec.respond_to?(:metadata)
spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
spec.metadata['allowed_push_host'] = "https://rubygems.org"
else
raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
end
......@@ -28,11 +28,10 @@ Gem::Specification.new do |spec|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ['lib']
spec.add_dependency 'colorize'
spec.add_dependency 'abstraction'
spec.add_dependency 'json'
spec.add_development_dependency 'bundler'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'rdoc'
spec.add_development_dependency 'aruba'
spec.add_dependency 'abstraction', '~> 0.0.4'
spec.add_dependency 'json', '~> 1.8'
spec.add_development_dependency 'bundler', '~> 1.13'
spec.add_development_dependency 'rake', '~> 11.3'
spec.add_development_dependency 'rdoc', '~> 4.2'
spec.add_development_dependency 'aruba', '~> 0.14'
end
module Kiss
# KISS Special Characters
# http://en.wikipedia.org/wiki/KISS_(TNC)#Special_Characters
FEND = 0xC0
FESC = 0xDB
TFEND = 0xDC
TFESC = 0xDD
# "FEND is sent as FESC, TFEND"
FESC_TFEND = [FESC] + [TFEND]
# "FESC is sent as FESC, TFESC"
FESC_TFESC = [FESC] + [TFESC]
# KISS Command Codes
# http://en.wikipedia.org/wiki/KISS_(TNC)#Command_Codes
DATA_FRAME = 0x00
TX_DELAY = 0x01
PERSISTENCE = 0x02
SLOT_TIME = 0x03
TX_TAIL = 0x04
FULL_DUPLEX = 0x05
SET_HARDWARE = 0x06
RETURN = 0xFF
DEFAULT_KISS_CONFIG_VALUES = {
:TX_DELAY => 40,
:PERSISTENCE => 63,
:SLOT_TIME => 20,
:TX_TAIL => 30,
:FULL_DUPLEX => 0
}
# This command will exit KISS mode
MODE_END = [192, 255, 192, 13]
# This will start kiss on a WA8DED or LINK>.<NORD firmware
MODE_INIT_W8DED = [13, 27, 64, 75, 13]
MODE_INIT_LINKNORD = MODE_INIT_W8DED
# Kenwood D710
MODE_INIT_KENWOOD_D710 = [72, 66, 32, 49, 50, 48, 48, 13, # HB 1200
75, 73, 83, 83, 32, 79, 78, 13, # KISS ON
82, 69, 83, 84, 65, 82, 84, 13] # RESTART
# Kantronics TNCs
MODE_INIT_KANTRONICS = [13, # Blank
73, 78, 84, 32, 75, 73, 83, 83, 13, # INT KISS
82, 69, 83, 84, 65, 82, 84, 13] # RESTART
# TINY2 TNC (TNC2)
MODE_INIT_TINY2 = [13, # Blank
75, 73, 83, 83, 32, 79, 78, 13, # KISS ON
82, 69, 83, 84, 65, 82, 84, 13] # RESTART
# Advanced Electronic Application (later Timewave) PK-232 TNC
MODE_INIT_PK232 = [42, 126, 13, # *~
69, 88, 80, 69, 82, 84, 32, 79, 78, 13, # EXPERT ON
75, 73, 83, 83, 32, 79, 78, 13, # KISS ON
82, 69, 83, 84, 65, 82, 84, 13] # RESTART
end
\ No newline at end of file
require 'thread'
require 'abstraction'
require 'kiss/constants'
module Kiss
class KissAbstract
abstract
protected
def initialize(strip_df_start=true)
@strip_df_start = strip_df_start
@frame_buffer = []
@lock = Mutex.new
end
private
def self.strip_df_start(frame)
while frame[0] == DATA_FRAME
frame.shift
end
while frame[0] and frame[0].chr == ' '
frame.shift
end
while frame[-1] and frame[-1].chr == ' '
frame.pop
end
frame
end
private
def self.escape_special_codes(raw_code_bytes)
encoded_bytes = []
raw_code_bytes.each do |raw_code_byte|
if raw_code_byte == FESC
encoded_bytes += FESC_TFESC
elsif raw_code_byte == FEND
encoded_bytes += FESC_TFEND
else
encoded_bytes += [raw_code_byte]
end
end
encoded_bytes
end
private
def self.command_byte_combine(port, command_code)
if port > 127 or port < 0
raise 'port out of range'
elsif command_code > 127 or command_code < 0
raise 'command_Code out of range'
end
(port << 4) & command_code
end
protected
def write_setting(command, value)
write_interface([FEND] + [command] + escape_special_codes(value) + [FEND])
end
private
def fill_buffer
new_frames = []
read_buffer = []
read_data = read_interface
while read_data and read_data.length > 0
split_data = [[]]
read_data.each do |read_byte|
if read_byte == FEND
split_data << []
else
split_data[-1] << read_byte
end
end
len_fend = split_data.length
# No FEND in frame
if len_fend == 1
read_buffer += split_data[0]
# Single FEND in frame
elsif len_fend == 2
# Closing FEND found
if split_data[0]
# Partial frame continued, otherwise drop
new_frames << read_buffer + split_data[0]
read_buffer = []
# Opening FEND found
else
new_frames << read_buffer
read_buffer = split_data[1]
end
# At least one complete frame received
elsif len_fend >= 3
(0...len_fend - 1).each do |i|
read_buffer_tmp = read_buffer + split_data[i]
if read_buffer_tmp.length > 0
new_frames << read_buffer_tmp
read_buffer = []
end
end
if split_data[len_fend - 1]
read_buffer = split_data[len_fend - 1]
end
end
# Get anymore data that is waiting
read_data = read_interface
end
new_frames.each do |new_frame|
if new_frame.length > 0 and new_frame[0] == 0
if @strip_df_start
new_frame = KissAbstract.strip_df_start(new_frame)
end
@frame_buffer << new_frame
end
end
end
public
def connect(mode_init=nil, *args, **kwargs)
end
public
def close
end
public
def read(*args, **kwargs)
@lock.synchronize do
if @frame_buffer.length == 0
fill_buffer
end
if @frame_buffer.length > 0
return_frame = @frame_buffer[0]
@frame_buffer.shift
return return_frame
else
return nil
end
end
end
public
def write(frame_bytes, port=0, *args, **kwargs)
@lock.synchronize do
kiss_packet = [FEND] + [KissAbstract.command_byte_combine(port, DATA_FRAME)] +
KissAbstract.escape_special_codes(frame_bytes) + [FEND]
write_interface(kiss_packet)
end
end
end
end
\ No newline at end of file
require 'serialport'
require 'kiss/kiss_abstract'
module Kiss
class KissSerial < KissAbstract
DEFAULT_READ_BYTES = 1000
SERIAL_READ_TIMEOUT = -1
protected
def initialize(com_port,
baud=38400,
parity=SerialPort::NONE,
stop_bits=1,
byte_size=8,
read_bytes=DEFAULT_READ_BYTES,
strip_df_start=true)
super(strip_df_start)
@com_port = com_port
@baud = baud
@parity = parity
@stop_bits = stop_bits
@byte_size = byte_size
@read_bytes = read_bytes
@serial = nil
@exit_kiss = false
end
protected
def read_interface
read_data = @serial.read(@read_bytes)
if read_data
return read_data.chars.map { |c| c.ord }
else
return nil
end
end
protected
def write_interface(data)
@serial.write(data)
end
public
def connect(mode_init=nil, **kwargs)
super
@serial = SerialPort.new(@com_port, @baud, @byte_size, @stop_bits, @parity)
@serial.read_timeout = SERIAL_READ_TIMEOUT
if mode_init
@serial.write(mode_init)
@exit_kiss = true
else
@exit_kiss = false
end
# Previous verious defaulted to Xastir-friendly configs. Unfortunately
# those don't work with Bluetooth TNCs, so we're reverting to None.
if kwargs
kwargs.each do |name, value|
write_setting(name, value)
end
end
end
public
def close
super
if @exit_kiss
write_interface(MODE_END)
end
if @serial == nil or @serial.closed?
raise 'Attempting to close before the class has been started.'
else
@serial.close
end
end
end
end
\ No newline at end of file
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 'kiss/test/kiss_mock'
require_relative '../lib/aprs/aprs_kiss'
module Aprs
......
require 'test/unit'
require_relative 'kiss_mock'
module Kiss
# 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,
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,
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]
DECODED_FRAME = [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,
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]
class TestKiss < Test::Unit::TestCase
def test_read
kiss_mock = KissMock.new
kiss_mock.add_read_from_interface(ENCODED_FRAME)
translated_frame = kiss_mock.read
assert_equal DECODED_FRAME, translated_frame
end
def test_write
kiss_mock = KissMock.new
kiss_mock.write(DECODED_FRAME)
all_raw_frames = kiss_mock.get_sent_to_interface
assert_equal ENCODED_FRAME, all_raw_frames[0]
end
def test_new_abstract_kiss
assert_raise(AbstractClassError) { KissAbstract.new }
end
end
end
\ No newline at end of file
Markdown is supported
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