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 +4 -4
- data/.rspec +1 -0
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +8 -0
- data/README.md +18 -2
- data/doc/LXP_REGISTERS.txt +4 -3
- data/lib/lxp/packet/base.rb +16 -11
- data/lib/lxp/packet/heartbeat.rb +0 -4
- data/lib/lxp/packet/read_hold.rb +26 -8
- data/lib/lxp/packet/write_single.rb +1 -5
- data/lib/lxp/version.rb +1 -1
- data/lxp-packet.gemspec +1 -0
- data/spec/parser_spec.rb +80 -0
- data/spec/read_hold_spec.rb +34 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/write_single_spec.rb +33 -0
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f690a3ff0e519ed9f0c68152117bfcd4ece48d2ffd67c32b83cd1b2bafc356b5
|
4
|
+
data.tar.gz: 4f35b9e46c92659e7bd5c366e3cc6bcbe9c4646e17278b6a8df3f7c3edb220a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d19df5ab0f0cbe0568c4f7277a1ea84c071f30a3c882cabc16464b0a6a1b2850d27deeb191e74920d5f6da7fb052fde8b89768a535117a369c1724b75cfc4ef4
|
7
|
+
data.tar.gz: 418b00400f1c147d45dccb5f0d74660baccd9a5a5d88fb81cd0e25c86115550f1609f1482d9ea8fca9f4f9ec56d86b6bd5654138d7d2561d8a9595dc0fb4f466
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/.rubocop.yml
ADDED
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
|
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
|
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
|
|
data/doc/LXP_REGISTERS.txt
CHANGED
@@ -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
|
+
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
|
data/lib/lxp/packet/base.rb
CHANGED
@@ -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
|
-
|
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]
|
data/lib/lxp/packet/heartbeat.rb
CHANGED
@@ -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
|
data/lib/lxp/packet/read_hold.rb
CHANGED
@@ -18,18 +18,36 @@ class LXP
|
|
18
18
|
self.value = 1
|
19
19
|
end
|
20
20
|
|
21
|
-
#
|
21
|
+
# Return the first value in a ReadHold packet. This is normally used
|
22
|
+
# when the packet only has one value.
|
22
23
|
#
|
23
|
-
#
|
24
|
+
# #values returns an Array. This converts it to an int.
|
24
25
|
#
|
25
|
-
|
26
|
-
|
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
|
-
|
29
|
-
|
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
|
-
|
32
|
-
|
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
|
-
|
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
data/lxp-packet.gemspec
CHANGED
data/spec/parser_spec.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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.
|
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-
|
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
|