kiss-tnc 1.0.2 → 2.0.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: 99d6c50a0bf885718135a8dc1cb68981f3687e4c
4
- data.tar.gz: 537b7c2326b4178c298a95b2ceb914847f3b89c2
2
+ SHA256:
3
+ metadata.gz: de2de9bab4531fa71c87064c557b99545191a14ca86d094c46be3969f7d326a9
4
+ data.tar.gz: d6623ac8144ac07a344262577aec994a4841ef5cd1e47a2b84c0ea398a8d3e2a
5
5
  SHA512:
6
- metadata.gz: 98e0c08a289ff4e3a2c7dc3b16d7447ba0ca7a4199d17b0f06c88c16d209723517e61080172b3aaaa493756c529e28fce8a9a2592a9b540f1d5c024f7683bfbd
7
- data.tar.gz: 1f45a81b214692a2e64e1749190bcea353efd8c93ef9599d8c97640dd0e75ca6e169abd3da79f01dc3769ccf0a35010818dbba47628377c1a13e7484891fecc5
6
+ metadata.gz: 56e1500ab363d8382e9d4f5324cdb9df36f9516974c01edf4c93e985e31a0597d50ff812853e101146f61838f563a832487309298a6c9427c3221a48d964463e
7
+ data.tar.gz: cfe67d7786440d421a7b676407c9efc102b1b6e568805b9992995d762eebf4758fc3b0110804cd115b319ecc42e04caa08fa7854fb10f2141e1c5e5c853961fe
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,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.0
4
+
5
+ * Moved abstraction over to abstractify library.
6
+ * Added more parsing methods so entry points now take strings rather than KISS encoded data.
7
+ * Added errors where appropriate, for example writing invalid frames now throw an IOError.
8
+
9
+ ## 1.0.3
10
+
11
+ * Changed KissSerial so its methods can accept any arguments, used for abstraction purposes.
12
+
3
13
  ## 1.0.2
4
14
 
5
15
  * Fixed a bug where bytes were not written to the serial stream correctly.
@@ -12,4 +22,4 @@
12
22
 
13
23
  ## 1.0.0
14
24
 
15
- * Initial release
25
+ * Initial release
data/CONTRIBUTORS.md ADDED
@@ -0,0 +1,19 @@
1
+ ## Current Project Lead
2
+
3
+ * Jeffrey Phillips Freeman (WI2ARD) - http://JeffreyFreeman.me
4
+
5
+ ## Past Contributors
6
+
7
+ * Greg Albrecht W2GMD <oss@undef.net>
8
+ * Martin Murray (KD8LVZ)
9
+ * Paul McMillan - https://github.com/PaulMcMillan
10
+ * Russ Innes
11
+ * John Hogenmiller (KB3DFZ) - https://github.com/ytjohn
12
+ * Phil Gagnon N1HHG
13
+ * Ben Benesh - https://github.com/bbene
14
+ * Joe Goforth
15
+ * Rick Eason
16
+ * Jay Nugent
17
+ * Pete Loveall (AE5PL)
18
+ * darksidelemm - https://github.com/darksidelemm
19
+ * agmuino - https://github.com/agmuino
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.2"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -1,10 +1,12 @@
1
1
  require 'thread'
2
- require 'abstraction'
2
+ require 'abstractify'
3
3
  require 'kiss/constants'
4
4
 
5
5
  module Kiss
6
6
  class KissAbstract
7
- abstract
7
+ include Abstractify::Abstract
8
+
9
+ abstract :write_interface, :read_interface, :connect, :close
8
10
 
9
11
  protected
10
12
  def initialize(strip_df_start=true)
@@ -52,9 +54,132 @@ module Kiss
52
54
  (port << 4) & command_code
53
55
  end
54
56
 
