Class: LXP::Packet::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/lxp/packet/base.rb

Direct Known Subclasses

Heartbeat, ReadHold, ReadInput, WriteSingle

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeBase

Returns a new instance of Base.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/lxp/packet/base.rb', line 18

def initialize
  @header ||= [0] * 20
  @data ||= [0] * 16
  @chksum ||= [0, 0]

  # prefix
  @header[0] = 161
  @header[1] = 26

  self.protocol = 1

  self.packet_length = 32

  @header[6] = 1 # unsure, always seems to be 1
end

Instance Attribute Details

#chksumObject

2 bytes



16
17
18
# File 'lib/lxp/packet/base.rb', line 16

def chksum
  @chksum
end

#dataObject

usually 16 bytes?



13
14
15
# File 'lib/lxp/packet/base.rb', line 13

def data
  @data
end

#headerObject

20 bytes



10
11
12
# File 'lib/lxp/packet/base.rb', line 10

def header
  @header
end

Class Method Details

.parse(ascii) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/lxp/packet/base.rb', line 43

def self.parse(ascii)
  # array of integers
  bdata = ascii.unpack('C*')

  raise 'invalid packet' if bdata[0] != 161 || bdata[1] != 26

  i = new

  # header is always 20 bytes
  i.header[0, 20] = bdata[0, 20]

  # data can vary from 17 bytes upwards
  i.data = bdata[20, i.data_length - 2] # -2, don't copy checksum
  raise 'bad data length' unless i.data.length != i.data_length

  # calculate checksum and compare to input
  i.update_checksum
  raise 'invalid checksum' if i.chksum != bdata[-2..-1]

  i
end

Instance Method Details

#bytesObject



34
35
36
37
# File 'lib/lxp/packet/base.rb', line 34

def bytes
  update_checksum
  header + data + chksum
end

#data_lengthObject



100
101
102
# File 'lib/lxp/packet/base.rb', line 100

def data_length
  @header[18] | @header[19] << 8
end

#data_length=(data_length) ⇒ Object



104
105
106
107
# File 'lib/lxp/packet/base.rb', line 104

def data_length=(data_length)
  @header[18] = data_length & 0xff
  @header[19] = (data_length >> 8) & 0xff
end

#datalog_serialObject



91
92
93
# File 'lib/lxp/packet/base.rb', line 91

def datalog_serial
  @header[8, 10].pack('C*')
end

#datalog_serial=(datalog_serial) ⇒ Object

Passed as a string



96
97
98
# File 'lib/lxp/packet/base.rb', line 96

def datalog_serial=(datalog_serial)
  @header[8, 10] = datalog_serial.bytes
end

#device_functionObject



109
110
111
# File 'lib/lxp/packet/base.rb', line 109

def device_function
  @data[1]
end

#device_function=(device_function) ⇒ Object



113
114
115
# File 'lib/lxp/packet/base.rb', line 113

def device_function=(device_function)
  @data[1] = device_function
end

#inverter_serialObject



117
118
119
# File 'lib/lxp/packet/base.rb', line 117

def inverter_serial
  @data[2, 10].pack('C*')
end

#inverter_serial=(inverter_serial) ⇒ Object

Passed as a string



122
123
124
# File 'lib/lxp/packet/base.rb', line 122

def inverter_serial=(inverter_serial)
  @data[2, 10] = inverter_serial.bytes
end

#packet_lengthObject



74
75
76
# File 'lib/lxp/packet/base.rb', line 74

def packet_length
  @header[4] | @header[5] << 8
end

#packet_length=(packet_length) ⇒ Object



78
79
80
81
# File 'lib/lxp/packet/base.rb', line 78

def packet_length=(packet_length)
  @header[4] = packet_length & 0xff
  @header[5] = (packet_length >> 8) & 0xff
end

#protocolObject



65
66
67
# File 'lib/lxp/packet/base.rb', line 65

def protocol
  @header[2] | @header[3] << 8
end

#protocol=(protocol) ⇒ Object



69
70
71
72
# File 'lib/lxp/packet/base.rb', line 69

def protocol=(protocol)
  @header[2] = protocol & 0xff
  @header[3] = (protocol >> 8) & 0xff
end

#registerObject



126
127
128
# File 'lib/lxp/packet/base.rb', line 126

def register
  @data[12] | @data[13] << 8
end

#register=(register) ⇒ Object



130
131
132
133
# File 'lib/lxp/packet/base.rb', line 130

def register=(register)
  @data[12] = register & 0xff
  @data[13] = (register >> 8) & 0xff
end

#tcp_functionObject



83
84
85
# File 'lib/lxp/packet/base.rb', line 83

def tcp_function
  @header[7]
end

#tcp_function=(tcp_function) ⇒ Object



87
88
89
# File 'lib/lxp/packet/base.rb', line 87

def tcp_function=(tcp_function)
  @header[7] = tcp_function & 0xff
end

#to_binObject



39
40
41
# File 'lib/lxp/packet/base.rb', line 39

def to_bin
  bytes.pack('C*')
end

#update_checksumObject



165
166
167
168
169
# File 'lib/lxp/packet/base.rb', line 165

def update_checksum
  chksum = crc16_modbus(data)
  @chksum[0] = chksum & 0xff
  @chksum[1] = (chksum >> 8) & 0xff
end

#value=(value) ⇒ Object

this only makes sense for protocol 1 at the moment. for 2 we’d need to append to an array, and not sure that is even used (sending an array of values to inverter) (maybe with W_MULTI?)



158
159
160
161
162
163
# File 'lib/lxp/packet/base.rb', line 158

def value=(value)
  raise 'cannot set value with protocol 2 yet' if protocol == 2

  @data[14] = value & 0xff
  @data[15] = (value >> 8) & 0xff
end

#value_lengthObject



135
136
137
138
139
140
141
# File 'lib/lxp/packet/base.rb', line 135

def value_length
  if value_length_byte?
    @data[14]
  else
    2
  end
end

#valuesObject

protocol 1 has value at 14 and 15 protocol 2 has length at 14, then that many bytes of values



146
147
148
149
150
151
152
# File 'lib/lxp/packet/base.rb', line 146

def values
  if value_length_byte?
    @data[15, value_length]
  else
    @data[14, 2] # | @data[15] << 8
  end
end