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.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SDN
2
4
  class Message
3
5
  module ILT2
@@ -10,12 +12,14 @@ module SDN
10
12
  return unless checksum(data[0..2]) == data[3..4]
11
13
  # no clue what's special about these
12
14
  return unless data[0..1] == [0xfa, 0x7a]
15
+
13
16
  klass = case data[2]
14
- when 0x00; Down
15
- when 0xfa; Up
16
- when 0xff; Stop
17
- end
17
+ when 0x00 then Down
18
+ when 0xfa then Up
19
+ when 0xff then Stop
20
+ end
18
21
  return unless klass
22
+
19
23
  [klass.new, 5]
20
24
  end
21
25
  end
@@ -25,11 +29,10 @@ module SDN
25
29
 
26
30
  class Stop < MasterControl
27
31
  end
28
-
32
+
29
33
  class Up < MasterControl
30
34
  end
31
-
32
35
  end
33
36
  end
34
37
  end
35
- end
38
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SDN
2
4
  class Message
3
5
  module ILT2
@@ -13,7 +15,7 @@ module SDN
13
15
  end
14
16
 
15
17
  def channels=(value)
16
- @channels = value &. & 0xff
18
+ @channels = value&.& 0xff
17
19
  end
18
20
 
19
21
  def parse(params)
@@ -26,7 +28,7 @@ module SDN
26
28
  end
27
29
 
28
30
  def class_inspect
29
- ", @channels=#{channels.chr.unpack('b8').first}"
31
+ ", @channels=#{channels.chr.unpack1("b8")}"
30
32
  end
31
33
  end
32
34
 
@@ -77,9 +79,9 @@ module SDN
77
79
  class PostMotorPosition < Message
78
80
  MSG = 0x64
79
81
  PARAMS_LENGTH = 3
80
-
82
+
81
83
  attr_accessor :position_pulses, :position_percent
82
-
84
+
83
85
  def initialize(position_pulses = nil, position_percent = nil, **kwargs)
84
86
  super(**kwargs)
85
87
  self.position_pulses = position_pulses
@@ -94,7 +96,7 @@ module SDN
94
96
 
95
97
  def params
96
98
  from_number(position_pulses, 2) +
97
- from_number(position_percent && position_percent * 255 / 100)
99
+ from_number(position_percent && (position_percent * 255 / 100))
98
100
  end
99
101
  end
100
102
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SDN
2
4
  class Message
3
5
  module ILT2
@@ -19,7 +21,7 @@ module SDN
19
21
  down_limit: 2,
20
22
  ip: 4,
21
23
  unlock: 5
22
- }
24
+ }.freeze
23
25
 
24
26
  # when target_type is down_limit, target is number of 10ms intervals it's still allowed to roll up
25
27
  attr_reader :target_type, :target, :priority
@@ -40,16 +42,21 @@ module SDN
40
42
  end
41
43
 
42
44
  def target_type=(value)
43
- raise ArgumentError, "target_type must be one of :current, :up_limit, :down_limit, :ip, or :unlock" unless TARGET_TYPE.keys.include?(value)
45
+ unless TARGET_TYPE.key?(value)
46
+ raise ArgumentError,
47
+ "target_type must be one of :current, :up_limit, :down_limit, :ip, or :unlock"
48
+ end
49
+
44
50
  @target_type = value
45
51
  end
46
52
 
47
53
  def target=(value)
48
- @target = value&. & 0xff
54
+ @target = value&.& 0xff
49
55
  end
50
56
 
51
57
  def priority=(value)
52
- raise ArgumentError, "priority must be between 1 and 100" unless (1..100).include?(value)
58
+ raise ArgumentError, "priority must be between 1 and 100" unless (1..100).cover?(value)
59
+
53
60
  @priority = value
54
61
  end
55
62
 
@@ -78,12 +85,13 @@ module SDN
78
85
  end
79
86
 
80
87
  def ip=(value)
81
- raise ArgumentError, "ip must be in range 1..16 or nil" unless ip.nil? || (1..16).include?(ip)
88
+ raise ArgumentError, "ip must be in range 1..16 or nil" unless ip.nil? || (1..16).cover?(ip)
89
+
82
90
  @ip = value