55
- protected
56
- def write_setting(command, value)
57
- write_interface([FEND] + [command] + escape_special_codes(value) + [FEND])
57
+ private
58
+ def self.extract_path(start, raw_frame)
59
+ full_path = []
60
+
61
+ (2...start).each do |i|
62
+ path = identity_as_string(extract_callsign(raw_frame[i * 7..-1]))
63
+ if path and path.length > 0
64
+ if raw_frame[i * 7 + 6] & 0x80 != 0
65
+ full_path << [path, '*'].join
66
+ else
67
+ full_path << path
68
+ end
69
+ end
70
+ end
71
+ return full_path
72
+ end
73
+
74
+ private
75
+ def self.parse_identity_string(identity_string)
76
+ # If we are parsing a spent token then first lets get rid of the astresick suffix.
77
+ if identity_string[-1] == '*'
78
+ identity_string = identity_string[0..-1]
79
+ end
80
+
81
+ if identity_string.include? '-'
82
+ call_sign, ssid = identity_string.split('-')
83
+ else
84
+ call_sign = identity_string
85
+ ssid = 0
86
+ end
87
+
88
+ return {:callsign => call_sign, :ssid => ssid.to_i}
89
+ end
90
+
91
+ private
92
+ def self.identity_as_string(identity)
93
+ if identity[:ssid] and identity[:ssid] > 0
94
+ return [identity[:callsign], identity[:ssid].to_s].join('-')
95
+ else
96
+ return identity[:callsign]
97
+ end
98
+ end
99
+
100
+ private
101
+ def self.extract_callsign(raw_frame)
102
+ callsign_as_array = raw_frame[0...6].map { |x| (x >> 1).chr }
103
+ callsign = callsign_as_array.join.strip
104
+ ssid = (raw_frame[6] >> 1) & 0x0f
105
+ ssid = (ssid == nil or ssid == 0 ? nil : ssid)
106
+ return {:callsign => callsign, :ssid => ssid}
107
+ end
108
+
109
+ private
110
+ def self.encode_callsign(callsign)
111
+ call_sign = callsign[:callsign]
112
+
113
+ enc_ssid = (callsign[:ssid] << 1) | 0x60
114
+
115
+ if call_sign.include? '*'
116
+ call_sign.gsub!(/\*/, '')
117
+ enc_ssid |= 0x80
118
+ end
119
+
120
+ while call_sign.length < 6
121
+ call_sign = [call_sign, ' '].join
122
+ end
123
+
124
+ return call_sign.chars.map { |p| p.ord << 1 } + [enc_ssid]
125
+ end
126
+
127
+ private
128
+ def self.encode_frame(frame)
129
+ enc_frame = encode_callsign(parse_identity_string(frame[:destination].to_s)) + encode_callsign(parse_identity_string(frame[:source].to_s))
130
+
131
+ frame[:path].each do |hop|
132
+ enc_frame += encode_callsign(parse_identity_string(hop.to_s))
133
+ end
134
+
135
+ return enc_frame[0...-1] + [enc_frame[-1] | 0x01] + [Kiss::SLOT_TIME] + [0xf0] + frame[:payload].chars.map { |c| c.ord }
136
+ end
137
+
138
+ private
139
+ def self.decode_frame(raw_frame)
140
+ frame_len = raw_frame.length
141
+
142
+ if frame_len > 16
143
+ (0...frame_len - 2).each do |raw_slice|
144
+ # Is address field length correct?
145
+ if raw_frame[raw_slice] & 0x01 != 0 and ((raw_slice + 1) % 7) == 0
146
+ i = (raw_slice.to_f + 1.0) / 7.0
147
+ # Less than 2 callsigns?
148
+ if 1.0 < i and i < 11.0
149
+ if raw_frame[raw_slice + 1] & 0x03 == 0x03 and [0xf0, 0xcf].include? raw_frame[raw_slice + 2]
150
+ payload_as_array = raw_frame[raw_slice + 3..-1].map { |b| b.chr }
151
+ payload = payload_as_array.join
152
+ destination = identity_as_string(extract_callsign(raw_frame))
153
+ source = identity_as_string(extract_callsign(raw_frame[7..-1]))
154
+ path = extract_path(i.to_i, raw_frame)
155
+ return {:source => source, :destination => destination, :path => path, :payload => payload}
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
161
+ return nil
162
+ end
163
+
164
+ private
165
+ def self.valid_frame(raw_frame)
166
+ frame_len = raw_frame.length
167
+
168
+ if frame_len > 16
169
+ (0...frame_len - 2).each do |raw_slice|
170
+ # Is address field length correct?
171
+ if raw_frame[raw_slice] & 0x01 != 0 and ((raw_slice + 1) % 7) == 0
172
+ i = (raw_slice.to_f + 1.0) / 7.0
173
+ # Less than 2 callsigns?
174
+ if 1.0 < i and i < 11.0
175
+ if raw_frame[raw_slice + 1] & 0x03 == 0x03 and [0xf0, 0xcf].include? raw_frame[raw_slice + 2]
176
+ return true
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end
182
+ return false
58
183
  end
