kiss-tnc 1.0.3 → 2.1.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
- SHA1:
3
- metadata.gz: 394d48eb1bdb8bda7bc9283a58b8b7ec8d53585b
4
- data.tar.gz: ce5f3281c95c4d13e740944a3b709715e527cbe6
2
+ SHA256:
3
+ metadata.gz: '09b09122da0f586f8c540ad8327c90ac04b5461b1fc6a7ed82e4a19319f23330'
4
+ data.tar.gz: 1c126ad07648e80290e873ed49cf9bf9c6672d3ea9e2d181ff977a54d6208a46
5
5
  SHA512:
6
- metadata.gz: 768bfa681b99bc095b97499cdf73b73490bd0abee0319710d13af7e57a81785ff09ef260a74476fd826748475ba0e9b538849666676509b970ddb4c9f4594b2a
7
- data.tar.gz: 1bcf99dd124fdea56a27529e76a0cd706ecf42fed6f9ece186781143242be71a9b702506df4f9a116f84d589c6feebf9f14acca36b2455caf99e5b2c22c2cf1b
6
+ metadata.gz: 2b0df5c966c1e2082162902ec988dff74d455ebe831f774e4df32768e6ea91ece147168714fa36cd71014616f6eb384550391003a22092bace28ab6672c066f8
7
+ data.tar.gz: f6fa098359c055522eddbcabd135244e06a4d06e37b0682556e77fbd9b0c0d017bce82c25c6fad12f06c2be358647511b562be09db7ee354514720230a226764
data/.gitignore CHANGED
@@ -5,3 +5,4 @@ html
5
5
  Gemfile.lock
6
6
  .idea/
7
7
  *.gem
8
+ /public/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.1.0
4
+
5
+ * Added a parent interface to KissAbstract called Kiss
6
+
7
+ ## 2.0.0
8
+
9
+ * Moved abstraction over to abstractify library.
10
+ * Added more parsing methods so entry points now take strings rather than KISS encoded data.
11
+ * Added errors where appropriate, for example writing invalid frames now throw an IOError.
12
+ * The write and read methods now take frames in the form of a map of strings, all encoding is now handled by the library.
13
+
3
14
  ## 1.0.3
4
15
 
5
16
  * Changed KissSerial so its methods can accept any arguments, used for abstraction purposes.
@@ -16,4 +27,4 @@
16
27
 
17
28
  ## 1.0.0
18
29
 
19
- * Initial release
30
+ * Initial release
data/CONTRIBUTORS.md CHANGED
@@ -1,4 +1,10 @@
1
+ ## Current Project Lead
2
+
1
3
  * Jeffrey Phillips Freeman (WI2ARD) - http://JeffreyFreeman.me
4
+
5
+ ## Contributors
6
+
7
+ * Greg Albrecht W2GMD <oss@undef.net>
2
8
  * Martin Murray (KD8LVZ)
3
9
  * Paul McMillan - https://github.com/PaulMcMillan
4
10
  * Russ Innes
data/Rakefile CHANGED
@@ -24,44 +24,43 @@ def dump_load_path
24
24
  end
25
25
  end
26
26
 
27
- gem 'json', '~> 1.8.3'
28
-
29
- gem 'bundler', '~> 1.7'
27
+ # gem 'json', '~> 1.8.3'
28
+ #
29
+ # gem 'bundler', '~> 1.7'
30
30
  require 'bundler'
31
31
 
32
- gem 'rake', '~> 11.3.0'
32
+ # gem 'rake', '~> 11.3.0'
33
33
  require 'rake/clean'
34
34
  require 'rake/testtask'
35
35
 
36
36
 
37
- require 'cucumber'
38
- require 'cucumber/rake/task'
39
- gem 'rdoc' # we need the installed RDoc gem, not the system one
40
- require 'rdoc/task'
37
+ # require 'cucumber'
38
+ # require 'cucumber/rake/task'
39
+ # gem 'rdoc' # we need the installed RDoc gem, not the system one
40
+ # require 'rdoc/task'
41
41
 
42
42
  include Rake::DSL
43
43
 
44
44
  Bundler::GemHelper.install_tasks
45
45
 