83
91
  end
84
92
 
85
93
  def value=(value)
86
- @value = value &. & 0xffff
94
+ @value = value&.& 0xffff
87
95
  end
88
96
 
89
97
  def params
@@ -110,7 +118,7 @@ module SDN
110
118
  jog_down_ms: 11,
111
119
  jog_up_pulses: 12,
112
120
  jog_down_pulses: 13,
113
- position_percent: 16,
121
+ position_percent: 16
114
122
  }.freeze
115
123
 
116
124
  attr_reader :target_type, :target
@@ -126,26 +134,27 @@ module SDN
126
134
  super
127
135
  self.target_type = TARGET_TYPE.invert[to_number(params[0])]
128
136
  target = to_number(params[1..2])
129
- if target_type == :position_percent
130
- target = target.to_f / 255 * 100
131
- end
132
- if target_type == :ip
133
- target += 1
134
- end
137
+ target = target.to_f / 255 * 100 if target_type == :position_percent
138
+ target += 1 if target_type == :ip
135
139
  self.target = target
136
140
  end
137
141
 
138
142
  def target_type=(value)
139
- raise ArgumentError, "target_type must be one of :up_limit, :down_limit, :stop, :ip, :next_ip_up, :next_ip_down, :jog_up, :jog_down, or :position_percent" unless TARGET_TYPE.keys.include?(value)
143
+ unless TARGET_TYPE.key?(value)
144
+ raise ArgumentError, "target_type must be one of :up_limit, :down_limit, " \
145
+ ":stop, :ip, :next_ip_up, :next_ip_down, :jog_up, " \
146
+ ":jog_down, or :position_percent"
147
+ end
148
+
140
149
  @target_type = value
141
150
  end
142
151
 
143
152
  def target=(value)
144
- if target_type == :position_percent && value
145
- @target = [[0, value].max, 100].min
146
- else
147
- @target = value&. & 0xffff
148
- end
153
+ @target = if target_type == :position_percent && value
154
+ value.clamp(0, 100)
155
+ else
156
+ value&.& 0xffff
157
+ end
149
158
  end
150
159
 
151
160
  def params
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SDN
2
4
  class Message
3
5
  class PostGroupAddr < Message
@@ -24,7 +26,7 @@ module SDN
24
26
  end
25
27
 
26
28
  def class_inspect
27
- ", group_index=#{group_index.inspect}, group_address=#{group_address ? print_address(group_address) : 'nil'}"
29
+ ", group_index=#{group_index.inspect}, group_address=#{group_address ? print_address(group_address) : "nil"}"
28
30
  end
29
31
  end
30
32
 
@@ -160,10 +162,6 @@ module SDN
160
162
  class PostNetworkLock < UnknownMessage
161
163
  MSG = 0x36
162
164
  PARAMS_LENGTH = 5
163
-
164
- def parse(params)
165
- super
166
- end
167
165
  end
168
166
 
169
167
  class PostNodeAddr < Message
@@ -1,9 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SDN
2
4
  class Message
3
5
  class SetFactoryDefault < Message
4
6
  MSG = 0x1f
5
7
  PARAMS_LENGTH = 1
6
- RESET = { all_settings: 0x00, group_addresses: 0x01, limits: 0x11, rotation: 0x12, rolling_speed: 0x13, ips: 0x15, locks: 0x17 }
8
+ RESET = { all_settings: 0x00,
9
+ group_addresses: 0x01,
10
+ limits: 0x11,
11
+ rotation: 0x12,
12
+ rolling_speed: 0x13,
13
+ ips: 0x15,
14
+ locks: 0x17 }.freeze
7
15
 
8
16
  attr_reader :reset
9
17
 
@@ -19,7 +27,11 @@ module SDN
19
27
  end
20
28
 
21
29
  def reset=(value)