59
184
 
60
185
  private
@@ -115,39 +240,64 @@ module Kiss
115
240
  end
116
241
  end
117
242
 
243
+ private
244
+ def read_bytes(*args, **kwargs)
245
+ if @frame_buffer.length == 0
246
+ fill_buffer
247
+ end
248
+
249
+ if @frame_buffer.length > 0
250
+ return_frame = @frame_buffer[0]
251
+ @frame_buffer.shift
252
+ return return_frame
253
+ else
254
+ return nil
255
+ end
256
+ end
257
+
258
+ private
259
+ def write_bytes(frame_bytes, port=0, *args, **kwargs)
260
+ kiss_packet = [FEND] + [KissAbstract.command_byte_combine(port, DATA_FRAME)] +
261
+ KissAbstract.escape_special_codes(frame_bytes) + [FEND]
262
+
263
+ write_interface(kiss_packet)
264
+ end
265
+
266
+ protected
267
+ def write_setting(command, value)
268
+ write_interface([FEND] + [command] + KissAbstract.escape_special_codes(value) + [FEND])
269
+ end
270
+
118
271
  public
119
272
  def connect(mode_init=nil, *args, **kwargs)
120
273
  end
121
274
 
122
275
  public
123
- def close
276
+ def close(*args, **kwargs)
124
277
  end
125
278
 
126
279
  public
127
280
  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
281
+ @lock.synchronize do
282
+ frame = self.read_bytes(*args, **kwargs)
283
+ if frame and frame.length > 0
284
+ return KissAbstract.decode_frame(frame)
285
+ else
286
+ return nil
287
+ end
288
+ end
141
289
  end
142
290
 
143
291
  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
292
+ def write(frame, port=0, *args, **kwargs)
293
+ @lock.synchronize do
294
+ encoded_frame = KissAbstract.encode_frame(frame)
295
+ if KissAbstract.valid_frame(encoded_frame)
296
+ self.write_bytes(encoded_frame, *args, **kwargs)
297
+ else
298
+ raise IOError.new("frame was able to be encoded but was determined not to be valid")
299
+ end
300
+ end
151
301
  end
152
302
  end
153
- end
303
+ end
@@ -46,7 +46,7 @@ module Kiss
46
46
  end
47
47
 
48
48
  public
49
- def connect(mode_init=nil, **kwargs)
49
+ def connect(mode_init=nil, *args, **kwargs)
50
50
  super
51
51
 
52
52
  @serial = SerialPort.new(@com_port, @baud, @byte_size, @stop_bits, @parity)
@@ -69,7 +69,7 @@ module Kiss
69
69
  end
70
70
 
71
71
  public
72
- def close
72
+ def close(*args, **kwargs)
73
73
  super
74
74
 
75
75
  if @exit_kiss
@@ -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
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.2
4
+ version: 2.0.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-04 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,7 +116,9 @@ extensions: []
102
116
  extra_rdoc_files: []
103
117
  files:
104
118
  - ".gitignore"
119
+ - ".rspec"
105
120
  - CHANGELOG.md
121
+ - CONTRIBUTORS.md
106
122
  - Gemfile
107
123
  - LICENSE
108
124
  - README.md
@@ -114,14 +130,12 @@ files:
114
130
  - lib/kiss/constants.rb
115
131
  - lib/kiss/kiss_abstract.rb
116
132
  - lib/kiss/kiss_serial.rb
117
- - lib/kiss/test.rb
118
- - lib/kiss/test/kiss_mock.rb
119
- homepage: https://github.com/Syncleus/aprs
133
+ homepage: https://git.qoto.org/digipex/kiss-tnc
120
134
  licenses:
121
135
  - Apache-2.0
122
136
  metadata:
123
137
  allowed_push_host: https://rubygems.org
124
- post_install_message:
138
+ post_install_message:
125
139
  rdoc_options: []
126
140
  require_paths:
127
141
  - lib
@@ -136,9 +150,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
136
150
  - !ruby/object:Gem::Version
137
151
  version: '0'
138
152
  requirements: []
139
- rubyforge_project:
140
- rubygems_version: 2.5.1
141
- signing_key:
153
+ rubygems_version: 3.4.17
154
+ signing_key:
142
155
  specification_version: 4
143
156
  summary: Library for KISS communication with TNCs.
144
157
  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'