46
46
 
47
- Rake::TestTask.new do |t|
48
- t.pattern = 'test/tc_*.rb'
49
- end
50
-
51
-
52
- CUKE_RESULTS = 'results.html'
53
- CLEAN << CUKE_RESULTS
54
- Cucumber::Rake::Task.new(:features) do |t|
55
- t.cucumber_opts = "features --format html -o #{CUKE_RESULTS} --format pretty --no-source -x"
56
- t.fork = false
57
- end
58
-
59
- Rake::RDocTask.new do |rd|
47
+ # Rake::TestTask.new do |t|
48
+ # t.pattern = 'test/tc_*.rb'
49
+ # end
60
50
 
61
- rd.main = "README.rdoc"
62
-
63
- rd.rdoc_files.include("README.rdoc", "lib/**/*.rb", "bin/**/*")
64
- end
65
51
 
66
- task :default => [:test, :features]
52
+ # CUKE_RESULTS = 'results.html'
53
+ # CLEAN << CUKE_RESULTS
54
+ # Cucumber::Rake::Task.new(:features) do |t|
55
+ # t.cucumber_opts = "features --format html -o #{CUKE_RESULTS} --format pretty --no-source -x"
56
+ # t.fork = false
57
+ # end
67
58
 
59
+ # Rake::RDocTask.new do |rd|
60
+ #
61
+ # rd.main = "README.rdoc"
62
+ #
63
+ # rd.rdoc_files.include("README.rdoc", "lib/**/*.rb", "bin/**/*")
64
+ # end
65
+ #
66
+ # task :default => [:test, :features]
data/kiss-tnc.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
 
13
13
  spec.summary = %q{Library for KISS communication with TNCs.}
14
14
  spec.description = %q{Ruby library for KISS communication with Terminal Node Controllers.}
15
- spec.homepage = 'https://github.com/Syncleus/aprs'
15
+ spec.homepage = 'https://git.qoto.org/digipex/kiss-tnc'
16
16
 
17
17
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
18
  # to allow pushing to a single host or delete this section to allow pushing to any host.
@@ -29,10 +29,12 @@ Gem::Specification.new do |spec|
29
29
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
30
  spec.require_paths = ['lib']
31
31
 
32
- spec.add_dependency 'abstraction', '~> 0.0.4'
32
+ spec.add_dependency 'abstractify', '~> 1.1'
33
33
  spec.add_dependency 'serialport', '~> 1.3'
34
- spec.add_development_dependency 'bundler', '~> 1.7'
35
- spec.add_development_dependency 'rake', '~> 11.3'
36
- spec.add_development_dependency 'rdoc', '~> 4.2'
37
- spec.add_development_dependency 'aruba', '~> 0.14'
34
+ spec.add_development_dependency 'bundler', '~> 2.3'
35
+ spec.add_development_dependency 'rake', '~> 13.0'
36
+ spec.add_development_dependency 'rspec', '~> 3.12'
37
+ spec.add_development_dependency 'simplecov', '~> 0.22'
38
+ spec.add_development_dependency 'simplecov-console', '~> 0.9'
39
+ #spec.add_development_dependency 'rdoc', '~> 6.5'
38
40
  end
data/lib/kiss/app_info.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Kiss
2
- VERSION = "1.0.3"
2
+ VERSION = "2.1.0"
3
3
  end
data/lib/kiss/kiss.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'abstractify'
2
+
3
+ module Kiss
4
+ class Kiss
5
+ include Abstractify::Abstract
6
+
7
+ abstract :write_interface, :read_interface, :connect, :close
8
+ end
9
+ end
@@ -1,10 +1,13 @@
1
1
  require 'thread'
2
- require 'abstraction'
2
+ require 'abstractify'
3
3
  require 'kiss/constants'
4
+ require 'kiss/kiss'
4
5
 
5
6
  module Kiss
6
- class KissAbstract
7
- abstract
7
+ class KissAbstract < Kiss
8
+ include Abstractify::Abstract
9
+
10
+ abstract :write_interface, :read_interface, :connect, :close
8
11
 
9
12
  protected
10
13
  def initialize(strip_df_start=true)