22
- raise ArgumentError, "reset must be one of :all_settings, :group_addresses, :limits, :rotation, :rolling_speed, :ips, :locks" unless RESET.keys.include?(value)
30
+ unless RESET.key?(value)
31
+ raise ArgumentError,
32
+ "reset must be one of :all_settings, :group_addresses, :limits, :rotation, :rolling_speed, :ips, :locks"
33
+ end
34
+
23
35
  @reset = value
24
36
  end
25
37
 
@@ -32,7 +44,8 @@ module SDN
32
44
  MSG = 0x51
33
45
  PARAMS_LENGTH = 4
34
46
 
35
- attr_reader :group_index, :group_address
47
+ attr_accessor :group_address
48
+ attr_reader :group_index
36
49
 
37
50
  def initialize(dest = nil, group_index = 1, group_address = nil, **kwargs)
38
51
  kwargs[:dest] ||= dest
@@ -48,12 +61,9 @@ module SDN
48
61
  end
49
62
 
50
63
  def group_index=(value)
51
- raise ArgumentError, "group_index is out of range" unless (1..16).include?(value)
52
- @group_index = value
53
- end
64
+ raise ArgumentError, "group_index is out of range" unless (1..16).cover?(value)
54
65
 
55
- def group_address=(value)
56
- @group_address = value
66
+ @group_index = value
57
67
  end
58
68
 
59
69
  def params
@@ -61,7 +71,7 @@ module SDN
61
71
  end
62
72
 
63
73
  def class_inspect
64
- ", group_index=#{group_index.inspect}, group_address=#{group_address ? print_address(group_address) : 'nil'}"
74
+ ", group_index=#{group_index.inspect}, group_address=#{group_address ? print_address(group_address) : "nil"}"
65
75
  end
66
76
  end
67
77
 
@@ -84,7 +94,8 @@ module SDN
84
94
  end
85
95
 
86
96
  def direction=(value)
87
- raise ArgumentError, "direction must be one of :standard, :reversed" unless DIRECTION.keys.include?(value)
97
+ raise ArgumentError, "direction must be one of :standard, :reversed" unless DIRECTION.key?(value)
98
+
88
99
  @direction = value
89
100
  end
90
101
 
@@ -97,7 +108,11 @@ module SDN
97
108
  MSG = 0x15
98
109
  PARAMS_LENGTH = 4
99
110
  # for distribute, value is how many IPs to distribute over
100
- TYPE = { delete: 0x00, current_position: 0x01, position_pulses: 0x02, position_percent: 0x03, distribute: 0x04 }.freeze
111
+ TYPE = { delete: 0x00,
112
+ current_position: 0x01,
113
+ position_pulses: 0x02,
114
+ position_percent: 0x03,
115
+ distribute: 0x04 }.freeze
101
116
 
102
117
  attr_reader :type, :ip, :value
103
118
 
@@ -113,23 +128,28 @@ module SDN
113
128
  super
114
129
  self.type = TYPE.invert[to_number(params[0])]
115
130
  ip = to_number(params[1])
116
- ip = nil if ip == 0
131
+ ip = nil if ip.zero?
117
132
  self.ip = ip
118
133
  self.value = to_number(params[2..3])
119
134
  end
120
135
 
121
136
  def type=(value)
122
- raise ArgumentError, "type must be one of :delete, :current_position, :position_pulses, :position_percent, :distribute" unless TYPE.keys.include?(value)
137
+ unless TYPE.key?(value)
138
+ raise ArgumentError,
139
+ "type must be one of :delete, :current_position, :position_pulses, :position_percent, :distribute"
140
+ end
141
+
123
142
  @type = value
124
143
  end
125
144
 
126
145
  def ip=(value)
127
- raise ArgumentError, "ip must be in range 1..16 or nil" unless ip.nil? || (1..16).include?(ip)
146
+ raise ArgumentError, "ip must be in range 1..16 or nil" unless ip.nil? || (1..16).cover?(ip)
147
+
128
148
  @ip = value
129
149
  end
130
150
 
131
151
  def value=(value)
132
- @value = value &. & 0xffff
152
+ @value = value&.& 0xffff
133
153
  end
134
154
 
135
155
  def params
