somfy_sdn 1.0.8 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +86 -26
- 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 +58 -21
- 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 -683
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b14639678ed3c5a54d4f8d70fd217898238aed5ccd1c81c0f3b78d04592e48b
|
4
|
+
data.tar.gz: 26d14eb134eee69523d2bca19f8ec32c63a3fc110ff7da704681569de2b8422b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3da036c72689def6022a487078bc1024ff9aa10c1b9ec7d04ce6e19a0b5b1e3956e18dcdd44272e6e7e72175afe335dc7d9f4c29785004b88ad5fda344b7a84d
|
7
|
+
data.tar.gz: c12a57173231c7be1b4b7557cb71c4c58fcc312deace5157893850d5301696ca77b1e743d6ed4e2b005c3cc532c267875f234bbe5bf92a564a17d5fa921b3ff9
|
data/bin/somfy_sdn
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'somfy_sdn'
|
4
|
+
require 'thor'
|
5
|
+
|
6
|
+
class SomfySDNCLI < Thor
|
7
|
+
class_option :verbose, type: :boolean, default: false
|
8
|
+
|
9
|
+
desc "monitor PORT", "Monitor traffic on the SDN network at PORT"
|
10
|
+
def monitor(port)
|
11
|
+
handle_global_options
|
12
|
+
|
13
|
+
sdn = SDN::Client.new(port)
|
14
|
+
|
15
|
+
loop do
|
16
|
+
sdn.receive do |message|
|
17
|
+
SDN.logger.info "Received message #{message.inspect}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "mqtt PORT MQTT_URI", "Run an MQTT bridge to control the SDN network at PORT"
|
23
|
+
option :"device-id", default: "somfy", desc: "The Homie Device ID"
|
24
|
+
option :"base-topic", default: "homie", desc: "The base Homie topic"
|
25
|
+
option :"auto-discover", type: :boolean, default: true, desc: "Do a discovery at startup"
|
26
|
+
def mqtt(port, mqtt_uri)
|
27
|
+
handle_global_options
|
28
|
+
|
29
|
+
require 'sdn/cli/mqtt'
|
30
|
+
|
31
|
+
SDN::CLI::MQTT.new(port, mqtt_uri,
|
32
|
+
device_id: options["device-id"],
|
33
|
+
base_topic: options["base-topic"],
|
34
|
+
auto_discover: options["auto-discover"])
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "provision PORT [ADDRESS]", "Provision a motor (label and set limits) at PORT"
|
38
|
+
def provision(port, address = nil)
|
39
|
+
handle_global_options
|
40
|
+
|
41
|
+
require 'sdn/cli/provisioner'
|
42
|
+
SDN::CLI::Provisioner.new(port, address)
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "simulator PORT [ADDRESS]", "Simulate a motor (for debugging purposes) at PORT"
|
46
|
+
def simulator(port, address = nil)
|
47
|
+
handle_global_options
|
48
|
+
|
49
|
+
require 'sdn/cli/simulator'
|
50
|
+
SDN::CLI::Simulator.new(port, address)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def handle_global_options
|
56
|
+
SDN.logger.level = options[:verbose] ? :debug : :info
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
SomfySDNCLI.start(ARGV)
|
data/lib/sdn.rb
CHANGED
@@ -1,6 +1,21 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
require 'sdn/client'
|
1
4
|
require 'sdn/message'
|
2
|
-
require 'sdn/mqtt_bridge'
|
3
5
|
|
4
6
|
module SDN
|
5
7
|
BROADCAST_ADDRESS = [0xff, 0xff, 0xff]
|
8
|
+
|
9
|
+
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
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
6
21
|
end
|
data/lib/sdn/cli/mqtt.rb
ADDED
@@ -0,0 +1,369 @@
|
|
1
|
+
require 'mqtt'
|
2
|
+
require 'uri'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
require 'sdn/cli/mqtt/group'
|
6
|
+
require 'sdn/cli/mqtt/motor'
|
7
|
+
require 'sdn/cli/mqtt/read'
|
8
|
+
require 'sdn/cli/mqtt/write'
|
9
|
+
require 'sdn/cli/mqtt/subscriptions'
|
10
|
+
|
11
|
+
module SDN
|
12
|
+
module CLI
|
13
|
+
class MQTT
|
14
|
+
MessageAndRetries = Struct.new(:message, :remaining_retries, :priority)
|
15
|
+
|
16
|
+
include Read
|
17
|
+
include Write
|
18
|
+
include Subscriptions
|
19
|
+
|
20
|
+
WAIT_TIME = 0.25
|
21
|
+
BROADCAST_WAIT = 5.0
|
22
|
+
|
23
|
+
attr_reader :motors, :groups
|
24
|
+
|
25
|
+
def initialize(port, mqtt_uri, device_id: "somfy", base_topic: "homie", auto_discover: true)
|
26
|
+
@base_topic = "#{base_topic}/#{device_id}"
|
27
|
+
@mqtt = ::MQTT::Client.new(mqtt_uri)
|
28
|
+
@mqtt.set_will("#{@base_topic}/$state", "lost", true)
|
29
|
+
@mqtt.connect
|
30
|
+
|
31
|
+
@motors = {}
|
32
|
+
@groups = {}
|
33
|
+
|
34
|
+
@mutex = Mutex.new
|
35
|
+
@cond = ConditionVariable.new
|
36
|
+
@queues = [[], [], []]
|
37
|
+
@response_pending = false
|
38
|
+
@broadcast_pending = false
|
39
|
+
|
40
|
+
@auto_discover = auto_discover
|
41
|
+
@motors_found = true
|
42
|
+
|
43
|
+
publish_basic_attributes
|
44
|
+
|
45
|
+
@sdn = Client.new(port)
|
46
|
+
|
47
|
+
read_thread = Thread.new { read }
|
48
|
+
write_thread = Thread.new { write }
|
49
|
+
@mqtt.get { |topic, value| handle_message(topic, value) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def publish(topic, value)
|
53
|
+
@mqtt.publish("#{@base_topic}/#{topic}", value, true, 0)
|
54
|
+
end
|
55
|
+
|
56
|
+
def subscribe(topic)
|
57
|
+
@mqtt.subscribe("#{@base_topic}/#{topic}")
|
58
|
+
end
|
59
|
+
|
60
|
+
def enqueue(message, queue = 0)
|
61
|
+
@mutex.synchronize do
|
62
|
+
queue = @queues[queue]
|
63
|
+
unless queue.include?(message)
|
64
|
+
queue.push(message)
|
65
|
+
@cond.signal
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def publish_basic_attributes
|
71
|
+
publish("$homie", "v4.0.0")
|
72
|
+
publish("$name", "Somfy SDN Network")
|
73
|
+
publish("$state", "init")
|
74
|
+
publish("$nodes", "FFFFFF")
|
75
|
+
|
76
|
+
publish("FFFFFF/$name", "Broadcast")
|
77
|
+
publish("FFFFFF/$type", "sdn")
|
78
|
+
publish("FFFFFF/$properties", "discover")
|
79
|
+
|
80
|
+
publish("FFFFFF/discover/$name", "Trigger Motor Discovery")
|
81
|
+
publish("FFFFFF/discover/$datatype", "enum")
|
82
|
+
publish("FFFFFF/discover/$format", "discover")
|
83
|
+
publish("FFFFFF/discover/$settable", "true")
|
84
|
+
publish("FFFFFF/discover/$retained", "false")
|
85
|
+
|
86
|
+
subscribe("+/discover/set")
|
87
|
+
subscribe("+/label/set")
|
88
|
+
subscribe("+/control/set")
|
89
|
+
subscribe("+/jog-ms/set")
|
90
|
+
subscribe("+/jog-pulses/set")
|
91
|
+
subscribe("+/position-pulses/set")
|
92
|
+
subscribe("+/position-percent/set")
|
93
|
+
subscribe("+/ip/set")
|
94
|
+
subscribe("+/reset/set")
|
95
|
+
subscribe("+/direction/set")
|
96
|
+
subscribe("+/up-speed/set")
|
97
|
+
subscribe("+/down-speed/set")
|
98
|
+
subscribe("+/slow-speed/set")
|
99
|
+
subscribe("+/up-limit/set")
|
100
|
+
subscribe("+/down-limit/set")
|
101
|
+
subscribe("+/groups/set")
|
102
|
+
(1..16).each do |ip|
|
103
|
+
subscribe("+/ip#{ip}-pulses/set")
|
104
|
+
subscribe("+/ip#{ip}-percent/set")
|
105
|
+
end
|
106
|
+
|
107
|
+
publish("$state", "ready")
|
108
|
+
end
|
109
|
+
|
110
|
+
def publish_motor(addr, node_type)
|
111
|
+
publish("#{addr}/$name", addr)
|
112
|
+
publish("#{addr}/$type", node_type.to_s)
|
113
|
+
properties = %w{
|
114
|
+
discover
|
115
|
+
label
|
116
|
+
state
|
117
|
+
control
|
118
|
+
jog-ms
|
119
|
+
jog-pulses
|
120
|
+
position-pulses
|
121
|
+
position-percent
|
122
|
+
ip
|
123
|
+
down-limit
|
124
|
+
groups
|
125
|
+
last-direction
|
126
|
+
} + (1..16).map { |ip| ["ip#{ip}-pulses", "ip#{ip}-percent"] }.flatten
|
127
|
+
|
128
|
+
unless node_type == :st50ilt2
|
129
|
+
properties.concat %w{
|
130
|
+
reset
|
131
|
+
last-action-source
|
132
|
+
last-action-cause
|
133
|
+
up-limit
|
134
|
+
direction
|
135
|
+
up-speed
|
136
|
+
down-speed
|
137
|
+
slow-speed
|
138
|
+
}
|
139
|
+
end
|
140
|
+
|
141
|
+
publish("#{addr}/$properties", properties.join(","))
|
142
|
+
|
143
|
+
publish("#{addr}/discover/$name", "Trigger Motor Discovery")
|
144
|
+
publish("#{addr}/discover/$datatype", "enum")
|
145
|
+
publish("#{addr}/discover/$format", "discover")
|
146
|
+
publish("#{addr}/discover/$settable", "true")
|
147
|
+
publish("#{addr}/discover/$retained", "false")
|
148
|
+
|
149
|
+
publish("#{addr}/label/$name", "Node label")
|
150
|
+
publish("#{addr}/label/$datatype", "string")
|
151
|
+
publish("#{addr}/label/$settable", "true")
|
152
|
+
|
153
|
+
publish("#{addr}/state/$name", "Current state of the motor")
|
154
|
+
publish("#{addr}/state/$datatype", "enum")
|
155
|
+
publish("#{addr}/state/$format", Message::PostMotorStatus::STATE.keys.join(','))
|
156
|
+
|
157
|
+
publish("#{addr}/control/$name", "Control motor")
|
158
|
+
publish("#{addr}/control/$datatype", "enum")
|
159
|
+
publish("#{addr}/control/$format", "up,down,stop,wink,next_ip,previous_ip,refresh")
|
160
|
+
publish("#{addr}/control/$settable", "true")
|
161
|
+
publish("#{addr}/control/$retained", "false")
|
162
|
+
|
163
|
+
publish("#{addr}/jog-ms/$name", "Jog motor by ms")
|
164
|
+
publish("#{addr}/jog-ms/$datatype", "integer")
|
165
|
+
publish("#{addr}/jog-ms/$format", "-65535:65535")
|
166
|
+
publish("#{addr}/jog-ms/$unit", "ms")
|
167
|
+
publish("#{addr}/jog-ms/$settable", "true")
|
168
|
+
publish("#{addr}/jog-ms/$retained", "false")
|
169
|
+
|
170
|
+
publish("#{addr}/jog-pulses/$name", "Jog motor by pulses")
|
171
|
+
publish("#{addr}/jog-pulses/$datatype", "integer")
|
172
|
+
publish("#{addr}/jog-pulses/$format", "-65535:65535")
|
173
|
+
publish("#{addr}/jog-pulses/$unit", "pulses")
|
174
|
+
publish("#{addr}/jog-pulses/$settable", "true")
|
175
|
+
publish("#{addr}/jog-pulses/$retained", "false")
|
176
|
+
|
177
|
+
publish("#{addr}/position-percent/$name", "Position (in %)")
|
178
|
+
publish("#{addr}/position-percent/$datatype", "integer")
|
179
|
+
publish("#{addr}/position-percent/$format", "0:100")
|
180
|
+
publish("#{addr}/position-percent/$unit", "%")
|
181
|
+
publish("#{addr}/position-percent/$settable", "true")
|
182
|
+
|
183
|
+
publish("#{addr}/position-pulses/$name", "Position from up limit (in pulses)")
|
184
|
+
publish("#{addr}/position-pulses/$datatype", "integer")
|
185
|
+
publish("#{addr}/position-pulses/$format", "0:65535")
|
186
|
+
publish("#{addr}/position-pulses/$unit", "pulses")
|
187
|
+
publish("#{addr}/position-pulses/$settable", "true")
|
188
|
+
|
189
|
+
publish("#{addr}/ip/$name", "Intermediate Position")
|
190
|
+
publish("#{addr}/ip/$datatype", "integer")
|
191
|
+
publish("#{addr}/ip/$format", "1:16")
|
192
|
+
publish("#{addr}/ip/$settable", "true")
|
193
|
+
publish("#{addr}/ip/$retained", "false") if node_type == :st50ilt2
|
194
|
+
|
195
|
+
publish("#{addr}/down-limit/$name", "Down limit")
|
196
|
+
publish("#{addr}/down-limit/$datatype", "integer")
|
197
|
+
publish("#{addr}/down-limit/$format", "0:65535")
|
198
|
+
publish("#{addr}/down-limit/$unit", "pulses")
|
199
|
+
publish("#{addr}/down-limit/$settable", "true")
|
200
|
+
|
201
|
+
publish("#{addr}/last-direction/$name", "Direction of last motion")
|
202
|
+
publish("#{addr}/last-direction/$datatype", "enum")
|
203
|
+
publish("#{addr}/last-direction/$format", Message::PostMotorStatus::DIRECTION.keys.join(','))
|
204
|
+
|
205
|
+
unless node_type == :st50ilt2
|
206
|
+
publish("#{addr}/reset/$name", "Recall factory settings")
|
207
|
+
publish("#{addr}/reset/$datatype", "enum")
|
208
|
+
publish("#{addr}/reset/$format", Message::SetFactoryDefault::RESET.keys.join(','))
|
209
|
+
publish("#{addr}/reset/$settable", "true")
|
210
|
+
publish("#{addr}/reset/$retained", "false")
|
211
|
+
|
212
|
+
publish("#{addr}/last-action-source/$name", "Source of last action")
|
213
|
+
publish("#{addr}/last-action-source/$datatype", "enum")
|
214
|
+
publish("#{addr}/last-action-source/$format", Message::PostMotorStatus::SOURCE.keys.join(','))
|
215
|
+
|
216
|
+
publish("#{addr}/last-action-cause/$name", "Cause of last action")
|
217
|
+
publish("#{addr}/last-action-cause/$datatype", "enum")
|
218
|
+
publish("#{addr}/last-action-cause/$format", Message::PostMotorStatus::CAUSE.keys.join(','))
|
219
|
+
|
220
|
+
publish("#{addr}/up-limit/$name", "Up limit (always = 0)")
|
221
|
+
publish("#{addr}/up-limit/$datatype", "integer")
|
222
|
+
publish("#{addr}/up-limit/$format", "0:65535")
|
223
|
+
publish("#{addr}/up-limit/$unit", "pulses")
|
224
|
+
publish("#{addr}/up-limit/$settable", "true")
|
225
|
+
|
226
|
+
publish("#{addr}/direction/$name", "Motor rotation direction")
|
227
|
+
publish("#{addr}/direction/$datatype", "enum")
|
228
|
+
publish("#{addr}/direction/$format", "standard,reversed")
|
229
|
+
publish("#{addr}/direction/$settable", "true")
|
230
|
+
|
231
|
+
publish("#{addr}/up-speed/$name", "Up speed")
|
232
|
+
publish("#{addr}/up-speed/$datatype", "integer")
|
233
|
+
publish("#{addr}/up-speed/$format", "6:28")
|
234
|
+
publish("#{addr}/up-speed/$unit", "RPM")
|
235
|
+
publish("#{addr}/up-speed/$settable", "true")
|
236
|
+
|
237
|
+
publish("#{addr}/down-speed/$name", "Down speed, always = Up speed")
|
238
|
+
publish("#{addr}/down-speed/$datatype", "integer")
|
239
|
+
publish("#{addr}/down-speed/$format", "6:28")
|
240
|
+
publish("#{addr}/down-speed/$unit", "RPM")
|
241
|
+
publish("#{addr}/down-speed/$settable", "true")
|
242
|
+
|
243
|
+
publish("#{addr}/slow-speed/$name", "Slow speed")
|
244
|
+
publish("#{addr}/slow-speed/$datatype", "integer")
|
245
|
+
publish("#{addr}/slow-speed/$format", "6:28")
|
246
|
+
publish("#{addr}/slow-speed/$unit", "RPM")
|
247
|
+
publish("#{addr}/slow-speed/$settable", "true")
|
248
|
+
end
|
249
|
+
|
250
|
+
publish("#{addr}/groups/$name", "Group Memberships (comma separated, address must start 0101xx)")
|
251
|
+
publish("#{addr}/groups/$datatype", "string")
|
252
|
+
publish("#{addr}/groups/$settable", "true")
|
253
|
+
|
254
|
+
(1..16).each do |ip|
|
255
|
+
publish("#{addr}/ip#{ip}-pulses/$name", "Intermediate Position #{ip}")
|
256
|
+
publish("#{addr}/ip#{ip}-pulses/$datatype", "integer")
|
257
|
+
publish("#{addr}/ip#{ip}-pulses/$format", "0:65535")
|
258
|
+
publish("#{addr}/ip#{ip}-pulses/$unit", "pulses")
|
259
|
+
publish("#{addr}/ip#{ip}-pulses/$settable", "true")
|
260
|
+
|
261
|
+
publish("#{addr}/ip#{ip}-percent/$name", "Intermediate Position #{ip}")
|
262
|
+
publish("#{addr}/ip#{ip}-percent/$datatype", "integer")
|
263
|
+
publish("#{addr}/ip#{ip}-percent/$format", "0:100")
|
264
|
+
publish("#{addr}/ip#{ip}-percent/$unit", "%")
|
265
|
+
publish("#{addr}/ip#{ip}-percent/$settable", "true")
|
266
|
+
end
|
267
|
+
|
268
|
+
motor = Motor.new(self, addr, node_type)
|
269
|
+
@motors[addr] = motor
|
270
|
+
publish("$nodes", (["FFFFFF"] + @motors.keys.sort + @groups.keys.sort).join(","))
|
271
|
+
|
272
|
+
sdn_addr = Message.parse_address(addr)
|
273
|
+
@mutex.synchronize do
|
274
|
+
@queues[2].push(MessageAndRetries.new(Message::GetNodeLabel.new(sdn_addr), 5, 2))
|
275
|
+
case node_type
|
276
|
+
when :st30
|
277
|
+
@queues[2].push(MessageAndRetries.new(Message::GetMotorStatus.new(sdn_addr), 5, 2))
|
278
|
+
@queues[2].push(MessageAndRetries.new(Message::GetMotorLimits.new(sdn_addr), 5, 2))
|
279
|
+
@queues[2].push(MessageAndRetries.new(Message::GetMotorDirection.new(sdn_addr), 5, 2))
|
280
|
+
@queues[2].push(MessageAndRetries.new(Message::GetMotorRollingSpeed.new(sdn_addr), 5, 2))
|
281
|
+
(1..16).each { |ip| @queues[2].push(MessageAndRetries.new(Message::GetMotorIP.new(sdn_addr, ip), 5, 2)) }
|
282
|
+
when :st50ilt2
|
283
|
+
@queues[2].push(MessageAndRetries.new(Message::ILT2::GetMotorSettings.new(sdn_addr), 5, 2))
|
284
|
+
@queues[2].push(MessageAndRetries.new(Message::ILT2::GetMotorPosition.new(sdn_addr), 5, 2))
|
285
|
+
(1..16).each { |ip| @queues[2].push(MessageAndRetries.new(Message::ILT2::GetMotorIP.new(sdn_addr, ip), 5, 2)) }
|
286
|
+
end
|
287
|
+
(1..16).each { |g| @queues[2].push(MessageAndRetries.new(Message::GetGroupAddr.new(sdn_addr, g), 5, 2)) }
|
288
|
+
|
289
|
+
@cond.signal
|
290
|
+
end
|
291
|
+
|
292
|
+
motor
|
293
|
+
end
|
294
|
+
|
295
|
+
def touch_group(group_addr)
|
296
|
+
group = @groups[Message.print_address(group_addr).gsub('.', '')]
|
297
|
+
group&.publish(:motors, group.motors_string)
|
298
|
+
end
|
299
|
+
|
300
|
+
def add_group(addr)
|
301
|
+
addr = addr.gsub('.', '')
|
302
|
+
group = @groups[addr]
|
303
|
+
return group if group
|
304
|
+
|
305
|
+
publish("#{addr}/$name", addr)
|
306
|
+
publish("#{addr}/$type", "Shade Group")
|
307
|
+
publish("#{addr}/$properties", "discover,control,jog-ms,jog-pulses,position-pulses,position-percent,ip,reset,state,last-direction,motors")
|
308
|
+
|
309
|
+
publish("#{addr}/discover/$name", "Trigger Motor Discovery")
|
310
|
+
publish("#{addr}/discover/$datatype", "enum")
|
311
|
+
publish("#{addr}/discover/$format", "discover")
|
312
|
+
publish("#{addr}/discover/$settable", "true")
|
313
|
+
publish("#{addr}/discover/$retained", "false")
|
314
|
+
|
315
|
+
publish("#{addr}/control/$name", "Control motors")
|
316
|
+
publish("#{addr}/control/$datatype", "enum")
|
317
|
+
publish("#{addr}/control/$format", "up,down,stop,wink,next_ip,previous_ip,refresh")
|
318
|
+
publish("#{addr}/control/$settable", "true")
|
319
|
+
publish("#{addr}/control/$retained", "false")
|
320
|
+
|
321
|
+
publish("#{addr}/jog-ms/$name", "Jog motors by ms")
|
322
|
+
publish("#{addr}/jog-ms/$datatype", "integer")
|
323
|
+
publish("#{addr}/jog-ms/$format", "-65535:65535")
|
324
|
+
publish("#{addr}/jog-ms/$unit", "ms")
|
325
|
+
publish("#{addr}/jog-ms/$settable", "true")
|
326
|
+
publish("#{addr}/jog-ms/$retained", "false")
|
327
|
+
|
328
|
+
publish("#{addr}/jog-pulses/$name", "Jog motors by pulses")
|
329
|
+
publish("#{addr}/jog-pulses/$datatype", "integer")
|
330
|
+
publish("#{addr}/jog-pulses/$format", "-65535:65535")
|
331
|
+
publish("#{addr}/jog-pulses/$unit", "pulses")
|
332
|
+
publish("#{addr}/jog-pulses/$settable", "true")
|
333
|
+
publish("#{addr}/jog-pulses/$retained", "false")
|
334
|
+
|
335
|
+
publish("#{addr}/position-pulses/$name", "Position from up limit (in pulses)")
|
336
|
+
publish("#{addr}/position-pulses/$datatype", "integer")
|
337
|
+
publish("#{addr}/position-pulses/$format", "0:65535")
|
338
|
+
publish("#{addr}/position-pulses/$unit", "pulses")
|
339
|
+
publish("#{addr}/position-pulses/$settable", "true")
|
340
|
+
|
341
|
+
publish("#{addr}/position-percent/$name", "Position (in %)")
|
342
|
+
publish("#{addr}/position-percent/$datatype", "integer")
|
343
|
+
publish("#{addr}/position-percent/$format", "0:100")
|
344
|
+
publish("#{addr}/position-percent/$unit", "%")
|
345
|
+
publish("#{addr}/position-percent/$settable", "true")
|
346
|
+
|
347
|
+
publish("#{addr}/ip/$name", "Intermediate Position")
|
348
|
+
publish("#{addr}/ip/$datatype", "integer")
|
349
|
+
publish("#{addr}/ip/$format", "1:16")
|
350
|
+
publish("#{addr}/ip/$settable", "true")
|
351
|
+
|
352
|
+
publish("#{addr}/state/$name", "State of the motors")
|
353
|
+
publish("#{addr}/state/$datatype", "enum")
|
354
|
+
publish("#{addr}/state/$format", Message::PostMotorStatus::STATE.keys.join(',') + ",mixed")
|
355
|
+
|
356
|
+
publish("#{addr}/last-direction/$name", "Direction of last motion")
|
357
|
+
publish("#{addr}/last-direction/$datatype", "enum")
|
358
|
+
publish("#{addr}/last-direction/$format", Message::PostMotorStatus::DIRECTION.keys.join(',') + ",mixed")
|
359
|
+
|
360
|
+
publish("#{addr}/motors/$name", "Comma separated motor addresses that are members of this group")
|
361
|
+
publish("#{addr}/motors/$datatype", "string")
|
362
|
+
|
363
|
+
group = @groups[addr] = Group.new(self, addr)
|
364
|
+
publish("$nodes", (["FFFFFF"] + @motors.keys.sort + @groups.keys.sort).join(","))
|
365
|
+
group
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|