lxp-packet 0.3.0 → 0.4.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
2
  SHA256:
3
- metadata.gz: 64f2d92693be97e362ae4d3485fa4772bc813a9271d0fd6aa90d60dad103fe31
4
- data.tar.gz: c55207ae772cbe564f7891d634547209d8e022e545711dbe5813138cd53de722
3
+ metadata.gz: f690a3ff0e519ed9f0c68152117bfcd4ece48d2ffd67c32b83cd1b2bafc356b5
4
+ data.tar.gz: 4f35b9e46c92659e7bd5c366e3cc6bcbe9c4646e17278b6a8df3f7c3edb220a5
5
5
  SHA512:
6
- metadata.gz: 9ae5ae4c8df6d890bf75ec7280c598d2fb29c48977b7ffb256163b105566f73796b915c631388dea19c7b59aad2305720f7e0db7173bf0373d9bef0299d1b92f
7
- data.tar.gz: d9290a541c2489825f76a259b467779dfc5b20f44b156a1f645d98b3515e3ab6ff1764ba99e3aa8733af07db0cae3f68f4d31b7f56da48cc32cfabee349a5c89
6
+ metadata.gz: d19df5ab0f0cbe0568c4f7277a1ea84c071f30a3c882cabc16464b0a6a1b2850d27deeb191e74920d5f6da7fb052fde8b89768a535117a369c1724b75cfc4ef4
7
+ data.tar.gz: 418b00400f1c147d45dccb5f0d74660baccd9a5a5d88fb81cd0e25c86115550f1609f1482d9ea8fca9f4f9ec56d86b6bd5654138d7d2561d8a9595dc0fb4f466
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,2 @@
1
+ Metrics/LineLength:
2
+ Enabled: no
data/CHANGELOG.md CHANGED
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.4.0] - 2020-04-07
11
+
12
+ ### Added
13
+
14
+ - parsing of ReadHold packets with multiple registers/values
15
+ - beginnings of a test suite!
16
+
17
+
10
18
  ## [0.3.0] - 2020-04-02
11
19
 
12
20
  ### Fixed
data/README.md CHANGED
@@ -96,6 +96,22 @@ r = read_reply(sock, pkt)
96
96
  puts "Received: #{r.value}" # should be discharge cut-off value
97
97
  ```
98
98
 
99
+ Usually, `ReadHold` instances contain the details of just one register. However, it is possible they can contain multiple. Pressing "Read" on the LuxPower Web Portal provokes the inverter into sending out 5 packets that each contain multiple registers, for example. [TODO: work out how to request these packets ourselves]
100
+
101
+ To access these, you can use subscript notation to get a register directly, or call `#to_h` to get a hash of registers/values. For convenience this also works with single register packets, though obviously only one subscript will ever return data, and `to_h` will only have one key.
102
+
103
+ ```ruby
104
+ # assuming pkt is a parsed packet with multiple registers/values:
105
+ pkt[0] # => 35462 # value of register 0
106
+ pkt.to_h # { 0 => 35462, 1 => 1, ... }
107
+
108
+ # assuming pkt is a parsed packet with only register 21:
109
+ pkt[21] # => value of register 21
110
+ pkt[22] # => nil
111
+ pkt.to_h # { 21 => 62292 }
112
+ ```
113
+
114
+
99
115
  ### Writing
100
116
 
101
117
  Updating a value on the inverter.
@@ -119,7 +135,7 @@ r = read_reply(sock, pkt)
119
135
  puts "Received: #{r.value}" # should be new discharge cut-off value, 20
120
136
  ```
121
137
 
122
- ### Updating a multi-byte register
138
+ ### Updating a bitwise register
123
139
 
124
140
  The Lux has two registers that contain multiple settings. In `doc/LXP_REGISTERS.txt` you can see them at 21 and 110. They have two bytes.
125
141
 
@@ -127,7 +143,7 @@ This library combines them into a 16bit word, so that the constants in `LXP::Pac
127
143
 
128
144
  First you need to read the previous value, update it with a new bit, then write it back. This is really just a combination of the two above examples.
129
145
 
130
- This enables AC charge. You need to OR the bit with the previous value so as not to change other settings tored in register 21.
146
+ This example enables AC charge. You need to OR the bit with the previous value so as not to change other settings stored in register 21.
131
147
 
132
148
  It could be improved not to bother doing the write if it was already enabled.
133
149
 
@@ -9,9 +9,10 @@ Registers 21 and 110 are bitmasks; normally you fetch the previous
9
9
  settings, apply your changes, and set the new value back.
