somfy_sdn 2.1.5 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/exe/somfy_sdn +69 -0
- data/lib/sdn/cli/mqtt/group.rb +12 -10
- data/lib/sdn/cli/mqtt/motor.rb +19 -14
- data/lib/sdn/cli/mqtt/p_queue.rb +18 -0
- data/lib/sdn/cli/mqtt/read.rb +125 -126
- data/lib/sdn/cli/mqtt/subscriptions.rb +186 -140
- data/lib/sdn/cli/mqtt/write.rb +39 -34
- data/lib/sdn/cli/mqtt.rb +84 -53
- data/lib/sdn/cli/provisioner.rb +56 -33
- data/lib/sdn/cli/simulator.rb +99 -65
- data/lib/sdn/client.rb +38 -24
- data/lib/sdn/message/control.rb +60 -30
- data/lib/sdn/message/get.rb +6 -2
- data/lib/sdn/message/helpers.rb +23 -22
- data/lib/sdn/message/ilt2/get.rb +6 -3
- data/lib/sdn/message/ilt2/master_control.rb +10 -7
- data/lib/sdn/message/ilt2/post.rb +7 -5
- data/lib/sdn/message/ilt2/set.rb +28 -19
- data/lib/sdn/message/post.rb +3 -5
- data/lib/sdn/message/set.rb +48 -22
- data/lib/sdn/message.rb +50 -34
- data/lib/sdn/version.rb +3 -1
- data/lib/sdn.rb +18 -12
- data/lib/somfy_sdn.rb +3 -1
- metadata +43 -13
- data/bin/somfy_sdn +0 -60
data/lib/sdn/cli/simulator.rb
CHANGED
@@ -1,8 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SDN
|
2
4
|
module CLI
|
3
5
|
class Simulator
|
4
6
|
class MockMotor
|
5
|
-
attr_accessor :address,
|
7
|
+
attr_accessor :address,
|
8
|
+
:node_type,
|
9
|
+
:label,
|
10
|
+
:ips,
|
11
|
+
:position_pulses,
|
12
|
+
:up_limit,
|
13
|
+
:down_limit,
|
14
|
+
:groups,
|
15
|
+
:network_lock_priority,
|
16
|
+
:lock_priority,
|
17
|
+
:ir_channels
|
18
|
+
|
19
|
+
ALLOWED_MOVE_TYPES = %i[up_limit
|
20
|
+
down_limit
|
21
|
+
ip
|
22
|
+
position_pulses
|
23
|
+
position_percent].freeze
|
6
24
|
|
7
25
|
def initialize(client)
|
8
26
|
@client = client
|
@@ -20,56 +38,67 @@ module SDN
|
|
20
38
|
@client.receive do |message|
|
21
39
|
SDN.logger.info "Received #{message.inspect}"
|
22
40
|
next unless message.is_a?(Message::ILT2::MasterControl) ||
|
23
|
-
|
24
|
-
|
25
|
-
|
41
|
+
message.dest == address ||
|
42
|
+
message.dest == BROADCAST_ADDRESS
|
43
|
+
|
26
44
|
case message
|
27
45
|
when Message::GetGroupAddr
|
28
|
-
next nack(message) unless (1..16).
|
46
|
+
next nack(message) unless (1..16).cover?(message.group_index)
|
47
|
+
|
29
48
|
respond(message.src, Message::PostGroupAddr.new(message.group_index, groups[message.group_index - 1]))
|
30
49
|
when Message::GetMotorIP
|
31
|
-
next nack(message) unless (1..16).
|
32
|
-
|
50
|
+
next nack(message) unless (1..16).cover?(message.ip)
|
51
|
+
|
52
|
+
respond(message.src,
|
53
|
+
Message::PostMotorIP.new(message.ip, ips[message.ip - 1], to_percent(ips[message.ip - 1])))
|
33
54
|
when Message::GetMotorLimits
|
34
55
|
respond(message.src, Message::PostMotorLimits.new(up_limit, down_limit))
|
35
56
|
when Message::GetMotorPosition
|
36
57
|
respond(message.src, Message::PostMotorPosition.new(
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
when Message::GetNodeAddr
|
42
|
-
when Message::GetNodeLabel
|
43
|
-
when Message::ILT2::GetIRConfig
|
44
|
-
when Message::ILT2::GetLockStatus
|
45
|
-
|
46
|
-
when Message::ILT2::
|
47
|
-
|
48
|
-
when Message::ILT2::
|
49
|
-
|
58
|
+
position_pulses,
|
59
|
+
to_percent(position_pulses),
|
60
|
+
ips.index(position_pulses)&.+(1)
|
61
|
+
))
|
62
|
+
when Message::GetNodeAddr then respond(message.src, Message::PostNodeAddr.new)
|
63
|
+
when Message::GetNodeLabel then respond(message.src, Message::PostNodeLabel.new(label))
|
64
|
+
when Message::ILT2::GetIRConfig then respond(message.src, Message::ILT2::PostIRConfig.new(ir_channels))
|
65
|
+
when Message::ILT2::GetLockStatus then respond(message.src,
|
66
|
+
Message::ILT2::PostLockStatus.new(lock_priority))
|
67
|
+
when Message::ILT2::GetMotorIP
|
68
|
+
respond(message.src, Message::ILT2::PostMotorIP.new(message.ip, ips[message.ip - 1]))
|
69
|
+
when Message::ILT2::GetMotorPosition
|
70
|
+
respond(message.src, Message::ILT2::PostMotorPosition.new(position_pulses, to_percent(position_pulses)))
|
71
|
+
when Message::ILT2::GetMotorSettings
|
72
|
+
respond(message.src, Message::ILT2::PostMotorSettings.new(down_limit))
|
73
|
+
when Message::ILT2::SetIRConfig then self.ir_channels = message.channels
|
74
|
+
when Message::ILT2::SetLockStatus then self.lock_priority = message.priority
|
50
75
|
when Message::ILT2::SetMotorIP
|
51
|
-
next nack(message) unless (1..16).
|
76
|
+
next nack(message) unless (1..16).cover?(message.ip)
|
77
|
+
|
52
78
|
ips[message.ip - 1] = message.value
|
53
79
|
ack(message)
|
54
80
|
when Message::ILT2::SetMotorPosition
|
55
81
|
next nack(message) unless down_limit
|
56
82
|
|
57
83
|
self.position_pulses = case message.target_type
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
84
|
+
when :up_limit then 0
|
85
|
+
when :down_limit then down_limit
|
86
|
+
when :ip
|
87
|
+
next nack(message) unless (1..16).cover?(message.target)
|
88
|
+
next nack(message) unless ips[message.target]
|
89
|
+
|
90
|
+
ips[message.target]
|
91
|
+
when :position_pulses
|
92
|
+
next nack(message) if message.target - 1 > down_limit
|
93
|
+
|
94
|
+
message.target - 1
|
95
|
+
when :jog_up_pulses then [0, position_pulses - message.target].max
|
96
|
+
when :jog_down_pulses then [down_limit, position_pulses + message.target].min
|
97
|
+
when :position_percent
|
98
|
+
next nack(message) if message.target > 100
|
99
|
+
|
100
|
+
to_pulses(message.target.to_f)
|
101
|
+
end
|
73
102
|
ack(message)
|
74
103
|
when Message::ILT2::SetMotorSettings
|
75
104
|
if message.down_limit != 0
|
@@ -78,29 +107,33 @@ module SDN
|
|
78
107
|
end
|
79
108
|
when Message::MoveTo
|
80
109
|
next nack(message) unless down_limit
|
81
|
-
next nack(message) unless
|
82
|
-
|
110
|
+
next nack(message) unless ALLOWED_MOVE_TYPES.include?(message.target_type)
|
111
|
+
|
83
112
|
self.position_pulses = case message.target_type
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
113
|
+
when :up_limit then 0
|
114
|
+
when :down_limit then down_limit
|
115
|
+
when :ip
|
116
|
+
next nack(message) unless (1..16).cover?(message.target)
|
117
|
+
next nack(message) unless ips[message.target - 1]
|
118
|
+
|
119
|
+
ips[message.target - 1]
|
120
|
+
when :position_pulses
|
121
|
+
next nack(message) if message.target > down_limit
|
122
|
+
|
123
|
+
message.target
|
124
|
+
when :position_percent
|
125
|
+
next nack(message) if message.target > 100
|
126
|
+
|
127
|
+
to_pulses(message.target)
|
128
|
+
end
|
97
129
|
ack(message)
|
98
130
|
when Message::SetGroupAddr
|
99
|
-
next nack(message) unless (1..16).
|
100
|
-
|
131
|
+
next nack(message) unless (1..16).cover?(message.group_index)
|
132
|
+
|
133
|
+
groups[message.group_index - 1] = (message.group_address == [0, 0, 0]) ? nil : message.group_address
|
101
134
|
ack(message)
|
102
135
|
when Message::SetMotorIP
|
103
|
-
next nack(message) unless (1..16).
|
136
|
+
next nack(message) unless (1..16).cover?(message.ip) || message.type == :distribute
|
104
137
|
|
105
138
|
case message.type
|
106
139
|
when :delete
|
@@ -122,7 +155,8 @@ module SDN
|
|
122
155
|
end
|
123
156
|
when :distribute
|
124
157
|
next nack(message) unless down_limit
|
125
|
-
next nack(message) unless (1..15).
|
158
|
+
next nack(message) unless (1..15).cover?(message.value)
|
159
|
+
|
126
160
|
span = down_limit / (message.value + 1)
|
127
161
|
current = 0
|
128
162
|
(0...message.value).each do |ip|
|
@@ -134,8 +168,8 @@ module SDN
|
|
134
168
|
ack(message)
|
135
169
|
end
|
136
170
|
when Message::SetMotorLimits
|
137
|
-
next nack(message) unless
|
138
|
-
next nack(message) unless
|
171
|
+
next nack(message) unless Message::SetMotorLimits::TARGET.key?(message.target)
|
172
|
+
next nack(message) unless message.type == :jog_pulses
|
139
173
|
|
140
174
|
self.up_limit ||= 0
|
141
175
|
self.down_limit ||= 0
|
@@ -150,27 +184,30 @@ module SDN
|
|
150
184
|
self.position_pulses += message.value if message.target == :down
|
151
185
|
end
|
152
186
|
ack(message)
|
153
|
-
when Message::SetNodeLabel
|
187
|
+
when Message::SetNodeLabel then self.label = message.label
|
188
|
+
ack(message)
|
154
189
|
end
|
155
190
|
end
|
156
191
|
end
|
157
192
|
end
|
158
193
|
|
159
194
|
def to_percent(pulses)
|
160
|
-
pulses && down_limit ? 100.0 * pulses / down_limit : nil
|
195
|
+
(pulses && down_limit) ? 100.0 * pulses / down_limit : nil
|
161
196
|
end
|
162
197
|
|
163
198
|
def to_pulses(percent)
|
164
|
-
percent && down_limit ? down_limit * percent / 100 : nil
|
199
|
+
(percent && down_limit) ? down_limit * percent / 100 : nil
|
165
200
|
end
|
166
201
|
|
167
202
|
def ack(message)
|
168
203
|
return unless message.ack_requested
|
204
|
+
|
169
205
|
respond(Message::Ack.new(message.dest))
|
170
206
|
end
|
171
207
|
|
172
|
-
def nack(message,
|
208
|
+
def nack(message, _error_code = nil)
|
173
209
|
return unless message.ack_requested
|
210
|
+
|
174
211
|
respond(Message::Nack.new(message.dest))
|
175
212
|
end
|
176
213
|
|
@@ -178,14 +215,11 @@ module SDN
|
|
178
215
|
message.src = address
|
179
216
|
message.node_type = node_type
|
180
217
|
message.dest = dest
|
181
|
-
SDN.logger.info "Sending #{message.inspect}"
|
182
218
|
@client.send(message)
|
183
219
|
end
|
184
220
|
end
|
185
221
|
|
186
|
-
def initialize(
|
187
|
-
sdn = Client.new(port)
|
188
|
-
|
222
|
+
def initialize(sdn, address = nil)
|
189
223
|
motor = MockMotor.new(sdn)
|
190
224
|
motor.address = Message.parse_address(address) if address
|
191
225
|
motor.node_type = :lt50
|
data/lib/sdn/client.rb
CHANGED
@@ -1,33 +1,42 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "io/wait"
|
2
4
|
|
3
5
|
module SDN
|
4
6
|
class Client
|
7
|
+
attr_writer :trace
|
8
|
+
|
5
9
|
def initialize(port)
|
6
10
|
uri = URI.parse(port)
|
7
11
|
@io = if uri.scheme == "tcp"
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
@buffer = ""
|
12
|
+
require "socket"
|
13
|
+
TCPSocket.new(uri.host, uri.port)
|
14
|
+
elsif uri.scheme == "telnet" || uri.scheme == "rfc2217"
|
15
|
+
require "net/telnet/rfc2217"
|
16
|
+
Net::Telnet::RFC2217.new(host: uri.host,
|
17
|
+
port: uri.port || 23,
|
18
|
+
baud: 4800,
|
19
|
+
data_bits: 8,
|
20
|
+
parity: :odd,
|
21
|
+
stop_bits: 1)
|
22
|
+
elsif port == "/dev/ptmx"
|
23
|
+
require "pty"
|
24
|
+
io, slave = PTY.open
|
25
|
+
puts "Slave PTY available at #{slave.path}"
|
26
|
+
io
|
27
|
+
else
|
28
|
+
require "ccutrer-serialport"
|
29
|
+
CCutrer::SerialPort.new(port, baud: 4800, data_bits: 8, parity: :odd, stop_bits: 1)
|
30
|
+
end
|
31
|
+
@buffer = +""
|
32
|
+
end
|
33
|
+
|
34
|
+
def trace?
|
35
|
+
@trace
|
28
36
|
end
|
29
37
|
|
30
38
|
def send(message)
|
39
|
+
SDN.logger.debug("Sending #{message.inspect}")
|
31
40
|
@io.write(message.serialize)
|
32
41
|
end
|
33
42
|
|
@@ -42,6 +51,7 @@ module SDN
|
|
42
51
|
messages = transact(message)
|
43
52
|
next if messages.empty?
|
44
53
|
next unless message.class.expected_response?(messages.first)
|
54
|
+
|
45
55
|
return messages.first
|
46
56
|
end
|
47
57
|
end
|
@@ -63,7 +73,7 @@ module SDN
|
|
63
73
|
eofs = 0
|
64
74
|
begin
|
65
75
|
block = @io.read_nonblock(64 * 1024)
|
66
|
-
SDN.logger.debug
|
76
|
+
SDN.logger.debug("Read #{block.unpack1("H*").gsub(/\h{2}/, "\\0 ")}") if trace?
|
67
77
|
@buffer.concat(block)
|
68
78
|
next
|
69
79
|
rescue IO::WaitReadable, EOFError => e
|
@@ -77,8 +87,10 @@ module SDN
|
|
77
87
|
wait = @buffer.empty? ? timeout : WAIT_TIME
|
78
88
|
if @io.wait_readable(wait).nil?
|
79
89
|
# timed out; just discard everything
|
80
|
-
|
81
|
-
|
90
|
+
unless @buffer.empty?
|
91
|
+
SDN.logger.debug "Discarding #{@buffer.unpack1("H*").gsub(/\h{2}/, "\\0 ")} due to timeout"
|
92
|
+
end
|
93
|
+
@buffer = +""
|
82
94
|
return messages if timeout
|
83
95
|
end
|
84
96
|
|
@@ -86,6 +98,8 @@ module SDN
|
|
86
98
|
end
|
87
99
|
next
|
88
100
|
end
|
101
|
+
|
102
|
+
SDN.logger.debug("Received message #{message.inspect}")
|
89
103
|
if block_given?
|
90
104
|
yield message
|
91
105
|
else
|
data/lib/sdn/message/control.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SDN
|
2
4
|
class Message
|
3
5
|
class Lock < Message
|
4
6
|
MSG = 0x06
|
5
7
|
PARAMS_LENGTH = 5
|
6
|
-
TARGET_TYPE = { current: 0, up_limit: 1, down_limit: 2, ip: 4, unlock: 5, position_percent: 7 }
|
8
|
+
TARGET_TYPE = { current: 0, up_limit: 1, down_limit: 2, ip: 4, unlock: 5, position_percent: 7 }.freeze
|
7
9
|
|
8
10
|
attr_reader :target_type, :target, :priority
|
9
11
|
|
@@ -16,12 +18,16 @@ module SDN
|
|
16
18
|
end
|
17
19
|
|
18
20
|
def target_type=(value)
|
19
|
-
|
21
|
+
unless TARGET_TYPE.key?(value)
|
22
|
+
raise ArgumentError,
|
23
|
+
"target_type must be one of :current, :up_limit, :down_limit, :ip, :unlock, or :position_percent"
|
24
|
+
end
|
25
|
+
|
20
26
|
@target_type = value
|
21
27
|
end
|
22
28
|
|
23
29
|
def target=(value)
|
24
|
-
@target = value
|
30
|
+
@target = value&.& 0xffff
|
25
31
|
end
|
26
32
|
|
27
33
|
def priority=(value)
|
@@ -37,7 +43,8 @@ module SDN
|
|
37
43
|
end
|
38
44
|
|
39
45
|
def params
|
40
|
-
transform_param(TARGET_TYPE[target_type]) + from_number(target,
|
46
|
+
transform_param(TARGET_TYPE[target_type]) + from_number(target,
|
47
|
+
2) + transform_param(priority) + transform_param(0)
|
41
48
|
end
|
42
49
|
end
|
43
50
|
|
@@ -56,29 +63,38 @@ module SDN
|
|
56
63
|
self.direction = direction
|
57
64
|
self.duration = duration
|
58
65
|
self.speed = speed
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
66
|
+
end
|
67
|
+
|
68
|
+
def parse(params)
|
69
|
+
super
|
70
|
+
self.direction = DIRECTION.invert[to_number(params[0])]
|
71
|
+
duration = to_number(params[1])
|
72
|
+
duration = nil if duration.zero?
|
73
|
+
self.duration = duration
|
74
|
+
self.speed = SPEED.invert[to_number(params[3])]
|
75
|
+
end
|
76
|
+
|
77
|
+
def direction=(value)
|
78
|
+
unless DIRECTION.key?(value)
|
79
|
+
raise ArgumentError,
|
80
|
+
"direction must be one of :down, :up, or :cancel (#{value})"
|
81
|
+
end
|
82
|
+
|
72
83
|
@direction = value
|
73
|
-
|
84
|
+
end
|
85
|
+
|
86
|
+
def duration=(value)
|
87
|
+
if value && (value < 0x0a || value > 0xff)
|
88
|
+
raise ArgumentError,
|
89
|
+
"duration must be in range 0x0a to 0xff (#{value})"
|
90
|
+
end
|
74
91
|
|
75
|
-
def duration=(value)
|
76
|
-
raise ArgumentError, "duration must be in range 0x0a to 0xff (#{value})" if value && (value < 0x0a || value > 0xff)
|
77
92
|
@duration = value
|
78
|
-
|
93
|
+
end
|
94
|
+
|
95
|
+
def speed=(value)
|
96
|
+
raise ArgumentError, "speed must be one of :up, :down, or :slow (#{value})" unless SPEED.key?(value)
|
79
97
|
|
80
|
-
def speed=(value)
|
81
|
-
raise ArgumentError, "speed must be one of :up, :down, or :slow (#{value})" unless SPEED.keys.include?(value)
|
82
98
|
@speed = speed
|
83
99
|
end
|
84
100
|
|
@@ -93,7 +109,12 @@ module SDN
|
|
93
109
|
class MoveOf < Message
|
94
110
|
MSG = 0x04
|
95
111
|
PARAMS_LENGTH = 4
|
96
|
-
TARGET_TYPE = { next_ip: 0x00,
|
112
|
+
TARGET_TYPE = { next_ip: 0x00,
|
113
|
+
previous_ip: 0x01,
|
114
|
+
jog_down_pulses: 0x02,
|
115
|
+
jog_up_pulses: 0x03,
|
116
|
+
jog_down_ms: 0x04,
|
117
|
+
jog_up_ms: 0x05 }.freeze
|
97
118
|
|
98
119
|
attr_reader :target_type, :target
|
99
120
|
|
@@ -108,12 +129,16 @@ module SDN
|
|
108
129
|
super
|
109
130
|
self.target_type = TARGET_TYPE.invert[to_number(params[0])]
|
110
131
|
target = to_number(params[1..2], nillable: true)
|
111
|
-
target *= 10 if %I
|
132
|
+
target *= 10 if %I[jog_down_ms jog_up_ms].include?(target_type)
|
112
133
|
self.target = target
|
113
134
|
end
|
114
135
|
|
115
136
|
def target_type=(value)
|
116
|
-
|
137
|
+
unless value.nil? || TARGET_TYPE.key?(value)
|
138
|
+
raise ArgumentError, "target_type must be one of :next_ip, :previous_ip, " \
|
139
|
+
":jog_down_pulses, :jog_up_pulses, :jog_down_ms, :jog_up_ms"
|
140
|
+
end
|
141
|
+
|
117
142
|
@target_type = value
|
118
143
|
end
|
119
144
|
|
@@ -124,7 +149,7 @@ module SDN
|
|
124
149
|
|
125
150
|
def params
|
126
151
|
param = target || 0xffff
|
127
|
-
param /= 10 if %I
|
152
|
+
param /= 10 if %I[jog_down_ms jog_up_ms].include?(target_type)
|
128
153
|
transform_param(TARGET_TYPE[target_type]) + from_number(param, 2) + transform_param(0)
|
129
154
|
end
|
130
155
|
end
|
@@ -138,7 +163,7 @@ module SDN
|
|
138
163
|
|
139
164
|
attr_reader :target_type, :target, :speed
|
140
165
|
|
141
|
-
def initialize(dest= nil, target_type = :down_limit, target = nil, speed = :up, **kwargs)
|
166
|
+
def initialize(dest = nil, target_type = :down_limit, target = nil, speed = :up, **kwargs)
|
142
167
|
kwargs[:dest] ||= dest
|
143
168
|
super(**kwargs)
|
144
169
|
self.target_type = target_type
|
@@ -154,7 +179,11 @@ module SDN
|
|
154
179
|
end
|
155
180
|
|
156
181
|
def target_type=(value)
|
157
|
-
|
182
|
+
unless TARGET_TYPE.key?(value)
|
183
|
+
raise ArgumentError,
|
184
|
+
"target_type must be one of :down_limit, :up_limit, :ip, :position_pulses, or :position_percent"
|
185
|
+
end
|
186
|
+
|
158
187
|
@target_type = value
|
159
188
|
end
|
160
189
|
|
@@ -164,7 +193,8 @@ module SDN
|
|
164
193
|
end
|
165
194
|
|
166
195
|
def speed=(value)
|
167
|
-
raise ArgumentError, "speed must be one of :up, :down, or :slow" unless SPEED.
|
196
|
+
raise ArgumentError, "speed must be one of :up, :down, or :slow" unless SPEED.key?(value)
|
197
|
+
|
168
198
|
@speed = value
|
169
199
|
end
|
170
200
|
|
data/lib/sdn/message/get.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SDN
|
2
4
|
class Message
|
3
5
|
class GetGroupAddr < Message
|
@@ -18,7 +20,8 @@ module SDN
|
|
18
20
|
end
|
19
21
|
|
20
22
|
def group_index=(value)
|
21
|
-
raise ArgumentError, "group_index is out of range" unless (1..16).
|
23
|
+
raise ArgumentError, "group_index is out of range" unless (1..16).cover?(value)
|
24
|
+
|
22
25
|
@group_index = value
|
23
26
|
end
|
24
27
|
|
@@ -49,7 +52,8 @@ module SDN
|
|
49
52
|
end
|
50
53
|
|
51
54
|
def ip=(value)
|
52
|
-
raise ArgumentError, "invalid IP #{value} (should be 1-16)" unless (1..16).
|
55
|
+
raise ArgumentError, "invalid IP #{value} (should be 1-16)" unless (1..16).cover?(value)
|
56
|
+
|
53
57
|
@ip = value
|
54
58
|
end
|
55
59
|
|
data/lib/sdn/message/helpers.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SDN
|
2
4
|
class Message
|
3
5
|
module Helpers
|
@@ -6,39 +8,39 @@ module SDN
|
|
6
8
|
end
|
7
9
|
|
8
10
|
def print_address(addr_bytes)
|
9
|
-
"%02X.%02X.%02X"
|
11
|
+
format("%02X.%02X.%02X", *addr_bytes)
|
10
12
|
end
|
11
13
|
|
12
|
-
def
|
14
|
+
def group_address?(addr_bytes)
|
13
15
|
addr_bytes[0..1] == [1, 1]
|
14
16
|
end
|
15
17
|
|
16
18
|
def node_type_from_number(number)
|
17
19
|
case number
|
18
|
-
when 1
|
19
|
-
when 2
|
20
|
-
when 6
|
21
|
-
when 7
|
22
|
-
when 8
|
23
|
-
when 0x70
|
20
|
+
when 1 then :st50ilt2
|
21
|
+
when 2 then :st30
|
22
|
+
when 6 then :glydea
|
23
|
+
when 7 then :st50ac
|
24
|
+
when 8 then :st50dc
|
25
|
+
when 0x70 then :lt50
|
24
26
|
else; number
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
28
30
|
def node_type_to_number(type)
|
29
31
|
case type
|
30
|
-
when :st50ilt2
|
31
|
-
when :st30
|
32
|
-
when :glydea
|
33
|
-
when :st50ac
|
34
|
-
when :st50dc
|
35
|
-
when :lt50
|
32
|
+
when :st50ilt2 then 1
|
33
|
+
when :st30 then 2
|
34
|
+
when :glydea then 6
|
35
|
+
when :st50ac then 7
|
36
|
+
when :st50dc then 8
|
37
|
+
when :lt50 then 0x70
|
36
38
|
else; type
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
40
42
|
def node_type_to_string(type)
|
41
|
-
type.is_a?(Integer) ? "%02xh"
|
43
|
+
type.is_a?(Integer) ? format("%02xh", type) : type.inspect
|
42
44
|
end
|
43
45
|
|
44
46
|
def transform_param(param)
|
@@ -52,28 +54,27 @@ module SDN
|
|
52
54
|
end
|
53
55
|
|
54
56
|
def from_number(number, bytes = 1)
|
55
|
-
number ||= 1
|
57
|
+
number ||= (1**(bytes * 8)) - 1
|
56
58
|
number = number.to_i
|
57
|
-
bytes.times.
|
58
|
-
res << (0xff - number & 0xff)
|
59
|
+
bytes.times.each_with_object([]) do |_, res|
|
60
|
+
res << ((0xff - number) & 0xff)
|
59
61
|
number >>= 8
|
60
|
-
res
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
64
65
|
def to_string(param)
|
65
66
|
chars = param.map { |b| 0xff - b }
|
66
|
-
chars.pack("C*").sub(/\0+$/,
|
67
|
+
chars.pack("C*").sub(/\0+$/, "").strip
|
67
68
|
end
|
68
69
|
|
69
70
|
def from_string(string, bytes)
|
70
71
|
chars = string.bytes
|
71
|
-
chars = chars[0...bytes].fill(
|
72
|
+
chars = chars[0...bytes].fill(" ".ord, chars.length, bytes - chars.length)
|
72
73
|
chars.map { |b| 0xff - b }
|
73
74
|
end
|
74
75
|
|
75
76
|
def checksum(bytes)
|
76
|
-
result = bytes.
|
77
|
+
result = bytes.sum
|
77
78
|
[result >> 8, result & 0xff]
|
78
79
|
end
|
79
80
|
end
|
data/lib/sdn/message/ilt2/get.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SDN
|
2
4
|
class Message
|
3
5
|
module ILT2
|
@@ -22,15 +24,16 @@ module SDN
|
|
22
24
|
end
|
23
25
|
|
24
26
|
def ip=(value)
|
25
|
-
raise ArgumentError, "invalid IP #{value} (should be 1-16)" unless (1..16).
|
27
|
+
raise ArgumentError, "invalid IP #{value} (should be 1-16)" unless (1..16).cover?(value)
|
28
|
+
|
26
29
|
@ip = value
|
27
30
|
end
|
28
|
-
|
31
|
+
|
29
32
|
def parse(params)
|
30
33
|
super
|
31
34
|
self.ip = to_number(params[0]) + 1
|
32
35
|
end
|
33
|
-
|
36
|
+
|
34
37
|
def params
|
35
38
|
transform_param(@ip - 1)
|
36
39
|
end
|