somfy_sdn 1.0.12 → 2.0.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.
@@ -13,6 +13,34 @@ module SDN
13
13
  addr_bytes[0..1] == [1, 1]
14
14
  end
15
15
 
16
+ def node_type_from_number(number)
17
+ case number
18
+ when 1; :st50ilt2
19
+ when 2; :st30
20
+ when 6; :glydea
21
+ when 7; :st50ac
22
+ when 8; :st50dc
23
+ when 0x70; :lt50
24
+ else; number
25
+ end
26
+ end
27
+
28
+ def node_type_to_number(type)
29
+ case type
30
+ when :st50ilt2; 1
31
+ when :st30; 2
32
+ when :glydea; 6
33
+ when :st50ac; 7
34
+ when :st50dc; 8
35
+ when :lt50; 0x70
36
+ else; type
37
+ end
38
+ end
39
+
40
+ def node_type_to_string(type)
41
+ type.is_a?(Integer) ? "%02xh" % type : type.inspect
42
+ end
43
+
16
44
  def transform_param(param)
17
45
  Array(param).reverse.map { |byte| 0xff - byte }
18
46
  end
@@ -23,7 +51,9 @@ module SDN
23
51
  result
24
52
  end
25
53
 
26
- def from_number(number, bytes)
54
+ def from_number(number, bytes = 1)
55
+ number ||= 1 ** (bytes * 8) - 1
56
+ number = number.to_i
27
57
  bytes.times.inject([]) do |res, _|
28
58
  res << (0xff - number & 0xff)
29
59
  number >>= 8
@@ -33,12 +63,12 @@ module SDN
33
63
 
34
64
  def to_string(param)
35
65
  chars = param.map { |b| 0xff - b }
36
- chars[0..-1].pack("C*").sub(/\0+$/, '')
66
+ chars.pack("C*").sub(/\0+$/, '').strip
37
67
  end
38
68
 
39
69
  def from_string(string, bytes)
40
70
  chars = string.bytes
41
- chars = chars[0...16].fill(0, chars.length, bytes - chars.length)
71
+ chars = chars[0...bytes].fill(' '.ord, chars.length, bytes - chars.length)
42
72
  chars.map { |b| 0xff - b }
43
73
  end
44
74
 