10
10
 
11
11
  0 MODEL
12
- 2 SERIAL_NUM
13
- 7 FW_CODE
14
- 12 TIME
12
+ 2-8 SERIAL_NUM
13
+ 7 FW_CODE ?
14
+ 9-10 ?
15
+ 12-14 TIME
15
16
  15 COM_ADDR
16
17
  16 LANGUAGE
17
18
  20 PV_INPUT_MODE
@@ -26,7 +26,6 @@ class LXP
26
26
 
27
27
  self.protocol = 1
28
28
 
29
- # length after first 6 bytes maybe?
30
29
  self.packet_length = 32
31
30
 
32
31
  @header[6] = 1 # unsure, always seems to be 1
@@ -89,6 +88,10 @@ class LXP
89
88
  @header[7] = tcp_function & 0xff
90
89
  end
91
90
 
91
+ def datalog_serial
92
+ @header[8, 10].pack('C*')
93
+ end
94
+
92
95
  # Passed as a string
93
96
  def datalog_serial=(datalog_serial)
94
97
  @header[8, 10] = datalog_serial.bytes
@@ -111,6 +114,10 @@ class LXP
111
114
  @data[1] = device_function
112
115
  end
113
116
 
117
+ def inverter_serial
118
+ @data[2, 10].pack('C*')
119
+ end
120
+
114
121
  # Passed as a string
115
122
  def inverter_serial=(inverter_serial)
116
123
  @data[2, 10] = inverter_serial.bytes
@@ -125,12 +132,6 @@ class LXP
125
132
  @data[13] = (register >> 8) & 0xff
126
133
  end
127
134
 
128
- def value_length_byte?
129
- @value_length_byte ||=
130
- protocol == 2 &&
131
- device_function != DeviceFunctions::WRITE_SINGLE
132
- end
133
-
134
135
  def value_length
135
136
  if value_length_byte?
136
137
  @data[14]
@@ -142,13 +143,11 @@ class LXP
142
143
  # protocol 1 has value at 14 and 15
143
144
  # protocol 2 has length at 14, then that many bytes of values
144
145
  #
145
- # So this can return an int or an array.
146
- #
147
- def value
146
+ def values
148
147
  if value_length_byte?
149
148
  @data[15, value_length]
150
149
  else
151
- @data[14] | @data[15] << 8
150
+ @data[14, 2] # | @data[15] << 8
152
151
  end
153
152
  end
154
153
 
@@ -171,6 +170,12 @@ class LXP
171
170
 
172
171
  private
173
172
 
173
+ def value_length_byte?
174
+ @value_length_byte ||=
175
+ protocol == 2 &&
176
+ device_function != DeviceFunctions::WRITE_SINGLE
177
+ end
178
+
174
179
  def crc16_modbus(arr)
175
180
  arr.length.times.inject(0xffff) do |r, n|
176
181
  r ^= arr[n]
@@ -15,10 +15,6 @@ class LXP
15
15
  #
16
16
  # They have no data and no checksum, so there's really not a lot here.
17
17
  #
18
- # Ideally these could be instantiated via .parse, but they only seem to
19
- # have one byte for the length, and .parse expects two. There's nothing
20
- # to parse anyway so never mind.
21
- #
22
18
  class Heartbeat < Base
23
19
  def initialize
24
20
  super
@@ -18,18 +18,36 @@ class LXP
18
18
  self.value = 1
19
19
  end
20
20
 
21
- # ReadHold packets should always (I think) have two byte values.
21
+ # Return the first value in a ReadHold packet. This is normally used
22
+ # when the packet only has one value.
22
23
  #
23
- # Raise if not, as that is not expected?
24
+ # #values returns an Array. This converts it to an int.
24
25
  #
25
- # Base#value will return an int for protocol 1, or an Array
26
- # for protocol 2. If we can, convert that Array to an int.
26
+ def value(offset = 0)
27
+ Utils.int(values[offset, 2])
28
+ end
29
+
30
+ # Subscript notation is used when the ReadHold packet has multiple
31
+ # registers in it. This is indicated by value_length > 2.
27
32
  #
28
- def value
29
- raise 'value_length not 2?' unless value_length == 2
33
+ # In this case, #register tells us the first register in the values, then
34
+ # each 2 bytes are subsequent registers.
35
+ #
36
+ def [](reg_num)
37
+ offset = (reg_num - register) * 2
38
+
39
+ return if offset.negative? || offset > data_length
40
+
41
+ value(offset)
42
+ end
43
+
44
+ # Return a Hash of all register->values in the ReadHold packet.
45
+ def to_h
46
+ r = register
30
47
 