@@ -140,8 +160,8 @@ module SDN
140
160
  class SetMotorLimits < Message
141
161
  MSG = 0x11
142
162
  PARAMS_LENGTH = 4
143
- TYPE = { delete: 0x00, current_position: 0x01, specified_position: 0x02, jog_ms: 0x04, jog_pulses: 0x05 }
144
- TARGET = { down: 0x00, up: 0x01 }
163
+ TYPE = { delete: 0x00, current_position: 0x01, specified_position: 0x02, jog_ms: 0x04, jog_pulses: 0x05 }.freeze
164
+ TARGET = { down: 0x00, up: 0x01 }.freeze
145
165
 
146
166
  attr_reader :type, :target, :value
147
167
 
@@ -161,17 +181,22 @@ module SDN
161
181
  end
162
182
 
163
183
  def type=(value)
164
- raise ArgumentError, "type must be one of :delete, :current_position, :specified_position, :jog_ms, :jog_pulses" unless TYPE.keys.include?(value)
184
+ unless TYPE.key?(value)
185
+ raise ArgumentError,
186
+ "type must be one of :delete, :current_position, :specified_position, :jog_ms, :jog_pulses"
187
+ end
188
+
165
189
  @type = value
166
190
  end
167
191
 
168
192
  def target=(value)
169
- raise ArgumentError, "target must be one of :up, :down" unless TARGET.keys.include?(value)
193
+ raise ArgumentError, "target must be one of :up, :down" unless TARGET.key?(value)
194
+
170
195
  @target = value
171
196
  end
172
197
 
173
198
  def value=(value)
174
- @value = value&. & 0xffff
199
+ @value = value&.& 0xffff
175
200
  end
176
201
 
177
202
  def params
@@ -186,6 +211,7 @@ module SDN
186
211
  PARAMS_LENGTH = 3
187
212
 
188
213
  attr_accessor :up_speed, :down_speed, :slow_speed
214
+
189
215
  def initialize(dest = nil, up_speed: nil, down_speed: nil, slow_speed: nil, **kwargs)
190
216
  kwargs[:dest] ||= dest
191
217
  super(**kwargs)
@@ -212,7 +238,7 @@ module SDN
212
238
  attr_accessor :locked, :priority
213
239
 
214
240
  def parse(params)
215
- self.locked = to_number(params[0]) == 1 ? true : false
241
+ self.locked = to_number(params[0]) == 1
216
242
  self.priority = to_number(params[1])
217
243
  end
218
244
 
@@ -227,7 +253,7 @@ module SDN
227
253
 
228
254
  attr_accessor :label
229
255
 
230
- def initialize(dest = nil, label = '', **kwargs)
256
+ def initialize(dest = nil, label = "", **kwargs)
231
257
  kwargs[:dest] ||= dest
232
258
  super(**kwargs)
233
259
  self.label = label
data/lib/sdn/message.rb CHANGED
@@ -1,4 +1,6 @@
1
- require 'sdn/message/helpers'
1
+ # frozen_string_literal: true
2
+
3
+ require "sdn/message/helpers"
2
4
 
3
5
  module SDN
4
6
  class MalformedMessage < RuntimeError; end
@@ -6,14 +8,16 @@ module SDN
6
8
  class Message
7
9
  class << self
8
10
  def inherited(klass)
11
+ super
9
12
  return Message.inherited(klass) unless self == Message
13
+
10
14
  @message_map = nil
11
15
  (@subclasses ||= []) << klass
12
16
  end
13
17
 
14
18
  def expected_response?(message)
15
- if name =~ /::Get([A-Za-z]+)/
16
- message.class.name == name.sub("::Get", "::Post")
19
+ if /::Get([A-Za-z]+)/.match?(name)
20
+ message.class.name == name.sub("::Get", "::Post") # rubocop:disable Style/ClassEqualityComparison
17
21
  else
18
22
  message.is_a?(Ack) || message.is_a?(Nack)
19
23
  end
@@ -30,6 +34,7 @@ module SDN
30
34
  return result if result
31
35
 
32
36
  return [nil, 0] if data.length - offset < 11