@@ -0,0 +1,48 @@
1
+ module SDN
2
+ class Message
3
+ module ILT2
4
+ class GetIRConfig < SimpleRequest
5
+ MSG = 0x49
6
+ end
7
+
8
+ class GetLockStatus < SimpleRequest
9
+ MSG = 0x4b
10
+ end
11
+
12
+ class GetMotorIP < Message
13
+ MSG = 0x43
14
+ PARAMS_LENGTH = 1
15
+
16
+ attr_reader :ip
17
+
18
+ def initialize(dest = nil, ip = 1, **kwargs)
19
+ kwargs[:dest] ||= dest
20
+ super(**kwargs)
21
+ self.ip = ip
22
+ end
23
+
24
+ def ip=(value)
25
+ raise ArgumentError, "invalid IP #{value} (should be 1-16)" unless (1..16).include?(value)
26
+ @ip = value
27
+ end
28
+
29
+ def parse(params)
30
+ super
31
+ self.ip = to_number(params[0]) + 1
32
+ end
33
+
34
+ def params
35
+ transform_param(@ip - 1)
36
+ end
37
+ end
38
+
39
+ class GetMotorPosition < SimpleRequest
40
+ MSG = 0x44
41
+ end
42
+
43
+ class GetMotorSettings < SimpleRequest
44
+ MSG = 0x42
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,35 @@
1
+ module SDN
2
+ class Message
3
+ module ILT2
4
+ class MasterControl
5
+ class << self
6
+ include Helpers
7
+
8
+ def parse(data)
9
+ return unless data.length >= 5
10
+ return unless checksum(data[0..2]) == data[3..4]
11
+ # no clue what's special about these
12
+ return unless data[0..1] == [0xfa, 0x7a]
13
+ klass = case data[2]
14
+ when 0x00; Down
15
+ when 0xfa; Up
16
+ when 0xff; Stop
17
+ end
18
+ return unless klass
19
+ [klass.new, 5]
20
+ end
21
+ end
22
+
23
+ class Down < MasterControl
24
+ end
25
+
26
+ class Stop < MasterControl
27
+ end
28
+
29
+ class Up < MasterControl
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,127 @@
1
+ module SDN
2
+ class Message
3
+ module ILT2
4
+ class PostIRConfig < Message
5
+ MSG = 0x69
6
+ PARAMS_LENGTH = 1
7
+
8
+ attr_reader :channels
9
+
10
+ def initialize(channels = nil, **kwargs)
11
+ super(**kwargs)
12
+ self.channels = channels
13
+ end
14
+
15
+ def channels=(value)
16
+ @channels = value &. & 0xff
17
+ end
18
+
19
+ def parse(params)
20
+ super
21
+ self.channels = to_number(params[0])
22
+ end
23
+
24
+ def params
25
+ transform_param(channels)
26
+ end
27
+
28
+ def class_inspect
29
+ ", @channels=#{channels.chr.unpack('b8').first}"
30
+ end
31
+ end
32
+
33
+ class PostLockStatus < Message
34
+ MSG = 0x6B
35
+ PARAMS_LENGTH = 1
36
+
37
+ attr_accessor :priority # 0 for not locked
38
+
39
+ def initialize(priority = nil, **kwargs)
40
+ super(**kwargs)
41
+ self.priority = priority
42
+ end
43
+
44
+ def parse(params)
45
+ super
46
+ self.current_lock_priority = to_number(params[0])
47
+ end
48
+
49
+ def params
50
+ transform_param(priority)
51
+ end
52
+ end
53
+
54
+ class PostMotorIP < Message
55
+ MSG = 0x63
56
+ PARAMS_LENGTH = 3
57
+
58
+ attr_accessor :ip, :position_pulses
59
+
60
+ def initialize(ip = nil, position_pulses = nil, **kwargs)
61
+ super(**kwargs)
62
+ self.ip = ip
63
+ self.position_pulses = position_pulses
64
+ end
65
+
66
+ def parse(params)
67
+ super
68
+ self.ip = to_number(params[0]) + 1
69
+ self.position_pulses = to_number(params[1..2], nillable: true)
70
+ end
71
+
72
+ def params
73
+ transform_param(ip - 1) + from_number(position_pulses, 2)
74
+ end
75
+ end
76
+
77
+ class PostMotorPosition < Message
78
+ MSG = 0x64
79
+ PARAMS_LENGTH = 3
80
+
81
+ attr_accessor :position_pulses, :position_percent
82
+
83
+ def initialize(position_pulses = nil, position_percent = nil, **kwargs)
84
+ super(**kwargs)
85
+ self.position_pulses = position_pulses
86
+ self.position_percent = position_percent
87
+ end
88
+
89
+ def parse(params)
90
+ super
91
+ self.position_pulses = to_number(params[0..1])
92
+ self.position_percent = to_number(params[2]).to_f / 255 * 100
93
+ end
94
+
95
+ def params
96
+ from_number(position_pulses, 2) +
97
+ from_number(position_percent && position_percent * 255 / 100)
98
+ end
99
+ end
100
+
101
+ class PostMotorSettings < UnknownMessage
102
+ MSG = 0x62
103
+ PARAMS_LENGTH = 3
104
+
105
+ attr_accessor :limit
106
+
107
+ def initialize(limit = nil, **kwargs)
108
+ super(**kwargs)
109
+ self.limit = limit
110
+ end
111
+
112
+ def parse(params)
113
+ super
114
+ self.limit = to_number(params[1..2])
115
+ end
116
+
117
+ def params
118
+ transform_param(0) + from_number(limit, 2)
119
+ end
120
+ end
121
+
122
+ class PostNodeLabel < ::SDN::Message::PostNodeLabel
123
+ MAX_LENGTH = 32
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,192 @@
1
+ module SDN
2
+ class Message
3
+ module ILT2
4
+ class SetIRConfig < PostIRConfig
5
+ MSG = 0x59
6
+
7
+ def initialize(dest = nil, channels = nil, **kwargs)
8
+ kwargs[:dest] ||= dest
9
+ super(channels, **kwargs)
10
+ end
11
+ end
12
+
13
+ class SetLockStatus < Message
14
+ MSG = 0x5B
15
+ PARAMS_LENGTH = 3
16
+ TARGET_TYPE = {
17
+ current: 0,
18
+ up_limit: 1,
19
+ down_limit: 2,
20
+ ip: 4,
21
+ unlock: 5
22
+ }
23
+
24
+ # when target_type is down_limit, target is number of 10ms intervals it's still allowed to roll up
25
+ attr_reader :target_type, :target, :priority
26
+
27
+ def initialize(dest = nil, target_type = :unlock, target = nil, priority = 1, **kwargs)
28
+ kwargs[:dest] ||= dest
29
+ super(**kwargs)
30
+ self.target_type = target_type
31
+ self.target = target
32
+ self.priority = priority
33
+ end
34
+
35
+ def parse(params)
36
+ super
37
+ self.target_type = TARGET_TYPE.invert[to_number(params[0])]
38
+ self.target = to_number(params[1])
39
+ self.priority = to_number(params[2])
40
+ end
41
+
42
+ 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)
44
+ @target_type = value
45
+ end
46
+
47
+ def target=(value)
48
+ @target = value&. & 0xff
49
+ end
50
+
51
+ def priority=(value)
52
+ raise ArgumentError, "priority must be between 1 and 100" unless (1..100).include?(value)
53
+ @priority = value
54
+ end
55
+
56
+ def params
57
+ transform_param(TARGET_TYPE[target_type]) + transform_param(target) + transform_param(priority)
58
+ end
59
+ end
60
+
61
+ class SetMotorIP < Message
62
+ MSG = 0x53
63
+ PARAMS_LENGTH = 3
64
+
65
+ attr_reader :ip, :value
66
+
67
+ def initialize(dest = nil, ip = 1, value = nil, **kwargs)
68
+ kwargs[:dest] ||= dest
69
+ super(**kwargs)
70
+ self.ip = ip
71
+ self.value = value
72
+ end
73
+
74
+ def parse(params)
75
+ super
76
+ self.ip = to_number(params[0]) + 1
77
+ self.value = to_number(params[1..2], nillable: true)
78
+ end
79
+
80
+ def ip=(value)
81
+ raise ArgumentError, "ip must be in range 1..16 or nil" unless ip.nil? || (1..16).include?(ip)
82
+ @ip = value
83
+ end
84
+
85
+ def value=(value)
86
+ @value = value &. & 0xffff
87
+ end
88
+
89
+ def params
90
+ transform_param(ip - 1) + from_number(value, 2)
91
+ end
92
+ end
93
+
94
+ class SetMotorLimits < UnknownMessage
95
+ MSG = 0x5C
96
+ end
97
+
98
+ class SetMotorPosition < Message
99
+ MSG = 0x54
100
+ PARAMS_LENGTH = 3
101
+ TARGET_TYPE = {
102
+ up_limit: 1,
103
+ down_limit: 2,
104
+ stop: 3,
105
+ ip: 4,
106
+ next_ip_up: 5,
107
+ next_ip_down: 6,
108
+ position_pulses: 8,
109
+ jog_up_ms: 10,
110
+ jog_down_ms: 11,
111
+ jog_up_pulses: 12,
112
+ jog_down_pulses: 13,
113
+ position_percent: 16,
114
+ }.freeze
115
+
116
+ attr_reader :target_type, :target
117
+
118
+ def initialize(dest = nil, target_type = :up_limit, target = 0, **kwargs)
119
+ kwargs[:dest] ||= dest
120
+ super(**kwargs)
121
+ self.target_type = target_type
122
+ self.target = target
123
+ end
124
+
125
+ def parse(params)
126
+ super
127
+ self.target_type = TARGET_TYPE.invert[to_number(params[0])]
128
+ 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
135
+ self.target = target
136
+ end
137
+
138
+ 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)
140
+ @target_type = value
141
+ end
142
+
143
+ 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
149
+ end
150
+
151
+ def params
152
+ param = target
153
+ param = (param * 255 / 100).to_i if target_type == :position_percent
154
+ param -= 1 if target_type == :ip
155
+ transform_param(TARGET_TYPE[target_type]) + from_number(param, 2)
156
+ end
157
+ end
158
+
159
+ # the motor does not move, and just stores the new values
160
+ # flags of 1 is reverse direction, but you have to set it every time
161
+ class SetMotorSettings < UnknownMessage
162
+ MSG = 0x52
163
+ PARAMS_LENGTH = 5
164
+
165
+ attr_accessor :flags, :down_limit, :position_pulses
166
+
167
+ def initialize(dest = nil, flags = 0, down_limit = 0, position_pulses = 0, **kwargs)
168
+ kwargs[:dest] ||= dest
169
+ super(**kwargs)
170
+ self.flags = flags
171
+ self.down_limit = down_limit
172
+ self.position_pulses = position_pulses
173
+ end
174
+
175
+ def parse(params)
176
+ super
177
+ self.flags = to_number(params[0])
178
+ self.down_limit = to_number(params[1..2])
179
+ self.position_pulses = to_number(params[3..4])
180
+ end
181
+
182
+ def params
183
+ transform_param(flags) + from_number(down_limit, 2) + from_number(position_pulses, 2)
184
+ end
185
+ end
186
+
187
+ class SetNodeLabel < ::SDN::Message::SetNodeLabel
188
+ MAX_LENGTH = 32
189
+ end
190
+ end
191
+ end
192
+ end