somfy_sdn 2.1.5 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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"