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.
- checksums.yaml +4 -4
- data/bin/somfy_sdn +60 -0
- data/lib/sdn.rb +16 -1
- data/lib/sdn/cli/mqtt.rb +369 -0
- data/lib/sdn/cli/mqtt/group.rb +31 -0
- data/lib/sdn/cli/mqtt/motor.rb +103 -0
- data/lib/sdn/cli/mqtt/read.rb +154 -0
- data/lib/sdn/cli/mqtt/subscriptions.rb +156 -0
- data/lib/sdn/cli/mqtt/write.rb +93 -0
- data/lib/sdn/cli/provisioner.rb +234 -0
- data/lib/sdn/cli/simulator.rb +197 -0
- data/lib/sdn/client.rb +84 -0
- data/lib/sdn/message.rb +81 -30
- data/lib/sdn/{messages → message}/control.rb +79 -38
- data/lib/sdn/{messages → message}/get.rb +48 -40
- data/lib/sdn/{messages → message}/helpers.rb +33 -3
- data/lib/sdn/message/ilt2/get.rb +48 -0
- data/lib/sdn/message/ilt2/master_control.rb +35 -0
- data/lib/sdn/message/ilt2/post.rb +127 -0
- data/lib/sdn/message/ilt2/set.rb +192 -0
- data/lib/sdn/{messages → message}/post.rb +127 -61
- data/lib/sdn/{messages → message}/set.rb +99 -84
- data/lib/sdn/version.rb +1 -1
- metadata +53 -16
- data/bin/sdn_mqtt_bridge +0 -5
- data/lib/sdn/messages/ilt2/get.rb +0 -9
- data/lib/sdn/messages/ilt2/post.rb +0 -18
- data/lib/sdn/messages/ilt2/set.rb +0 -59
- data/lib/sdn/mqtt_bridge.rb +0 -711
@@ -1,44 +1,68 @@
|
|
1
1
|
module SDN
|
2
2
|
class Message
|
3
|
-
class
|
4
|
-
MSG =
|
5
|
-
PARAMS_LENGTH =
|
3
|
+
class PostGroupAddr < Message
|
4
|
+
MSG = 0x61
|
5
|
+
PARAMS_LENGTH = 4
|
6
6
|
|
7
|
-
|
7
|
+
def initialize(group_index = nil, group_address = nil, **kwargs)
|
8
|
+
super(**kwargs)
|
9
|
+
self.group_index = group_index
|
10
|
+
self.group_address = group_address
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :group_index, :group_address
|
8
14
|
|
9
15
|
def parse(params)
|
10
16
|
super
|
11
|
-
self.
|
12
|
-
self.
|
13
|
-
self.
|
17
|
+
self.group_index = to_number(params[0]) + 1
|
18
|
+
self.group_address = transform_param(params[1..3])
|
19
|
+
self.group_address = nil if group_address == [0, 0, 0] || group_address == [0x01, 0x01, 0xff]
|
20
|
+
end
|
21
|
+
|
22
|
+
def params
|
23
|
+
from_number(group_index - 1) + transform_param(group_address || [0, 0, 0])
|
24
|
+
end
|
25
|
+
|
26
|
+
def class_inspect
|
27
|
+
", group_index=#{group_index.inspect}, group_address=#{group_address ? print_address(group_address) : 'nil'}"
|
14
28
|
end
|
15
29
|
end
|
16
30
|
|
17
|
-
class
|
18
|
-
MSG =
|
31
|
+
class PostMotorDirection < Message
|
32
|
+
MSG = 0x32
|
33
|
+
PARAMS_LENGTH = 1
|
34
|
+
DIRECTION = { standard: 0x00, reversed: 0x01 }.freeze
|
35
|
+
|
36
|
+
attr_accessor :direction
|
37
|
+
|
38
|
+
def parse(params)
|
39
|
+
super
|
40
|
+
self.direction = DIRECTION.invert[to_number(params[0])]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class PostMotorIP < Message
|
45
|
+
MSG = 0x35
|
19
46
|
PARAMS_LENGTH = 4
|
20
|
-
STATE = { stopped: 0x00, running: 0x01, blocked: 0x02, locked: 0x03 }.freeze
|
21
|
-
DIRECTION = { down: 0x00, up: 0x01 }.freeze
|
22
|
-
SOURCE = { internal: 0x00, network: 0x01, dct: 0x02 }.freeze
|
23
|
-
CAUSE = { target_reached: 0x00,
|
24
|
-
explicit_command: 0x01,
|
25
|
-
wink: 0x02,
|
26
|
-
limits_not_set: 0x10,
|
27
|
-
ip_not_set: 0x11,
|
28
|
-
polarity_not_checked: 0x12,
|
29
|
-
in_configuration_mode: 0x13,
|
30
|
-
obstacle_detection: 0x20,
|
31
|
-
over_current_protection: 0x21,
|
32
|
-
thermal_protection: 0x22 }.freeze
|
33
47
|
|
34
|
-
attr_accessor :
|
48
|
+
attr_accessor :ip, :position_pulses, :position_percent
|
49
|
+
|
50
|
+
def initialize(ip = nil, position_pulses = nil, position_percent = nil, **kwargs)
|
51
|
+
super(**kwargs)
|
52
|
+
self.ip = ip
|
53
|
+
self.position_pulses = position_pulses
|
54
|
+
self.position_percent = position_percent
|
55
|
+
end
|
35
56
|
|
36
57
|
def parse(params)
|
37
58
|
super
|
38
|
-
self.
|
39
|
-
self.
|
40
|
-
self.
|
41
|
-
|
59
|
+
self.ip = to_number(params[0])
|
60
|
+
self.position_pulses = to_number(params[1..2], nillable: true)
|
61
|
+
self.position_percent = to_number(params[3], nillable: true)
|
62
|
+
end
|
63
|
+
|
64
|
+
def params
|
65
|
+
from_number(ip) + from_number(position_pulses, 2) + from_number(position_percent)
|
42
66
|
end
|
43
67
|
end
|
44
68
|
|
@@ -48,23 +72,45 @@ module SDN
|
|
48
72
|
|
49
73
|
attr_accessor :up_limit, :down_limit
|
50
74
|
|
75
|
+
def initialize(up_limit = nil, down_limit = nil, **kwargs)
|
76
|
+
super(**kwargs)
|
77
|
+
self.up_limit = up_limit
|
78
|
+
self.down_limit = down_limit
|
79
|
+
end
|
80
|
+
|
51
81
|
def parse(params)
|
52
82
|
super
|
53
83
|
self.up_limit = to_number(params[0..1], nillable: true)
|
54
84
|
self.down_limit = to_number(params[2..3], nillable: true)
|
55
85
|
end
|
86
|
+
|
87
|
+
def params
|
88
|
+
from_number(up_limit, 2) + from_number(down_limit, 2)
|
89
|
+
end
|
56
90
|
end
|
57
91
|
|
58
|
-
class
|
59
|
-
MSG =
|
60
|
-
PARAMS_LENGTH =
|
61
|
-
DIRECTION = { standard: 0x00, reversed: 0x01 }.freeze
|
92
|
+
class PostMotorPosition < Message
|
93
|
+
MSG = 0x0d
|
94
|
+
PARAMS_LENGTH = 5
|
62
95
|
|
63
|
-
attr_accessor :
|
96
|
+
attr_accessor :position_pulses, :position_percent, :ip
|
97
|
+
|
98
|
+
def initialize(position_pulses = nil, position_percent = nil, ip = nil, **kwargs)
|
99
|
+
super(**kwargs)
|
100
|
+
self.position_pulses = position_pulses
|
101
|
+
self.position_percent = position_percent
|
102
|
+
self.ip = ip
|
103
|
+
end
|
64
104
|
|
65
105
|
def parse(params)
|
66
106
|
super
|
67
|
-
self.
|
107
|
+
self.position_pulses = to_number(params[0..1], nillable: true)
|
108
|
+
self.position_percent = to_number(params[2], nillable: true)
|
109
|
+
self.ip = to_number(params[4], nillable: true)
|
110
|
+
end
|
111
|
+
|
112
|
+
def params
|
113
|
+
from_number(position_pulses, 2) + from_number(position_percent) + from_number(ip)
|
68
114
|
end
|
69
115
|
end
|
70
116
|
|
@@ -83,17 +129,40 @@ module SDN
|
|
83
129
|
end
|
84
130
|
end
|
85
131
|
|
86
|
-
class
|
87
|
-
MSG =
|
132
|
+
class PostMotorStatus < Message
|
133
|
+
MSG = 0x0f
|
88
134
|
PARAMS_LENGTH = 4
|
135
|
+
STATE = { stopped: 0x00, running: 0x01, blocked: 0x02, locked: 0x03 }.freeze
|
136
|
+
DIRECTION = { down: 0x00, up: 0x01 }.freeze
|
137
|
+
SOURCE = { internal: 0x00, network: 0x01, dct: 0x02 }.freeze
|
138
|
+
CAUSE = { target_reached: 0x00,
|
139
|
+
explicit_command: 0x01,
|
140
|
+
wink: 0x02,
|
141
|
+
limits_not_set: 0x10,
|
142
|
+
ip_not_set: 0x11,
|
143
|
+
polarity_not_checked: 0x12,
|
144
|
+
in_configuration_mode: 0x13,
|
145
|
+
obstacle_detection: 0x20,
|
146
|
+
over_current_protection: 0x21,
|
147
|
+
thermal_protection: 0x22 }.freeze
|
89
148
|
|
90
|
-
attr_accessor :
|
149
|
+
attr_accessor :state, :last_direction, :last_action_source, :last_action_cause
|
150
|
+
|
151
|
+
def parse(params)
|
152
|
+
super
|
153
|
+
self.state = STATE.invert[to_number(params[0])]
|
154
|
+
self.last_direction = DIRECTION.invert[to_number(params[1])]
|
155
|
+
self.last_action_source = SOURCE.invert[to_number(params[2])]
|
156
|
+
self.last_action_cause = CAUSE.invert[to_number(params[3])]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
class PostNetworkLock < UnknownMessage
|
161
|
+
MSG = 0x36
|
162
|
+
PARAMS_LENGTH = 5
|
91
163
|
|
92
164
|
def parse(params)
|
93
165
|
super
|
94
|
-
self.ip = to_number(params[0])
|
95
|
-
self.position_pulses = to_number(params[1..2], nillable: true)
|
96
|
-
self.position_percent = to_number(params[3], nillable: true)
|
97
166
|
end
|
98
167
|
end
|
99
168
|
|
@@ -102,32 +171,39 @@ module SDN
|
|
102
171
|
PARAMS_LENGTH = 0
|
103
172
|
end
|
104
173
|
|
105
|
-
class
|
106
|
-
MSG =
|
107
|
-
PARAMS_LENGTH =
|
174
|
+
class PostNodeAppVersion < Message
|
175
|
+
MSG = 0x75
|
176
|
+
PARAMS_LENGTH = 6
|
108
177
|
|
109
|
-
attr_accessor :
|
178
|
+
attr_accessor :reference, :index_letter, :index_number, :profile
|
110
179
|
|
111
180
|
def parse(params)
|
112
181
|
super
|
113
|
-
self.
|
114
|
-
self.
|
115
|
-
self.
|
116
|
-
|
117
|
-
|
118
|
-
def class_inspect
|
119
|
-
", group_index=#{group_index.inspect}, group_address=#{group_address ? print_address(group_address) : 'nil'}"
|
182
|
+
self.reference = to_number(params[0..2])
|
183
|
+
self.index_letter = to_string(params[3..3])
|
184
|
+
self.index_number = transform_param(params[4])
|
185
|
+
self.profile = transform_param(params[5])
|
120
186
|
end
|
121
187
|
end
|
122
188
|
|
123
189
|
class PostNodeLabel < Message
|
124
190
|
MSG = 0x65
|
191
|
+
MAX_LENGTH = 16
|
125
192
|
|
126
193
|
attr_accessor :label
|
127
194
|
|
195
|
+
def initialize(label = nil, **kwargs)
|
196
|
+
super(**kwargs)
|
197
|
+
self.label = label
|
198
|
+
end
|
199
|
+
|
128
200
|
def parse(params)
|
129
201
|
@label = to_string(params)
|
130
202
|
end
|
203
|
+
|
204
|
+
def params
|
205
|
+
from_string(label, self.class::MAX_LENGTH)
|
206
|
+
end
|
131
207
|
end
|
132
208
|
|
133
209
|
class PostNodeSerialNumber < Message
|
@@ -145,18 +221,8 @@ module SDN
|
|
145
221
|
end
|
146
222
|
end
|
147
223
|
|
148
|
-
class PostNodeStackVersion <
|
224
|
+
class PostNodeStackVersion < PostNodeAppVersion
|
149
225
|
MSG = 0x71
|
150
|
-
|
151
|
-
attr_accessor :params
|
152
|
-
|
153
|
-
def parse(params)
|
154
|
-
# I don't know how to interpret this yet
|
155
|
-
# I get b6 bc b2 be fc fe, and UAI+ shows 5063497A3
|
156
|
-
super
|
157
|
-
end
|
158
|
-
|
159
|
-
def msg; MSG; end
|
160
226
|
end
|
161
227
|
end
|
162
228
|
end
|
@@ -1,46 +1,67 @@
|
|
1
1
|
module SDN
|
2
2
|
class Message
|
3
|
-
class
|
4
|
-
MSG =
|
5
|
-
PARAMS_LENGTH =
|
6
|
-
|
7
|
-
TARGET = { down: 0x00, up: 0x01 }
|
3
|
+
class SetFactoryDefault < Message
|
4
|
+
MSG = 0x1f
|
5
|
+
PARAMS_LENGTH = 1
|
6
|
+
RESET = { all_settings: 0x00, group_addresses: 0x01, limits: 0x11, rotation: 0x12, rolling_speed: 0x13, ips: 0x15, locks: 0x17 }
|
8
7
|
|
9
|
-
attr_reader :
|
8
|
+
attr_reader :reset
|
10
9
|
|
11
|
-
def initialize(dest = nil,
|
12
|
-
kwargs[:dest]
|
10
|
+
def initialize(dest = nil, reset = :all_settings, **kwargs)
|
11
|
+
kwargs[:dest] ||= dest
|
13
12
|
super(**kwargs)
|
14
|
-
self.
|
15
|
-
self.target = target
|
16
|
-
self.value = value
|
13
|
+
self.reset = reset
|
17
14
|
end
|
18
15
|
|
19
16
|
def parse(params)
|
20
17
|
super
|
21
|
-
self.
|
22
|
-
self.target = TARGET.invert[to_number(params[1])]
|
23
|
-
self.value = to_number(params[2..3])
|
18
|
+
self.reset = RESET.invert[to_number(params)]
|
24
19
|
end
|
25
20
|
|
26
|
-
def
|
27
|
-
raise ArgumentError, "
|
28
|
-
@
|
21
|
+
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)
|
23
|
+
@reset = value
|
29
24
|
end
|
30
25
|
|
31
|
-
def
|
32
|
-
|
33
|
-
@target = value
|
26
|
+
def params
|
27
|
+
transform_param(RESET[reset])
|
34
28
|
end
|
29
|
+
end
|
35
30
|
|
36
|
-
|
37
|
-
|
31
|
+
class SetGroupAddr < Message
|
32
|
+
MSG = 0x51
|
33
|
+
PARAMS_LENGTH = 4
|
34
|
+
|
35
|
+
attr_reader :group_index, :group_address
|
36
|
+
|
37
|
+
def initialize(dest = nil, group_index = 1, group_address = nil, **kwargs)
|
38
|
+
kwargs[:dest] ||= dest
|
39
|
+
super(**kwargs)
|
40
|
+
self.group_index = group_index
|
41
|
+
self.group_address = group_address
|
42
|
+
end
|
43
|
+
|
44
|
+
def parse(params)
|
45
|
+
super
|
46
|
+
self.group_index = to_number(params[0]) + 1
|
47
|
+
self.group_address = transform_param(params[1..3])
|
48
|
+
end
|
49
|
+
|
50
|
+
def group_index=(value)
|
51
|
+
raise ArgumentError, "group_index is out of range" unless (1..16).include?(value)
|
52
|
+
@group_index = value
|
53
|
+
end
|
54
|
+
|
55
|
+
def group_address=(value)
|
56
|
+
@group_address = value
|
38
57
|
end
|
39
58
|
|
40
59
|
def params
|
41
|
-
|
42
|
-
|
43
|
-
|
60
|
+
transform_param(group_index - 1) + transform_param(group_address || [0, 0, 0])
|
61
|
+
end
|
62
|
+
|
63
|
+
def class_inspect
|
64
|
+
", group_index=#{group_index.inspect}, group_address=#{group_address ? print_address(group_address) : 'nil'}"
|
44
65
|
end
|
45
66
|
end
|
46
67
|
|
@@ -72,31 +93,6 @@ module SDN
|
|
72
93
|
end
|
73
94
|
end
|
74
95
|
|
75
|
-
class SetMotorRollingSpeed < Message
|
76
|
-
MSG = 0x13
|
77
|
-
PARAMS_LENGTH = 3
|
78
|
-
|
79
|
-
attr_accessor :up_speed, :down_speed, :slow_speed
|
80
|
-
def initialize(dest = nil, up_speed: nil, down_speed: nil, slow_speed: nil, **kwargs)
|
81
|
-
kwargs[:dest] ||= dest
|
82
|
-
super(**kwargs)
|
83
|
-
self.up_speed = up_speed
|
84
|
-
self.down_speed = down_speed
|
85
|
-
self.slow_speed = slow_speed
|
86
|
-
end
|
87
|
-
|
88
|
-
def parse(params)
|
89
|
-
super
|
90
|
-
self.up_speed = to_number(params[0])
|
91
|
-
self.down_speed = to_number(params[1])
|
92
|
-
self.slow_speed = to_number(params[2])
|
93
|
-
end
|
94
|
-
|
95
|
-
def params
|
96
|
-
transform_param(up_speed || 0xff) + transform_param(down_speed || 0xff) + transform_param(slow_speed || 0xff)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
96
|
class SetMotorIP < Message
|
101
97
|
MSG = 0x15
|
102
98
|
PARAMS_LENGTH = 4
|
@@ -141,74 +137,93 @@ module SDN
|
|
141
137
|
end
|
142
138
|
end
|
143
139
|
|
144
|
-
class
|
145
|
-
MSG =
|
146
|
-
PARAMS_LENGTH =
|
147
|
-
|
140
|
+
class SetMotorLimits < Message
|
141
|
+
MSG = 0x11
|
142
|
+
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 }
|
148
145
|
|
149
|
-
attr_reader :
|
146
|
+
attr_reader :type, :target, :value
|
150
147
|
|
151
|
-
def initialize(dest = nil,
|
148
|
+
def initialize(dest = nil, type = :delete, target = :up, value = nil, **kwargs)
|
152
149
|
kwargs[:dest] ||= dest
|
153
150
|
super(**kwargs)
|
154
|
-
self.
|
151
|
+
self.type = type
|
152
|
+
self.target = target
|
153
|
+
self.value = value
|
155
154
|
end
|
156
155
|
|
157
156
|
def parse(params)
|
158
157
|
super
|
159
|
-
self.
|
158
|
+
self.type = TYPE.invert[to_number(params[0])]
|
159
|
+
self.target = TARGET.invert[to_number(params[1])]
|
160
|
+
self.value = to_number(params[2..3])
|
160
161
|
end
|
161
162
|
|
162
|
-
def
|
163
|
-
raise ArgumentError, "
|
164
|
-
@
|
163
|
+
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)
|
165
|
+
@type = value
|
166
|
+
end
|
167
|
+
|
168
|
+
def target=(value)
|
169
|
+
raise ArgumentError, "target must be one of :up, :down" unless TARGET.keys.include?(value)
|
170
|
+
@target = value
|
171
|
+
end
|
172
|
+
|
173
|
+
def value=(value)
|
174
|
+
@value = value&. & 0xffff
|
165
175
|
end
|
166
176
|
|
167
177
|
def params
|
168
|
-
|
178
|
+
param = value || 0
|
179
|
+
param /= 10 if target == :jog_ms
|
180
|
+
transform_param(TYPE[type]) + transform_param(TARGET[target]) + from_number(param, 2)
|
169
181
|
end
|
170
182
|
end
|
171
183
|
|
172
|
-
class
|
173
|
-
MSG =
|
174
|
-
PARAMS_LENGTH =
|
175
|
-
|
176
|
-
attr_reader :group_index, :group_address
|
184
|
+
class SetMotorRollingSpeed < Message
|
185
|
+
MSG = 0x13
|
186
|
+
PARAMS_LENGTH = 3
|
177
187
|
|
178
|
-
|
188
|
+
attr_accessor :up_speed, :down_speed, :slow_speed
|
189
|
+
def initialize(dest = nil, up_speed: nil, down_speed: nil, slow_speed: nil, **kwargs)
|
179
190
|
kwargs[:dest] ||= dest
|
180
191
|
super(**kwargs)
|
181
|
-
self.
|
182
|
-
self.
|
192
|
+
self.up_speed = up_speed
|
193
|
+
self.down_speed = down_speed
|
194
|
+
self.slow_speed = slow_speed
|
183
195
|
end
|
184
196
|
|
185
197
|
def parse(params)
|
186
198
|
super
|
187
|
-
self.
|
188
|
-
self.
|
199
|
+
self.up_speed = to_number(params[0])
|
200
|
+
self.down_speed = to_number(params[1])
|
201
|
+
self.slow_speed = to_number(params[2])
|
189
202
|
end
|
190
203
|
|
191
|
-
def
|
192
|
-
|
193
|
-
@group_index = value
|
204
|
+
def params
|
205
|
+
transform_param(up_speed || 0xff) + transform_param(down_speed || 0xff) + transform_param(slow_speed || 0xff)
|
194
206
|
end
|
207
|
+
end
|
195
208
|
|
196
|
-
|
197
|
-
|
198
|
-
end
|
209
|
+
class SetNetworkLock < Message
|
210
|
+
MSG = 0x16
|
199
211
|
|
200
|
-
|
201
|
-
|
212
|
+
attr_accessor :locked, :priority
|
213
|
+
|
214
|
+
def parse(params)
|
215
|
+
self.locked = to_number(params[0]) == 1 ? true : false
|
216
|
+
self.priority = to_number(params[1])
|
202
217
|
end
|
203
218
|
|
204
|
-
def
|
205
|
-
|
219
|
+
def params
|
220
|
+
transform_param(locked ? 1 : 0) + transform_param(priority)
|
206
221
|
end
|
207
222
|
end
|
208
223
|
|
209
224
|
class SetNodeLabel < Message
|
210
225
|
MSG = 0x55
|
211
|
-
|
226
|
+
MAX_LENGTH = 16
|
212
227
|
|
213
228
|
attr_accessor :label
|
214
229
|
|
@@ -223,7 +238,7 @@ module SDN
|
|
223
238
|
end
|
224
239
|
|
225
240
|
def params
|
226
|
-
from_string(label,
|
241
|
+
from_string(label, self.class::MAX_LENGTH)
|
227
242
|
end
|
228
243
|
end
|
229
244
|
end
|