31
- r = super
32
- r.is_a?(Array) ? Utils.int(r, 2) : r
48
+ values.each_slice(2).each_with_index.map do |v, idx|
49
+ [r + idx, Utils.int(v)]
50
+ end.to_h
33
51
  end
34
52
  end
35
53
  end
@@ -27,14 +27,10 @@ class LXP
27
27
  #
28
28
  # Raise if not, as that is not expected?
29
29
  #
30
- # Base#value will return an int for protocol 1, or an Array
31
- # for protocol 2. If we can, convert that Array to an int.
32
- #
33
30
  def value
34
31
  raise 'value_length not 2?' unless value_length == 2
35
32
 
36
- r = super
37
- r.is_a?(Array) ? Utils.int(r, 2) : r
33
+ Utils.int(values[0, 2])
38
34
  end
39
35
  end
40
36
  end
data/lib/lxp/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class LXP
4
- VERSION = '0.3.0'
4
+ VERSION = '0.4.0'
5
5
  end
data/lxp-packet.gemspec CHANGED
@@ -21,4 +21,5 @@ Gem::Specification.new do |s|
21
21
  s.require_paths = ['lib']
22
22
 
23
23
  s.add_development_dependency 'bundler', '~> 2.0'
24
+ s.add_development_dependency 'rspec'
24
25
  end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe LXP::Packet::Parser do