37
+
33
38
  msg = to_number(data[offset])
34
39
  length = to_number(data[offset + 1])
35
40
  ack_requested = length & 0x80 == 0x80
@@ -57,7 +62,7 @@ module SDN
57
62
  result.parse(data.slice(offset + 9, length - 11))
58
63
  result.msg = msg if message_class == UnknownMessage
59
64
  rescue ArgumentError => e
60
- SDN.logger.warn "discarding illegal message of type #{message_class.name}: #{e}"
65
+ SDN.logger.warn "Discarding illegal message of type #{message_class.name}: #{e}"
61
66
  result = nil
62
67
  end
63
68
  [result, offset + length]
@@ -67,10 +72,10 @@ module SDN
67
72
 
68
73
  def message_map
69
74
  @message_map ||=
70
- @subclasses.inject({}) do |memo, klass|
75
+ @subclasses.each_with_object({}) do |klass, memo|
71
76
  next memo unless klass.constants(false).include?(:MSG)
77
+
72
78
  memo[klass.const_get(:MSG, false)] = klass
73
- memo
74
79
  end
75
80
  end
76
81
  end
@@ -83,7 +88,7 @@ module SDN
83
88
  def initialize(node_type: nil, ack_requested: false, src: nil, dest: nil)
84
89
  @node_type = node_type || 0
85
90
  @ack_requested = ack_requested
86
- if src.nil? && !dest.nil? && is_group_address?(dest)
91
+ if src.nil? && !dest.nil? && group_address?(dest)
87
92
  src = dest
88
93
  dest = nil
89
94
  end
@@ -92,7 +97,11 @@ module SDN
92
97
  end
93
98
 
94
99
  def parse(params)
95
- raise MalformedMessage, "unrecognized params for #{self.class.name}: #{params.map { |b| '%02x' % b }}" if self.class.const_defined?(:PARAMS_LENGTH) && params.length != self.class.const_get(:PARAMS_LENGTH)
100
+ return unless self.class.const_defined?(:PARAMS_LENGTH) && params.length != self.class.const_get(:PARAMS_LENGTH)
101
+
102
+ raise MalformedMessage, "unrecognized params for #{self.class.name}: #{params.map do |b|
103
+ format("%02x", b)
104
+ end}"
96
105
  end
97
106
 
98
107
  def serialize
@@ -105,25 +114,32 @@ module SDN
105
114
  end
106
115
 
107
116
  def ==(other)
108
- self.serialize == other.serialize
117
+ serialize == other.serialize
109
118
  end
110
119
 
111
120
  def inspect
112
- "#<%s @node_type=%s, @ack_requested=%s, @src=%s, @dest=%s%s>" % [self.class.name, node_type_to_string(node_type), ack_requested, print_address(src), print_address(dest), class_inspect]
121
+ format("#<%s @node_type=%s, @ack_requested=%s, @src=%s, @dest=%s%s>",
122
+ self.class.name,
123
+ node_type_to_string(node_type),
124
+ ack_requested,
125
+ print_address(src),
126
+ print_address(dest),
127
+ class_inspect)
113
128
  end
114
129
  alias_method :to_s, :inspect
115
130
 
116
131
  def class_inspect
117
- ivars = instance_variables - [:@node_type, :@ack_requested, :@src, :@dest, :@params]
132
+ ivars = instance_variables - %i[@node_type @ack_requested @src @dest @params]
118
133
  return if ivars.empty?
134
+
119
135
  ivars.map { |iv| ", #{iv}=#{instance_variable_get(iv).inspect}" }.join
120
136
  end
121
137
 
122
138
  protected
123
139
 
124
- def params; []; end
125
-
126
- public
140
+ def params
141
+ []
142
+ end
127
143
 
128
144
  class SimpleRequest < Message
129
145
  PARAMS_LENGTH = 0
@@ -144,11 +160,10 @@ module SDN
144
160
  limits_not_set: 0x22,
145
161
  ip_not_set: 0x23,
146
162
  out_of_range: 0x24,