@@ -52,9 +55,132 @@ module Kiss
52
55
  (port << 4) & command_code
53
56
  end
54
57
 
55
- protected
56
- def write_setting(command, value)
57
- write_interface([FEND] + [command] + escape_special_codes(value) + [FEND])
58
+ private
59
+ def self.extract_path(start, raw_frame)
60
+ full_path = []
61
+
62
+ (2...start).each do |i|
63
+ path = identity_as_string(extract_callsign(raw_frame[i * 7..-1]))
64
+ if path and path.length > 0
65
+ if raw_frame[i * 7 + 6] & 0x80 != 0
66
+ full_path << [path, '*'].join
67
+ else
68
+ full_path << path
69
+ end
70
+ end
71
+ end
72
+ return full_path
73
+ end
74
+
75
+ private
76
+ def self.parse_identity_string(identity_string)
77
+ # If we are parsing a spent token then first lets get rid of the astresick suffix.
78
+ if identity_string[-1] == '*'
79
+ identity_string = identity_string[0..-1]
80
+ end
81
+
82
+ if identity_string.include? '-'
83
+ call_sign, ssid = identity_string.split('-')
84
+ else
85
+ call_sign = identity_string
86
+ ssid = 0
87
+ end
88
+
89
+ return {:callsign => call_sign, :ssid => ssid.to_i}
90
+ end
91
+
92
+ private
93
+ def self.identity_as_string(identity)
94
+ if identity[:ssid] and identity[:ssid] > 0
95
+ return [identity[:callsign], identity[:ssid].to_s].join('-')
96
+ else
97
+ return identity[:callsign]
98
+ end
99
+ end
100
+
101
+ private
102
+ def self.extract_callsign(raw_frame)
103
+ callsign_as_array = raw_frame[0...6].map { |x| (x >> 1).chr }
104
+ callsign = callsign_as_array.join.strip
105
+ ssid = (raw_frame[6] >> 1) & 0x0f
106
+ ssid = (ssid == nil or ssid == 0 ? nil : ssid)
107
+ return {:callsign => callsign, :ssid => ssid}
108
+ end
109
+
110
+ private
111
+ def self.encode_callsign(callsign)
112
+ call_sign = callsign[:callsign]
113
+
114
+ enc_ssid = (callsign[:ssid] << 1) | 0x60
115
+
116
+ if call_sign.include? '*'
117
+ call_sign.gsub!(/\*/, '')
118
+ enc_ssid |= 0x80
119
+ end
120
+
121
+ while call_sign.length < 6
122
+ call_sign = [call_sign, ' '].join
123
+ end
124
+
125
+ return call_sign.chars.map { |p| p.ord << 1 } + [enc_ssid]
126
+ end
127
+
128
+ private
129
+ def self.encode_frame(frame)
130
+ enc_frame = encode_callsign(parse_identity_string(frame[:destination].to_s)) + encode_callsign(parse_identity_string(frame[:source].to_s))
131
+
132
+ frame[:path].each do |hop|
133
+ enc_frame += encode_callsign(parse_identity_string(hop.to_s))
134
+ end
135
+
136
+ return enc_frame[0...-1] + [enc_frame[-1] | 0x01] + [SLOT_TIME] + [0xf0] + frame[:payload].chars.map { |c| c.ord }
137
+ end
138
+
139
+ private
140
+ def self.decode_frame(raw_frame)
141
+ frame_len = raw_frame.length
142
+
143
+ if frame_len > 16
144
+ (0...frame_len - 2).each do |raw_slice|
145
+ # Is address field length correct?
146
+ if raw_frame[raw_slice] & 0x01 != 0 and ((raw_slice + 1) % 7) == 0
147
+ i = (raw_slice.to_f + 1.0) / 7.0
148
+ # Less than 2 callsigns?
149
+ if 1.0 < i and i < 11.0
150
+ if raw_frame[raw_slice + 1] & 0x03 == 0x03 and [0xf0, 0xcf].include? raw_frame[raw_slice + 2]
151
+ payload_as_array = raw_frame[raw_slice + 3..-1].map { |b| b.chr }
152
+ payload = payload_as_array.join
153
+ destination = identity_as_string(extract_callsign(raw_frame))
154
+ source = identity_as_string(extract_callsign(raw_frame[7..-1]))
155
+ path = extract_path(i.to_i, raw_frame)
156
+ return {:source => source, :destination => destination, :path => path, :payload => payload}
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
162
+ return nil
163
+ end
164
+
165
+ private
166
+ def self.valid_frame(raw_frame)
167
+ frame_len = raw_frame.length
168
+
169
+ if frame_len > 16
170
+ (0...frame_len - 2).each do |raw_slice|
171
+ # Is address field length correct?
172
+ if raw_frame[raw_slice] & 0x01 != 0 and ((raw_slice + 1) % 7) == 0
173
+ i = (raw_slice.to_f + 1.0) / 7.0
174
+ # Less than 2 callsigns?
175
+ if 1.0 < i and i < 11.0
176
+ if raw_frame[raw_slice + 1] & 0x03 == 0x03 and [0xf0, 0xcf].include? raw_frame[raw_slice + 2]
177
+ return true
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
183
+ return false
58
184
  end