4
+ let(:parser) { LXP::Packet::Parser.new(input.pack('C*')) }
5
+ let(:packet) { parser.parse }
6
+
7
+ subject { packet }
8
+
9
+ context 'ReadHold multi data (registers 0-22)' do
10
+ let(:input) { [161, 26, 2, 0, 77, 0, 1, 194, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 63, 0, 1, 3, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 0, 0, 46, 134, 138, 1, 0, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 66, 65, 65, 65, 1, 10, 10, 1, 0, 0, 20, 4, 7, 16, 14, 49, 1, 0, 1, 0, 0, 0, 0, 0, 4, 0, 0, 0, 84, 243, 176, 4, 40, 224] }
11
+
12
+ it { is_expected.to be_a LXP::Packet::ReadHold }
13
+
14
+ it 'has the correct attributes' do
15
+ expect(packet).to have_attributes register: 0,
16
+ values: [134, 138, 1, 0, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 66, 65, 65, 65, 1, 10, 10, 1, 0, 0, 20, 4, 7, 16, 14, 49, 1, 0, 1, 0, 0, 0, 0, 0, 4, 0, 0, 0, 84, 243, 176, 4],
17
+ to_h: { 0 => 35_462, 1 => 1, 2 => 22_616, 3 => 22_616, 4 => 22_616, 5 => 22_616, 6 => 22_616, 7 => 16_706, 8 => 16_705, 9 => 2561, 10 => 266, 11 => 0, 12 => 1044, 13 => 4103, 14 => 12_558, 15 => 1, 16 => 1, 17 => 0, 18 => 0, 19 => 4, 20 => 0, 21 => 62_292, 22 => 1200 },
18
+ protocol: 2,
19
+ packet_length: 77, data_length: 63,
20
+ tcp_function: LXP::Packet::TcpFunctions::TRANSLATED_DATA,
21
+ device_function: LXP::Packet::DeviceFunctions::READ_HOLD,
22
+ inverter_serial: 'XXXXXXXXXX',
23
+ datalog_serial: 'cccccccccc',
24
+ bytes: input
25
+ expect(packet[22]).to eq 1200
26
+
27
+ # test out of bounds subscripts return nil
28
+ expect(packet[23]).to be_nil
29
+ end
30
+ end
31
+
32
+ context 'ReadHold multi data (registers 80-113)' do
33
+ let(:input) { [161, 26, 2, 0, 99, 0, 1, 194, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 85, 0, 1, 3, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 80, 0, 68, 0, 0, 0, 0, 100, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0, 50, 0, 111, 9, 252, 8, 20, 0, 5, 0, 0, 0, 0, 0, 0, 0, 48, 2, 144, 1, 66, 0, 66, 0, 0, 0, 0, 0, 10, 0, 56, 255, 38, 2, 0, 0, 144, 1, 2, 0, 0, 0, 0, 0, 0, 0, 193, 242] }
34
+
35
+ it { is_expected.to be_a LXP::Packet::ReadHold }
36
+
37
+ it 'has the correct attributes' do
38
+ expect(packet).to have_attributes register: 80,
39
+ values: [0, 0, 0, 0, 100, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0, 50, 0, 111, 9, 252, 8, 20, 0, 5, 0, 0, 0, 0, 0, 0, 0, 48, 2, 144, 1, 66, 0, 66, 0, 0, 0, 0, 0, 10, 0, 56, 255, 38, 2, 0, 0, 144, 1, 2, 0, 0, 0, 0, 0, 0, 0],
40
+ to_h: { 80 => 0, 81 => 0, 82 => 100, 83 => 20, 84 => 0, 85 => 0, 86 => 0, 87 => 0, 88 => 0, 89 => 0, 90 => 230, 91 => 50, 92 => 2415, 93 => 2300, 94 => 20, 95 => 5, 96 => 0, 97 => 0, 98 => 0, 99 => 560, 100 => 400, 101 => 66, 102 => 66, 103 => 0, 104 => 0, 105 => 10, 106 => 65_336, 107 => 550, 108 => 0, 109 => 400, 110 => 2, 111 => 0, 112 => 0, 113 => 0 },
41
+ protocol: 2,
42
+ packet_length: 99, data_length: 85,
43
+ tcp_function: LXP::Packet::TcpFunctions::TRANSLATED_DATA,
44
+ device_function: LXP::Packet::DeviceFunctions::READ_HOLD,
45
+ inverter_serial: 'XXXXXXXXXX',
46
+ datalog_serial: 'cccccccccc',
47
+ bytes: input
48
+ expect(packet[80]).to eq 0
49
+ expect(packet[94]).to eq 20
50
+ expect(packet[113]).to eq 0
51
+
52
+ # test out of bounds subscripts return nil
53
+ expect(packet[114]).to be_nil
54
+ expect(packet[79]).to be_nil
55
+ end
56
+ end
57
+
58
+ context 'ReadInput1 data' do
59
+ let(:input) { [161, 26, 2, 0, 111, 0, 1, 194, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 97, 0, 1, 4, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 0, 0, 80, 16, 0, 0, 0, 0, 0, 0, 0, 241, 1, 95, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 121, 2, 172, 9, 1, 0, 0, 0, 146, 19, 57, 2, 0, 0, 227, 0, 232, 3, 172, 9, 0, 11, 80, 112, 146, 19, 0, 0, 0, 0, 0, 0, 0, 0, 221, 0, 0, 0, 0, 0, 42, 0, 73, 0, 86, 0, 52, 0, 0, 0, 36, 0, 2, 0, 172, 14, 181, 11, 127, 131] }
60
+
61
+ it { is_expected.to be_a LXP::Packet::ReadInput1 }
62
+
63
+ it 'has the correct attributes' do
64
+ expect(packet).to have_attributes register: 0,
65
+ values: [16, 0, 0, 0, 0, 0, 0, 0, 241, 1, 95, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 121, 2, 172, 9, 1, 0, 0, 0, 146, 19, 57, 2, 0, 0, 227, 0, 232, 3, 172, 9, 0, 11, 80, 112, 146, 19, 0, 0, 0, 0, 0, 0, 0, 0, 221, 0, 0, 0, 0, 0, 42, 0, 73, 0, 86, 0, 52, 0, 0, 0, 36, 0, 2, 0, 172, 14, 181, 11],
66
+ protocol: 2,
67
+ packet_length: 111, data_length: 97,
68
+ tcp_function: LXP::Packet::TcpFunctions::TRANSLATED_DATA,
69
+ device_function: LXP::Packet::DeviceFunctions::READ_INPUT,
70
+ inverter_serial: 'XXXXXXXXXX',
71
+ datalog_serial: 'cccccccccc',
72
+ bytes: input
73
+ end
74
+
75
+ describe '#to_h' do
76
+ subject { packet.to_h }
77
+ it { is_expected.to eq status: 16, v_bat: 49.7, soc: 95, p_pv: 0, p_charge: 0, p_discharge: 633, v_acr: 247.6, f_ac: 50.1, p_inv: 569, p_rec: 0, v_eps: 247.6, f_eps: 50.1, p_to_grid: 0, p_to_user: 0, e_pv_day: 22.1, e_inv_day: 4.2, e_rec_day: 7.3, e_chg_day: 8.6, e_dischg_day: 5.2, e_eps_day: 0.0, e_to_grid_day: 3.6, e_to_user_day: 0.2, v_bus_1: 375.6, v_bus_2: 299.7 }
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe LXP::Packet::ReadHold do
4
+ let(:packet) { LXP::Packet::ReadHold.new }
5
+
6
+ before do
7
+ packet.inverter_serial = '1234567890'
8
+ packet.datalog_serial = '0987654321'
9
+ packet.register = 21
10
+ end
11
+
12
+ it 'has the correct attributes' do
13
+ expect(packet).to have_attributes register: 21, values: [1, 0], value: 1,
14
+ to_h: { 21 => 1 },
15
+ protocol: 1,
16
+ packet_length: 32, data_length: 18,
17
+ tcp_function: LXP::Packet::TcpFunctions::TRANSLATED_DATA,
18
+ device_function: LXP::Packet::DeviceFunctions::READ_HOLD,
19
+ inverter_serial: '1234567890',
20
+ datalog_serial: '0987654321',
21
+ bytes: [161, 26, 1, 0, 32, 0, 1, 194, 48, 57, 56, 55, 54, 53, 52, 51, 50, 49, 18, 0, 0, 3, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 21, 0, 1, 0, 241, 72]
22
+ expect(packet[21]).to eq 1
23
+ end
24
+
25
+ it 'creates the correct binary' do
26
+ expect(packet.to_bin).to eq [161, 26, 1, 0, 32, 0, 1, 194, 48, 57, 56, 55, 54, 53, 52, 51, 50, 49, 18, 0, 0, 3, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 21, 0, 1, 0, 241, 72].pack('C*')
27
+ end
28
+
29
+ it 'works with protocol 2' do
30
+ packet.protocol = 2
31
+ expect(packet).to have_attributes protocol: 2,
32
+ bytes: [161, 26, 2, 0, 32, 0, 1, 194, 48, 57, 56, 55, 54, 53, 52, 51, 50, 49, 18, 0, 0, 3, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 21, 0, 1, 0, 241, 72]
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lxp/packet'
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe LXP::Packet::WriteSingle do
4
+ let(:packet) { LXP::Packet::WriteSingle.new }
5
+
6
+ before do
7
+ packet.inverter_serial = '1234567890'
8
+ packet.datalog_serial = '0987654321'
9
+ packet.register = 21
10
+ packet.value = 8000
11
+ end
12
+
13
+ it 'has the correct attributes' do
14
+ expect(packet).to have_attributes register: 21, values: [64, 31], value: 8000,
15
+ protocol: 1,
16
+ packet_length: 32, data_length: 18,
17
+ tcp_function: LXP::Packet::TcpFunctions::TRANSLATED_DATA,
18
+ device_function: LXP::Packet::DeviceFunctions::WRITE_SINGLE,
19
+ inverter_serial: '1234567890',
20
+ datalog_serial: '0987654321',
21
+ bytes: [161, 26, 1, 0, 32, 0, 1, 194, 48, 57, 56, 55, 54, 53, 52, 51, 50, 49, 18, 0, 0, 6, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 21, 0, 64, 31, 69, 211]
22
+ end
23
+
24
+ it 'creates the correct binary' do
25
+ expect(packet.to_bin).to eq [161, 26, 1, 0, 32, 0, 1, 194, 48, 57, 56, 55, 54, 53, 52, 51, 50, 49, 18, 0, 0, 6, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 21, 0, 64, 31, 69, 211].pack('C*')
26
+ end
27
+
28
+ it 'works with protocol 2' do
29
+ packet.protocol = 2
30
+ expect(packet).to have_attributes protocol: 2,
31
+ bytes: [161, 26, 2, 0, 32, 0, 1, 194, 48, 57, 56, 55, 54, 53, 52, 51, 50, 49, 18, 0, 0, 6, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 21, 0, 64, 31, 69, 211]
32
+ end
33
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lxp-packet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Elsworth
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-02 00:00:00.000000000 Z
11
+ date: 2020-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  description:
28
42
  email:
29
43
  - chris@cae.me.uk
@@ -32,6 +46,8 @@ extensions: []
32
46
  extra_rdoc_files: []
33
47
  files:
34
48
  - ".gitignore"
49
+ - ".rspec"
50
+ - ".rubocop.yml"
35
51
  - CHANGELOG.md
36
52
  - Gemfile
37
53
  - LICENSE.txt
@@ -55,6 +71,10 @@ files:
55
71
  - lib/lxp/utils.rb
56
72
  - lib/lxp/version.rb
57
73
  - lxp-packet.gemspec
74
+ - spec/parser_spec.rb
75
+ - spec/read_hold_spec.rb
76
+ - spec/spec_helper.rb
77
+ - spec/write_single_spec.rb
58
78
  homepage: https://github.com/celsworth/lxp-packet
59
79
  licenses:
60
80
  - MIT