147
- busy: 0xff }
148
- # 17 limits not set?
149
- # 37 not implemented? (get motor rolling speed)
150
- # 39 at limit? blocked?
151
-
163
+ busy: 0xff }.freeze
164
+ # 17 limits not set?
165
+ # 37 not implemented? (get motor rolling speed)
166
+ # 39 at limit? blocked?
152
167
 
153
168
  # presumed
154
169
  attr_accessor :error_code
@@ -180,33 +195,34 @@ module SDN
180
195
  self.params = params
181
196
  end
182
197
 
183
- alias parse params=
198
+ alias_method :parse, :params=
184
199
 
185
200
  def serialize
186
201
  # prevent serializing something we don't know
187
202
  raise NotImplementedError unless params
203
+
188
204
  super
189
205
  end
190
206
 
191
207
  def class_inspect
192
- result = if self.class == UnknownMessage
193
- result = ", @msg=%02xh" % msg
194
- else
195
- super || ""
196
- end
208
+ result = if instance_of?(UnknownMessage)
209
+ format(", @msg=%02xh", msg)
210
+ else
211
+ super || ""
212
+ end
197
213
  return result if params.empty?
198
214
 
199
- result << ", @params=#{params.map { |b| "%02x" % b }.join(' ')}"
215
+ result << ", @params=#{params.map { |b| format("%02x", b) }.join(" ")}"
200
216
  end
201
217
  end
202
218
  end
203
219
  end
204
220
 
205
- require 'sdn/message/control'
206
- require 'sdn/message/get'
207
- require 'sdn/message/post'
208
- require 'sdn/message/set'
209
- require 'sdn/message/ilt2/get'
210
- require 'sdn/message/ilt2/master_control'
211
- require 'sdn/message/ilt2/post'
212
- require 'sdn/message/ilt2/set'
221
+ require "sdn/message/control"
222
+ require "sdn/message/get"
223
+ require "sdn/message/post"
224
+ require "sdn/message/set"
225
+ require "sdn/message/ilt2/get"
226
+ require "sdn/message/ilt2/master_control"
227
+ require "sdn/message/ilt2/post"
228
+ require "sdn/message/ilt2/set"
data/lib/sdn/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SDN
2
- VERSION = '2.1.5'
4
+ VERSION = "2.2.0"
3
5
  end
data/lib/sdn.rb CHANGED
@@ -1,21 +1,27 @@
1
- require 'logger'
1
+ # frozen_string_literal: true
2
2
 
3
- require 'sdn/client'
4
- require 'sdn/message'
3
+ require "logger"
4
+
5
+ require "sdn/client"
6
+ require "sdn/message"
5
7
 
6
8
  module SDN
7
- BROADCAST_ADDRESS = [0xff, 0xff, 0xff]
9
+ BROADCAST_ADDRESS = [0xff, 0xff, 0xff].freeze
8
10
 
9
11
  class << self
10
- def logger
11
- @logger ||= begin
12
- Logger.new(STDOUT, :info).tap do |logger|
13
- logger.datetime_format = '%Y-%m-%d %H:%M:%S.%L'
14
- logger.formatter = proc do |severity, datetime, progname, msg|
15
- "#{datetime.strftime(logger.datetime_format)} [#{Process.pid}/#{Thread.current.object_id}] #{severity}: #{msg}\n"
16
- end
17
- end
12
+ def logger=(logger)
13
+ logger.datetime_format = "%Y-%m-%d %H:%M:%S.%L"
14
+ logger.formatter = proc do |severity, datetime, _progname, msg|
15
+ "#{datetime.strftime(logger.datetime_format)} " \
16
+ "[#{Process.pid}/#{Thread.current.object_id}] " \
17
+ "#{severity}: #{msg}\n"
18
18
  end
19
+ @logger = logger
20
+ end
21
+
22
+ def logger
23
+ self.logger = Logger.new($stdout, :info) unless @logger
24
+ @logger
19
25
  end
20
26
  end
21
27
  end
data/lib/somfy_sdn.rb CHANGED
@@ -1 +1,3 @@
1
- require 'sdn'
1
+ # frozen_string_literal: true
2
+
3
+ require "sdn"