59
185
 
60
186
  private
@@ -115,6 +241,34 @@ module Kiss
115
241
  end
116
242
  end
117
243
 
244
+ private
245
+ def read_bytes(*args, **kwargs)
246
+ if @frame_buffer.length == 0
247
+ fill_buffer
248
+ end
249
+
250
+ if @frame_buffer.length > 0
251
+ return_frame = @frame_buffer[0]
252
+ @frame_buffer.shift
253
+ return return_frame
254
+ else
255
+ return nil
256
+ end
257
+ end
258
+
259
+ private
260
+ def write_bytes(frame_bytes, port=0, *args, **kwargs)
261
+ kiss_packet = [FEND] + [KissAbstract.command_byte_combine(port, DATA_FRAME)] +
262
+ KissAbstract.escape_special_codes(frame_bytes) + [FEND]
263
+
264
+ write_interface(kiss_packet)
265
+ end
266
+
267
+ protected
268
+ def write_setting(command, value)
269
+ write_interface([FEND] + [command] + KissAbstract.escape_special_codes(value) + [FEND])
270
+ end
271
+
118
272
  public
119
273
  def connect(mode_init=nil, *args, **kwargs)
120
274
  end
@@ -125,29 +279,26 @@ module Kiss
125
279
 
126
280
  public
127
281
  def read(*args, **kwargs)
128
- @lock.synchronize do
129
- if @frame_buffer.length == 0
130
- fill_buffer
131
- end
132
-
133
- if @frame_buffer.length > 0
134
- return_frame = @frame_buffer[0]
135
- @frame_buffer.shift
136
- return return_frame
137
- else
138
- return nil
139
- end
140
- end
282
+ @lock.synchronize do
283
+ frame = self.read_bytes(*args, **kwargs)
284
+ if frame and frame.length > 0
285
+ return KissAbstract.decode_frame(frame)
286
+ else
287
+ return nil
288
+ end
289
+ end
141
290
  end
142
291
 
143
292
  public
144
- def write(frame_bytes, port=0, *args, **kwargs)
145
- @lock.synchronize do
146
- kiss_packet = [FEND] + [KissAbstract.command_byte_combine(port, DATA_FRAME)] +
147
- KissAbstract.escape_special_codes(frame_bytes) + [FEND]
148
-
149
- write_interface(kiss_packet)
150
- end
293
+ def write(frame, port=0, *args, **kwargs)
294
+ @lock.synchronize do
295
+ encoded_frame = KissAbstract.encode_frame(frame)
296
+ if KissAbstract.valid_frame(encoded_frame)
297
+ self.write_bytes(encoded_frame, *args, **kwargs)
298
+ else
299
+ raise IOError.new("frame was able to be encoded but was determined not to be valid")
300
+ end
301
+ end
151
302
  end
152
303
  end
153
- end
304
+ end
@@ -77,10 +77,10 @@ module Kiss
77
77
  end
78
78
 
79
79
  if @serial == nil or @serial.closed?
80
- raise 'Attempting to close before the class has been started.'
80
+ raise IOError.new('Attempting to close before the class has been started.')
81
81
  else
