somfy_sdn 1.0.12 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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