somfy_sdn 1.0.12 → 2.1.2
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/cli/mqtt/group.rb +31 -0
- data/lib/sdn/cli/mqtt/motor.rb +103 -0
- data/lib/sdn/cli/mqtt/read.rb +156 -0
- data/lib/sdn/cli/mqtt/subscriptions.rb +156 -0
- data/lib/sdn/cli/mqtt/write.rb +93 -0
- data/lib/sdn/cli/mqtt.rb +397 -0
- data/lib/sdn/cli/provisioner.rb +234 -0
- data/lib/sdn/cli/simulator.rb +197 -0
- data/lib/sdn/client.rb +86 -0
- 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/message.rb +81 -30
- data/lib/sdn/version.rb +1 -1
- data/lib/sdn.rb +16 -1
- metadata +63 -26
- 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
@@ -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
|
@@ -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
|