kiss-tnc 2.1.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cb77dc5922f2db446d2525759dd1bd3810bf1e1af39a540b5cb3bb228aa5665e
4
- data.tar.gz: 1c8220134ab81ef510dca73ff16d3f57054130cb819883895109e1fa14e3e0da
3
+ metadata.gz: 61dbec4bf66f1db239d96585ba818fb83bb42f657c24cd01dfa51c6df0ced59d
4
+ data.tar.gz: 3f3ee940d016ba7c7f138cf0f9decc38d5f56b4506d94c51aae78aa60df27add
5
5
  SHA512:
6
- metadata.gz: c7df53d5fdf834592d5ccd1024d689a0f265610f2cda5bbc93d2290c1fb8a6153b10cfae37142824870aa31e91f88b22af637810a7039092f7c3cd9588d1c267
7
- data.tar.gz: c6f23c7122e5b1fcfb14813d6a6b2e13725569cd44fc35343fcda47a4a2b12acf00bbcc96143650ca66a3665358225fdf4ef9df05847634d194129b9b6265e88
6
+ metadata.gz: 99031072302ad853d9129aab307df24246adc382fb6b87f8c246d412fa2e49973bbba4c69df783040418dbfcc5accb7a85e3157c06b98811b986fd500e780afc
7
+ data.tar.gz: d9250c3e5708faa3e2a71336e008111f8b600e31d67e7ab6e211f54de2c6733a0c6fc70562139c940fb307b24e5d727cde5a226d6a4fc5cbd2d837afc01df6de
data/.gitignore CHANGED
@@ -6,3 +6,4 @@ Gemfile.lock
6
6
  .idea/
7
7
  *.gem
8
8
  /public/