82
82
  @serial.close
83
83
  end
84
84
  end
85
85
  end
86
- end
86
+ end
data/lib/kiss.rb CHANGED
@@ -1,3 +1,5 @@
1
1
  require 'kiss/app_info'
2
2
  require 'kiss/kiss_serial'
3
- require 'kiss/constants'
3
+ require 'kiss/constants'
4
+ require 'kiss/kiss_abstract'
5
+ require 'kiss/kiss'
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kiss-tnc
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeffrey Phillips Freeman
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-10-05 00:00:00.000000000 Z
11
+ date: 2023-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: abstraction
14
+ name: abstractify
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.0.4
19
+ version: '1.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.0.4
26
+ version: '1.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: serialport
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,56 +44,70 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.7'
47
+ version: '2.3'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.7'
54
+ version: '2.3'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '11.3'
61
+ version: '13.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '11.3'
68
+ version: '13.0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rdoc
70
+ name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '4.2'
75
+ version: '3.12'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '4.2'
82
+ version: '3.12'
83
83
  - !ruby/object:Gem::Dependency
84
- name: aruba
84
+ name: simplecov
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0.14'
89
+ version: '0.22'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0.14'
96
+ version: '0.22'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov-console
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.9'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.9'
97
111
  description: Ruby library for KISS communication with Terminal Node Controllers.
98
112
  email:
99
113
  - jeffrey.freeman@syncleus.com
@@ -102,6 +116,7 @@ extensions: []
102
116
  extra_rdoc_files: []
103
117
  files:
104
118
  - ".gitignore"
119
+ - ".rspec"
105
120
  - CHANGELOG.md
106
121
  - CONTRIBUTORS.md
107
122
  - Gemfile
@@ -113,16 +128,15 @@ files:
113
128
  - lib/kiss.rb
114
129
  - lib/kiss/app_info.rb
115
130
  - lib/kiss/constants.rb
131
+ - lib/kiss/kiss.rb
116
132
  - lib/kiss/kiss_abstract.rb
117
133
  - lib/kiss/kiss_serial.rb
118
- - lib/kiss/test.rb
119
- - lib/kiss/test/kiss_mock.rb
120
- homepage: https://github.com/Syncleus/aprs
134
+ homepage: https://git.qoto.org/digipex/kiss-tnc
121
135
  licenses:
122
136
  - Apache-2.0
123
137
  metadata:
124
138
  allowed_push_host: https://rubygems.org
125
- post_install_message:
139
+ post_install_message:
126
140
  rdoc_options: []
127
141
  require_paths:
128
142
  - lib
@@ -137,9 +151,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
151
  - !ruby/object:Gem::Version
138
152
  version: '0'
139
153
  requirements: []
140
- rubyforge_project:
141
- rubygems_version: 2.5.1
142
- signing_key:
154
+ rubygems_version: 3.4.17
155
+ signing_key:
143
156
  specification_version: 4
144
157
  summary: Library for KISS communication with TNCs.
145
158
  test_files: []
@@ -1,41 +0,0 @@
1
- require 'kiss/kiss_abstract'
2
-
3
- module Kiss
4
- class KissMock < KissAbstract
5
-
6
- def initialize(strip_df_start=true)
7
- super(strip_df_start)
8
- @read_from_interface = []
9
- @sent_to_interface = []
10
- end
11
-
12
- protected
13
- def read_interface
14
- if @read_from_interface.length == 0
15
- return nil
16
- end
17
- return @read_from_interface.shift
18
- end
19
-
20
- protected
21
- def write_interface(data)
22
- @sent_to_interface << data
23
- end
24
-
25
- public
26
- def clear_interface
27
- @read_from_interface = []
28
- @sent_to_interface = []
29
- end
30
-
31
- public
32
- def add_read_from_interface(raw_frame)
33
- @read_from_interface << raw_frame
34
- end
35
-
36
- public
37
- def get_sent_to_interface
38
- return @sent_to_interface
39
- end
40
- end
41
- end
data/lib/kiss/test.rb DELETED
@@ -1 +0,0 @@
1
- require 'kiss/test/kiss_mock'