9
+ /vendor/
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.0.0
4
+ * Moved all elements of AX.25 out into its own library (https://git.qoto.org/digipex/ax25).
5
+ * No longer backwards compatible with older versions.
6
+
7
+ ## 2.1.3
8
+
9
+ * Had to revert some of the changes from the last release... KissAbstract now uses include again and kind_of should now work (unit test added to confirm).
10
+
3
11
  ## 2.1.2
4
12
 
5
13
  * KissAbstract now extends Kiss::Kiss rather than just including it (so kind_of will work).
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Gem Version](https://badge.fury.io/rb/kiss-tnc.svg)](https://badge.fury.io/rb/kiss-tnc)
2
+
1
3
  # Kiss
2
4
 
3
5
  Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/apex`. To experiment with that code, run `bin/console` for an interactive prompt.
@@ -20,17 +22,18 @@ Or install it yourself as:
20
22
 
21
23
  $ gem install kiss-tnc
22
24
 
23
- ## Usage
24
-
25
- TODO: Write usage instructions here
26
-
27
25
  ## Development
28
26
 
29
27
  After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
28
 
31
29
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
30
 
31
+ To run tests do the following:
32
+
33
+ ```bash
34
+ bundle exec rspec
35
+ ```
36
+
33
37
  ## Contributing
34
38
 
35
39
  Bug reports and pull requests are welcome on GitHub at https://github.com/Syncleus/kiss-tnc
36
-
data/kiss-tnc.gemspec CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Kiss::VERSION
9
9
  spec.licenses = ['Apache-2.0']
10
10
  spec.authors = ['Jeffrey Phillips Freeman']
11
- spec.email = ['jeffrey.freeman@syncleus.com']
11
+ spec.email = ['the@jeffreyfreeman.me']
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.}
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
26
26
  f.match(%r{^(test|spec|features)/})
27
27
  end
28
- spec.bindir = 'exe'
28
+ spec.bindir = 'bin'
29
29
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
30
  spec.require_paths = ['lib']
31
31
 
data/lib/kiss/app_info.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Kiss
2
- VERSION = "2.1.2"
2
+ VERSION = "3.0.0"
3
3
  end
data/lib/kiss/kiss.rb CHANGED
@@ -4,6 +4,101 @@ module Kiss
4
4
  module Kiss
5
5
  include Abstractify::Abstract
6
6
 
7
- abstract :write_interface, :read_interface, :connect, :close
7
+ abstract :write_interface, :read_interface, :connect, :close, :read_datagram, :write_generic_command, :write_datagram, :write_tx_delay, :write_persistence, :write_slot_time, :write_tx_tail, :write_full_duplex, :write_set_hardware, :write_exit_kiss_mode
8
+
9
+ ##
10
+ # Reads raw data as a byte array off the underlying stream. This data is
11
+ # before escapaing, or extracting from the frame.
12
+ protected
13
+ def read_interface(*args, **kwargs)
14
+ end
15
+
16
+ ##
17
+ # Writes raw bytes to the underlying stream. The bytes should already begin
18
+ # escaped and framed by this point.
19
+ protected
20
+ def write_interface(data, *args, **kwargs)
21
+ end
22
+
23
+ ##
24
+ # Prepares the underlying connection for reading and writing. What this
25
+ # means depends on the underlying implementation. It may do nothing if
26
+ # there are no initialization steps. Otherwise it will initiate the
27
+ # connection to the TNC and send the initial data needed to get it to
28
+ # enter KISS mode.
29
+ public
30
+ def connect(mode_init=nil, *args, **kwargs)
31
+ end
32
+
33
+ ##
34
+ # Closes the underlying connection and frees up any relevant resources.
35
+ # After the connection is closed read and write opperations will usually
36
+ # fail.
37
+ public
38
+ def close(*args, **kwargs)
39
+ end
40
+
41
+ ##
42
+ # Read and return the next datagram waiting in the buffer. Nil if there
43
+ # is no datagram waiting.
44
+ public
45
+ def read_datagram(*args, **kwargs)
46
+ end
47
+
48
+ ##
49
+ # This method sends any command to the underlying KISS device. All
50
+ # outgoing calls, methods with write_*, ultimately calls this method
51
+ # as the underlying call to KISS.
52
+ public
53
+ def write_generic_command(command, port, value, *args, **kwargs)
54
+ end
55
+
56
+ ##
57
+ # This command nibble should be set anytime a datagram is being sent for transmission.
58
+ public
59
+ def write_datagram(packet_data, port = 0, *args, **kwargs)
60
+ end
61
+
62
+ ##
63
+ # The amount of time to wait between keying the transmitter and beginning to send data (in 10 ms units).
64
+ public
65
+ def write_tx_delay(tx_delay, port = 0, *args, **kwargs)
66
+ end
67
+
68
+ ##
69
+ # The persistence parameter. Persistence=Data*256-1. Used for CSMA.
70
+ public
71
+ def write_persistence(persistence, port = 0, *args, **kwargs)
72
+ end
73
+
74
+ ##
75
+ # Slot time in 10 ms units. Used for CSMA.
76
+ public
77
+ def write_slot_time(slot_time, port = 0, *args, **kwargs)
78
+ end
79
+
80
+ ##
81
+ # The length of time to keep the transmitter keyed after sending the data (in 10 ms units).
82
+ public
83
+ def write_tx_tail(tx_tail, port = 0, *args, **kwargs)
84
+ end
85
+
86
+ ##
87
+ # True to turn on full_duplex, false to turn it off.
88
+ public
89
+ def write_full_duplex(full_duplex, port = 0, *args, **kwargs)
90
+ end
91
+
92
+ ##
93
+ # The meaning of this command is device dependent.
94
+ public
95
+ def write_set_hardware(value, port = 0, *args, **kwargs)
96
+ end
97
+
98
+ ##
99
+ # The meaning of this command is device dependent.
100
+ public
101
+ def write_exit_kiss_mode(*args, **kwargs)
102
+ end
8
103
  end
9
104
  end
@@ -5,7 +5,7 @@ require 'kiss/kiss'
5
5
 
6
6
  module Kiss
7
7
  class KissAbstract
8
- extend Kiss
8
+ include Kiss
9
9
  include Abstractify::Abstract
10
10
 
11
11
  abstract :write_interface, :read_interface, :connect, :close
@@ -57,138 +57,10 @@ module Kiss
57
57
  end
58
58
 
59
59
  private
60
- def self.extract_path(start, raw_frame)
61
- full_path = []
62
-
63
- (2...start).each do |i|
64
- path = identity_as_string(extract_callsign(raw_frame[i * 7..-1]))
65
- if path and path.length > 0
66
- if raw_frame[i * 7 + 6] & 0x80 != 0
67
- full_path << [path, '*'].join
68
- else
69
- full_path << path
70
- end
71
- end
72
- end
73
- return full_path
74
- end
75
-
76
- private
77
- def self.parse_identity_string(identity_string)
78
- # If we are parsing a spent token then first lets get rid of the astresick suffix.
79
- if identity_string[-1] == '*'
80
- identity_string = identity_string[0..-1]
81
- end
82
-
83
- if identity_string.include? '-'
84
- call_sign, ssid = identity_string.split('-')
85
- else
86
- call_sign = identity_string
87
- ssid = 0
88
- end
89
-
90
- return {:callsign => call_sign, :ssid => ssid.to_i}
91
- end
92
-
93
- private
94
- def self.identity_as_string(identity)
95
- if identity[:ssid] and identity[:ssid] > 0
96
- return [identity[:callsign], identity[:ssid].to_s].join('-')
97
- else
98
- return identity[:callsign]
99
- end
100
- end
101
-
102
- private
103
- def self.extract_callsign(raw_frame)
104
- callsign_as_array = raw_frame[0...6].map { |x| (x >> 1).chr }
105
- callsign = callsign_as_array.join.strip
106
- ssid = (raw_frame[6] >> 1) & 0x0f
107
- ssid = (ssid == nil or ssid == 0 ? nil : ssid)
108
- return {:callsign => callsign, :ssid => ssid}
109
- end
110
-
111
- private
112
- def self.encode_callsign(callsign)
113
- call_sign = callsign[:callsign]
114
-
115
- enc_ssid = (callsign[:ssid] << 1) | 0x60
116
-
117
- if call_sign.include? '*'
118
- call_sign.gsub!(/\*/, '')
119
- enc_ssid |= 0x80
120
- end
121
-
122
- while call_sign.length < 6
123
- call_sign = [call_sign, ' '].join
124
- end
125
-
126
- return call_sign.chars.map { |p| p.ord << 1 } + [enc_ssid]
127
- end
128
-
129
- private
130
- def self.encode_frame(frame)
131
- enc_frame = encode_callsign(parse_identity_string(frame[:destination].to_s)) + encode_callsign(parse_identity_string(frame[:source].to_s))
132
-
133
- frame[:path].each do |hop|
134
- enc_frame += encode_callsign(parse_identity_string(hop.to_s))
135
- end
136
-
137
- return enc_frame[0...-1] + [enc_frame[-1] | 0x01] + [SLOT_TIME] + [0xf0] + frame[:payload].chars.map { |c| c.ord }
138
- end
139
-
140
- private
141
- def self.decode_frame(raw_frame)
142
- frame_len = raw_frame.length
143
-
144
- if frame_len > 16
145
- (0...frame_len - 2).each do |raw_slice|
146
- # Is address field length correct?
147
- if raw_frame[raw_slice] & 0x01 != 0 and ((raw_slice + 1) % 7) == 0
148
- i = (raw_slice.to_f + 1.0) / 7.0
149
- # Less than 2 callsigns?
150
- if 1.0 < i and i < 11.0
151
- if raw_frame[raw_slice + 1] & 0x03 == 0x03 and [0xf0, 0xcf].include? raw_frame[raw_slice + 2]
152
- payload_as_array = raw_frame[raw_slice + 3..-1].map { |b| b.chr }
153
- payload = payload_as_array.join
154
- destination = identity_as_string(extract_callsign(raw_frame))
155
- source = identity_as_string(extract_callsign(raw_frame[7..-1]))
156
- path = extract_path(i.to_i, raw_frame)
157
- return {:source => source, :destination => destination, :path => path, :payload => payload}
158
- end
159
- end
160
- end
161
- end
162
- end
163
- return nil
164
- end
165
-
166
- private
167
- def self.valid_frame(raw_frame)
168
- frame_len = raw_frame.length
169
-
170
- if frame_len > 16
171
- (0...frame_len - 2).each do |raw_slice|
172
- # Is address field length correct?
173
- if raw_frame[raw_slice] & 0x01 != 0 and ((raw_slice + 1) % 7) == 0
174
- i = (raw_slice.to_f + 1.0) / 7.0
175
- # Less than 2 callsigns?
176
- if 1.0 < i and i < 11.0
177
- if raw_frame[raw_slice + 1] & 0x03 == 0x03 and [0xf0, 0xcf].include? raw_frame[raw_slice + 2]
178
- return true
179
- end
180
- end
181
- end
182
- end
183
- end
184
- return false
185
- end
186
-
187
- private
188
- def fill_buffer
60
+ def fill_buffer(*args, **kwargs)
189
61
  new_frames = []
190
62
  read_buffer = []
191
- read_data = read_interface
63
+ read_data = read_interface(*args, **kwargs)
192
64
  while read_data and read_data.length > 0
193
65
  split_data = [[]]
194
66
  read_data.each do |read_byte|
@@ -229,7 +101,7 @@ module Kiss
229
101
  end
230
102
  end
231
103
  # Get anymore data that is waiting
232
- read_data = read_interface
104
+ read_data = read_interface(*args, **kwargs)
233
105
  end
234
106
 
235
107
  new_frames.each do |new_frame|
@@ -245,7 +117,7 @@ module Kiss
245
117
  private
246
118
  def read_bytes(*args, **kwargs)
247
119
  if @frame_buffer.length == 0
248
- fill_buffer
120
+ fill_buffer(*args, **kwargs)
249
121
  end
250
122
 
251
123
  if @frame_buffer.length > 0
@@ -257,48 +129,99 @@ module Kiss
257
129
  end
258
130
  end
259
131
 
260
- private
261
- def write_bytes(frame_bytes, port=0, *args, **kwargs)
262
- kiss_packet = [FEND] + [KissAbstract.command_byte_combine(port, DATA_FRAME)] +
263
- KissAbstract.escape_special_codes(frame_bytes) + [FEND]
132
+ public
133
+ def write_generic_command(command, port, value, *args, **kwargs)
134
+ @lock.synchronize do
135
+ raise ArgumentError.new ("command can not be nil") if command.nil?
136
+ raise RangeError.new("command must be an integer between 0 (inclusive) and 15 (inclusive) instead we got #{command}") if command < 0 or command >= 16 or command&0x0f!=command
137
+ raise ArgumentError.new ("port can not be nil") if port.nil?
138
+ raise RangeError.new("port must be an integer between 0 (inclusive) and 15 (inclusive) instead we got #{port}") if port < 0 or port >= 16 or port&0x0f!=port
264
139
 
265
- write_interface(kiss_packet)
140
+ if value.nil?
141
+ write_interface([FEND] + [KissAbstract.command_byte_combine(port, command)] +[FEND], *args, **kwargs)
142
+ else
143
+ write_interface([FEND] + [KissAbstract.command_byte_combine(port, command)] + KissAbstract.escape_special_codes(value) + [FEND], *args, **kwargs)
144
+ end
145
+ end
266
146
  end
267
147
 
268
- protected
269
- def write_setting(command, value)
270
- write_interface([FEND] + [command] + KissAbstract.escape_special_codes(value) + [FEND])
148
+ public
149
+ def write_datagram(packet_data, port = 0, *args, **kwargs)
150
+ raise TypeError.new("packet_data can not be nil") if packet_data.nil?
151
+ raise TypeError.new("packet_data must be an array-like object that implements each, length, and []") if (not packet_data.respond_to?(:each)) or (not packet_data.respond_to?(:[])) or (not packet_data.respond_to?(:length))
152
+ raise RangeError.new("packet_data must have a length of 1 or more") if packet_data.length <= 0
153
+
154
+ write_generic_command(DATA_FRAME, port, packet_data, *args, **kwargs)
271
155
  end
272
156
 
273
157
  public
274
- def connect(mode_init=nil, *args, **kwargs)
158
+ def write_tx_delay(tx_delay, port = 0, *args, **kwargs)
159
+ raise TypeError.new("tx_delay can not be nil") if tx_delay.nil?
160
+ raise RangeError.new("tx_delay must be an integer value greater than or equal to 0 and less than 256") if tx_delay < 0 and tx_delay&0xff==tx_delay
161
+
162
+ write_generic_command(TX_DELAY, port, tx_delay, *args, **kwargs)
275
163
  end
276
164
 
277
165
  public
278
- def close(*args, **kwargs)
166
+ def write_persistence(persistence, port = 0, *args, **kwargs)
167
+ raise TypeError.new("persistence can not be nil") if persistence.nil?
168
+ raise RangeError.new("persistence must be an integer value greater than or equal to 0 and less than 256") if persistence < 0 and persistence&0xff==persistence
169
+
170
+ write_generic_command(PERSISTENCE, port, persistence, *args, **kwargs)
279
171
  end
280
172
 
281
173
  public
282
- def read(*args, **kwargs)
283
- @lock.synchronize do
284
- frame = self.read_bytes(*args, **kwargs)
285
- if frame and frame.length > 0
286
- return KissAbstract.decode_frame(frame)
287
- else
288
- return nil
289
- end
174
+ def write_slot_time(slot_time, port = 0, *args, **kwargs)
175
+ raise TypeError.new("slot_time can not be nil") if slot_time.nil?
176
+ raise RangeError.new("slot_time must be an integer value greater than or equal to 0 and less than 256") if slot_time < 0 and slot_time&0xff==slot_time
177
+
178
+ write_generic_command(SLOT_TIME, port, slot_time, *args, **kwargs)
179
+ end
180
+
181
+ public
182
+ def write_tx_tail(tx_tail, port = 0, *args, **kwargs)
183
+ raise TypeError.new("tx_tail can not be nil") if tx_tail.nil?
184
+ raise RangeError.new("tx_tail must be an integer value greater than or equal to 0 and less than 256") if tx_tail < 0 and tx_tail&0xff==tx_tail
185
+
186
+ write_generic_command(TX_TAIL, port, tx_tail, *args, **kwargs)
187
+ end
188
+
189
+ public
190
+ def write_full_duplex(full_duplex, port = 0, *args, **kwargs)
191
+ raise TypeError.new("full_duplex can not be nil") if full_duplex.nil?
192
+ raise TypeError.new("full_duplex must be either truthy or falsy") if full_duplex != (!!full_duplex)
193
+
194
+ if full_duplex
195
+ write_generic_command(FULL_DUPLEX, port, 1, *args, **kwargs)
196
+ else
197
+ write_generic_command(FULL_DUPLEX, port, 0, *args, **kwargs)
290
198
  end
291
199
  end
292
200
 
293
201
  public
294
- def write(frame, port=0, *args, **kwargs)
202
+ def write_set_hardware(value, port = 0, *args, **kwargs)
203
+ raise TypeError.new("value can not be nil") if value.nil?
204
+
205
+ write_generic_command(SET_HARDWARE, port, value, *args, **kwargs)
206
+ end
207
+
208
+ public
209
+ def write_exit_kiss_mode(*args, **kwargs)
210
+ write_generic_command(RETURN, 0, nil*args, **kwargs)
211
+ end
212
+
213
+ public
214
+ def connect(mode_init=nil, *args, **kwargs)
215
+ end
216
+
217
+ public
218
+ def close(*args, **kwargs)
219
+ end
220
+
221
+ public
222
+ def read_datagram(*args, **kwargs)
295
223
  @lock.synchronize do
296
- encoded_frame = KissAbstract.encode_frame(frame)
297
- if KissAbstract.valid_frame(encoded_frame)
298
- self.write_bytes(encoded_frame, *args, **kwargs)
299
- else
300
- raise IOError.new("frame was able to be encoded but was determined not to be valid")
301
- end
224
+ return self.read_bytes(*args, **kwargs)
302
225
  end
303
226
  end
304
227
  end
@@ -28,8 +28,8 @@ module Kiss
28
28
  end
29
29
 
30
30
  protected
31
- def read_interface
32
- read_data = @serial.read(@read_bytes)
31
+ def read_interface(*args, **kwargs)
32
+ read_data = @serial.read(@read_bytes, *args, **kwargs)
33
33
  if read_data
34
34
  return read_data.chars.map { |c| c.ord }
35
35
  else
@@ -38,18 +38,18 @@ module Kiss
38
38
  end
39
39
 
40
40
  protected
41
- def write_interface(data)
41
+ def write_interface(data, *args, **kwargs)
42
42
  unless data.is_a? String
43
43
  data = data.map { |b| b.chr }.join
44
44
  end
45
- @serial.write(data)
45
+ @serial.write(data, *args, **kwargs)
46
46
  end
47
47
 
48
48
  public
49
49
  def connect(mode_init=nil, *args, **kwargs)
50
50
  super
51
51
 
52
- @serial = SerialPort.new(@com_port, @baud, @byte_size, @stop_bits, @parity)
52
+ @serial = SerialPort.new(@com_port, @baud, @byte_size, @stop_bits, @parity, *args, **kwargs)
53
53
  @serial.read_timeout = SERIAL_READ_TIMEOUT
54
54
 
55
55
  if mode_init
@@ -58,14 +58,6 @@ module Kiss
58
58
  else
59
59
  @exit_kiss = false
60
60
  end
61
-
62
- # Previous verious defaulted to Xastir-friendly configs. Unfortunately
63
- # those don't work with Bluetooth TNCs, so we're reverting to None.
64
- if kwargs
65
- kwargs.each do |name, value|
66
- write_setting(name, value)
67
- end
68
- end
69
61
  end
70
62
 
71
63
  public
@@ -79,7 +71,7 @@ module Kiss
79
71
  if @serial == nil or @serial.closed?
80
72
  raise IOError.new('Attempting to close before the class has been started.')
81
73
  else
82
- @serial.close
74
+ @serial.close(*args, **kwargs)
83
75
  end
84
76
  end
85
77
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kiss-tnc
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.2
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeffrey Phillips Freeman
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-16 00:00:00.000000000 Z
11
+ date: 2023-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: abstractify
@@ -110,7 +110,7 @@ dependencies:
110
110
  version: '0.9'
111
111
  description: Ruby library for KISS communication with Terminal Node Controllers.
112
112
  email:
113
- - jeffrey.freeman@syncleus.com
113
+ - the@jeffreyfreeman.me
114
114
  executables: []
115
115
  extensions: []
116
116
  extra_rdoc_files: []
@@ -122,7 +122,6 @@ files:
122
122
  - Gemfile
123
123
  - LICENSE
124
124
  - README.md
125
- - README.rdoc
126
125
  - Rakefile
127
126
  - kiss-tnc.gemspec
128
127
  - lib/kiss.rb
@@ -151,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
151
150
  - !ruby/object:Gem::Version
152
151
  version: '0'
153
152
  requirements: []
154
- rubygems_version: 3.4.17
153
+ rubygems_version: 3.4.19
155
154
  signing_key:
156
155
  specification_version: 4
157
156
  summary: Library for KISS communication with TNCs.
data/README.rdoc DELETED
@@ -1,19 +0,0 @@
1
- = apex - DESCRIBE YOUR GEM
2
-
3
- Author:: Jeffrey Phillips Freeman (freemo@gmail.com)
4
- Copyright:: Copyright (c) 2016 Syncleus
5
-
6
-
7
- DESCRIBE YOUR GEM HERE
8
-
9
- == Links
10
-
11
- * {Source on Github}[https://github.com/Syncleus/kiss-tnc]
12
- * RDoc[LINK TO RDOC.INFO]
13
-
14
- == Install
15
-
16
- == Examples
17
-
18
- == Contributing
19
-