asterism-zenoh 0.3.0 → 0.4.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/CHANGELOG.md +89 -0
- data/README.md +69 -18
- data/docs/feature_coverage.md +5 -4
- data/ext/asterism_zenoh/zenoh.c +136 -58
- data/lib/asterism/zenoh/common.rb +221 -0
- data/lib/asterism/zenoh/cruby.rb +128 -0
- data/lib/asterism/zenoh/values.rb +13 -6
- data/lib/asterism/zenoh/version.rb +1 -1
- data/lib/asterism/zenoh.rb +2 -0
- metadata +5 -2
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# The part of Asterism::Zenoh written in Ruby that is the same on every
|
|
2
|
+
# backend: this file is byte for byte the same as mrblib/common.rb of the
|
|
3
|
+
# mruby / PicoRuby binding (picoruby-asterism-zenoh). It runs on CRuby,
|
|
4
|
+
# mruby and PicoRuby, so it keeps to what all three have (no Regexp, no
|
|
5
|
+
# Data, while loops where a block would be called from C).
|
|
6
|
+
#
|
|
7
|
+
# What it adds on top of the C binding:
|
|
8
|
+
# - the deprecation helper (Asterism.deprecated, Asterism.deprecations=),
|
|
9
|
+
# shared by every Asterism gem, and Asterism.warn_once (lost replies);
|
|
10
|
+
# - the time limit in seconds (timeout:) next to milliseconds (timeout_ms:)
|
|
11
|
+
# on get and liveliness_get, and keywords for the positional optionals;
|
|
12
|
+
# - connection_count's old name peers, and the one-argument Query#reply
|
|
13
|
+
# that will change in 1.0, both with a deprecation warning;
|
|
14
|
+
# - Error#code and the readable constant names.
|
|
15
|
+
module Asterism
|
|
16
|
+
# The root of every Asterism error (the binding's C code defines it first).
|
|
17
|
+
class Error < StandardError; end
|
|
18
|
+
|
|
19
|
+
# Raised instead of a warning when Asterism.deprecations is :raise.
|
|
20
|
+
class DeprecationError < Error; end
|
|
21
|
+
|
|
22
|
+
# How a deprecated call is reported: :warn (once per name, the default),
|
|
23
|
+
# :raise (DeprecationError; for CI) or :silent. The environment variable
|
|
24
|
+
# ASTERISM_DEPRECATIONS (warn / raise / silent) sets the default.
|
|
25
|
+
def self.deprecations
|
|
26
|
+
if @deprecations.nil?
|
|
27
|
+
mode = nil
|
|
28
|
+
begin
|
|
29
|
+
mode = ENV["ASTERISM_DEPRECATIONS"] if Object.const_defined?(:ENV)
|
|
30
|
+
rescue StandardError
|
|
31
|
+
mode = nil
|
|
32
|
+
end
|
|
33
|
+
@deprecations = (mode == "raise" || mode == "silent") ? mode.to_sym : :warn
|
|
34
|
+
end
|
|
35
|
+
@deprecations
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.deprecations=(mode)
|
|
39
|
+
m = mode.to_s.to_sym
|
|
40
|
+
raise ArgumentError, "deprecations must be :warn, :raise or :silent" unless m == :warn || m == :raise || m == :silent
|
|
41
|
+
@deprecations = m
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Reports that `old` is deprecated in favour of `instead`: warns once per
|
|
45
|
+
# `old` per process (per VM on the boards), raises DeprecationError, or
|
|
46
|
+
# stays silent (Asterism.deprecations). `why` is an optional sentence.
|
|
47
|
+
def self.deprecated(old, instead, why = nil)
|
|
48
|
+
mode = deprecations
|
|
49
|
+
return nil if mode == :silent
|
|
50
|
+
msg = "asterism: #{old} is deprecated and goes away in 1.0; use #{instead}"
|
|
51
|
+
msg = "#{msg} (#{why})" if why
|
|
52
|
+
raise DeprecationError, msg if mode == :raise
|
|
53
|
+
@deprecated_seen ||= {}
|
|
54
|
+
return nil if @deprecated_seen[old]
|
|
55
|
+
@deprecated_seen[old] = true
|
|
56
|
+
if respond_to?(:warn, true)
|
|
57
|
+
warn(msg)
|
|
58
|
+
else
|
|
59
|
+
puts(msg)
|
|
60
|
+
end
|
|
61
|
+
nil
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Warns msg once for obj (a Get, a watch, a wrapper): later calls for
|
|
65
|
+
# the same object say nothing. For losses the application did not ask
|
|
66
|
+
# for, such as replies dropped from a full queue. Returns true when it
|
|
67
|
+
# warned. Ruby's warn stays silent with $VERBOSE = nil.
|
|
68
|
+
def self.warn_once(obj, msg)
|
|
69
|
+
# By object_id: not every mruby build has instance_variable_get. The
|
|
70
|
+
# objects warned about are few; the table is emptied past 256.
|
|
71
|
+
@warned_once ||= {}
|
|
72
|
+
id = obj.object_id
|
|
73
|
+
return false if @warned_once[id]
|
|
74
|
+
@warned_once = {} if @warned_once.size >= 256
|
|
75
|
+
@warned_once[id] = true
|
|
76
|
+
if respond_to?(:warn, true)
|
|
77
|
+
warn(msg)
|
|
78
|
+
else
|
|
79
|
+
puts(msg)
|
|
80
|
+
end
|
|
81
|
+
true
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# The names warned about so far (for tests). @api private
|
|
85
|
+
def self.deprecated_names
|
|
86
|
+
(@deprecated_seen || {}).keys
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Forget the names warned about (for tests). @api private
|
|
90
|
+
def self.reset_deprecations
|
|
91
|
+
@deprecated_seen = {}
|
|
92
|
+
nil
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# A time limit in milliseconds from the ways a call may take it: timeout:
|
|
96
|
+
# (seconds), timeout_ms: or the old positional milliseconds (deprecated).
|
|
97
|
+
# Giving more than one raises ArgumentError. @api private
|
|
98
|
+
def self.time_ms(where, timeout, timeout_ms, positional, default_ms)
|
|
99
|
+
given = 0
|
|
100
|
+
given += 1 unless timeout.nil?
|
|
101
|
+
given += 1 unless timeout_ms.nil?
|
|
102
|
+
given += 1 unless positional.nil?
|
|
103
|
+
raise ArgumentError, "#{where}: give the time limit once (timeout: in seconds, or timeout_ms:)" if given > 1
|
|
104
|
+
unless positional.nil?
|
|
105
|
+
if positional.is_a?(Float)
|
|
106
|
+
deprecated("#{where} with a Float as the positional time limit", "timeout: (seconds)",
|
|
107
|
+
"the positional time limit is milliseconds, so #{positional} waits #{positional.to_i} ms; " \
|
|
108
|
+
"a Float there is usually meant as seconds")
|
|
109
|
+
else
|
|
110
|
+
deprecated("#{where} with the time limit as a positional argument", "timeout: (seconds) or timeout_ms:")
|
|
111
|
+
end
|
|
112
|
+
return positional.to_i
|
|
113
|
+
end
|
|
114
|
+
unless timeout_ms.nil?
|
|
115
|
+
raise TypeError, "#{where}: timeout_ms: must be a number" unless timeout_ms.is_a?(Numeric)
|
|
116
|
+
return timeout_ms.round
|
|
117
|
+
end
|
|
118
|
+
return default_ms if timeout.nil?
|
|
119
|
+
raise TypeError, "#{where}: timeout: must be a number of seconds" unless timeout.is_a?(Numeric)
|
|
120
|
+
ms = (timeout * 1000).round
|
|
121
|
+
raise ArgumentError, "#{where}: timeout: #{timeout} s is less than 1 ms" if ms < 1
|
|
122
|
+
ms
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# A queue depth given positionally (kept) or as depth: (not both).
|
|
126
|
+
# @api private
|
|
127
|
+
def self.depth_of(where, args, depth, default)
|
|
128
|
+
raise ArgumentError, "#{where}: too many arguments" if args.size > 1
|
|
129
|
+
raise ArgumentError, "#{where}: give the depth once (positional or depth:)" if args.size == 1 && !depth.nil?
|
|
130
|
+
return args[0] if args.size == 1
|
|
131
|
+
depth.nil? ? default : depth
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
module Zenoh
|
|
135
|
+
# The readable name of PEER: whether this build has peer mode.
|
|
136
|
+
PEER_SUPPORTED = PEER
|
|
137
|
+
# The default time limit of get and liveliness_get, in seconds.
|
|
138
|
+
DEFAULT_TIMEOUT = 2.0
|
|
139
|
+
|
|
140
|
+
class Error
|
|
141
|
+
# The result code of zenoh-c / zenoh-pico (a negative Integer) when the
|
|
142
|
+
# failure came with one, else nil.
|
|
143
|
+
attr_reader :code
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
class Session
|
|
147
|
+
alias_method :__asterism_get, :get
|
|
148
|
+
alias_method :__asterism_liveliness_get, :liveliness_get
|
|
149
|
+
alias_method :__asterism_subscribe, :subscribe
|
|
150
|
+
alias_method :__asterism_queryable, :queryable
|
|
151
|
+
alias_method :__asterism_liveliness_watch, :liveliness_watch
|
|
152
|
+
|
|
153
|
+
# get(key, timeout: 2.0, params: nil, payload: nil, attachment: nil,
|
|
154
|
+
# target: :all, consolidation: :none, depth: DEFAULT_GET_DEPTH,
|
|
155
|
+
# ...) -> Get.
|
|
156
|
+
# timeout: seconds; or timeout_ms:. depth: the replies kept until
|
|
157
|
+
# taken (past it the oldest go; Get#dropped counts them). The old
|
|
158
|
+
# positional form get(key, timeout_ms, params, payload) still works
|
|
159
|
+
# (deprecated).
|
|
160
|
+
def get(key, *args, timeout: nil, timeout_ms: nil, params: nil, payload: nil, **opts)
|
|
161
|
+
raise ArgumentError, "get: wrong number of arguments (given #{args.size + 1}, expected 1..4)" if args.size > 3
|
|
162
|
+
raise ArgumentError, "get: params given twice" if args.size > 1 && !params.nil?
|
|
163
|
+
raise ArgumentError, "get: payload given twice" if args.size > 2 && !payload.nil?
|
|
164
|
+
ms = ::Asterism.time_ms("Session#get", timeout, timeout_ms, args[0], 2000)
|
|
165
|
+
params = args[1] if args.size > 1
|
|
166
|
+
payload = args[2] if args.size > 2
|
|
167
|
+
__asterism_get(key, ms, params, payload, **opts)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# liveliness_get(key, timeout: 2.0, depth: DEFAULT_GET_DEPTH) -> Get
|
|
171
|
+
# (or timeout_ms:).
|
|
172
|
+
def liveliness_get(key, *args, timeout: nil, timeout_ms: nil, depth: nil)
|
|
173
|
+
raise ArgumentError, "liveliness_get: wrong number of arguments (given #{args.size + 1}, expected 1..2)" if args.size > 1
|
|
174
|
+
ms = ::Asterism.time_ms("Session#liveliness_get", timeout, timeout_ms, args[0], 2000)
|
|
175
|
+
__asterism_liveliness_get(key, ms, depth: depth.nil? ? DEFAULT_GET_DEPTH : depth)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# subscribe(key, depth = 16) or subscribe(key, depth: 16).
|
|
179
|
+
def subscribe(key, *args, depth: nil)
|
|
180
|
+
__asterism_subscribe(key, ::Asterism.depth_of("subscribe", args, depth, DEFAULT_DEPTH))
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# queryable(key, depth = 16, complete: false) or with depth:.
|
|
184
|
+
def queryable(key, *args, depth: nil, **opts)
|
|
185
|
+
__asterism_queryable(key, ::Asterism.depth_of("queryable", args, depth, DEFAULT_DEPTH), **opts)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# liveliness_watch(key, depth = DEFAULT_WATCH_DEPTH) or with depth:.
|
|
189
|
+
# The tokens alive when it is declared come in one burst.
|
|
190
|
+
def liveliness_watch(key, *args, depth: nil)
|
|
191
|
+
__asterism_liveliness_watch(key, ::Asterism.depth_of("liveliness_watch", args, depth, DEFAULT_WATCH_DEPTH))
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# Deprecated: the number of connections is connection_count.
|
|
195
|
+
def peers
|
|
196
|
+
::Asterism.deprecated("Session#peers", "Session#connection_count",
|
|
197
|
+
"for a client session it counts routers, not peers")
|
|
198
|
+
connection_count
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
class Query
|
|
203
|
+
alias_method :__asterism_reply, :reply
|
|
204
|
+
|
|
205
|
+
# reply(payload) answers on the query's key today. From 1.0 it answers
|
|
206
|
+
# on the queryable's own key when that key has no wildcard (as the
|
|
207
|
+
# CRuby block API does); a reply that would change warns now.
|
|
208
|
+
def reply(*args, **kw)
|
|
209
|
+
if args.size == 1
|
|
210
|
+
own = @asterism_queryable_key
|
|
211
|
+
if own && !own.include?("*") && !own.include?("$") && own != key
|
|
212
|
+
::Asterism.deprecated("Query#reply(payload) for a query whose key differs from the queryable's",
|
|
213
|
+
"q.reply(key, payload)",
|
|
214
|
+
"from 1.0 a reply with only a payload answers on the queryable's own key")
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
__asterism_reply(*args, **kw)
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# What only the CRuby binding (zenoh-c) adds in Ruby: the backend
|
|
2
|
+
# constants, Session.open with a block and connect_timeout:, seconds and
|
|
3
|
+
# keywords on the CRuby-only calls (querier, advanced subscriber,
|
|
4
|
+
# listeners), the long reply names, and scout's argument check.
|
|
5
|
+
module Asterism
|
|
6
|
+
module Zenoh
|
|
7
|
+
# Which Zenoh implementation is underneath (:zenoh_pico on the boards).
|
|
8
|
+
BACKEND = :zenoh_c
|
|
9
|
+
# Its version (C_VERSION here, PICO_VERSION on the boards).
|
|
10
|
+
BACKEND_VERSION = C_VERSION
|
|
11
|
+
|
|
12
|
+
class Session
|
|
13
|
+
class << self
|
|
14
|
+
alias_method :__asterism_open, :open
|
|
15
|
+
|
|
16
|
+
# Session.open(locator = nil, mode:, listen:, scouting:,
|
|
17
|
+
# timestamping:, config:, config_file:, connect_timeout:) -> Session.
|
|
18
|
+
# connect_timeout: seconds to wait for a router or peer
|
|
19
|
+
# (CONNECT_TIMEOUT_MS by default; zenoh's connect/timeout_ms). With a
|
|
20
|
+
# block: yields the session, closes it when the block ends (also on
|
|
21
|
+
# an exception) and returns the block's value.
|
|
22
|
+
def open(locator = nil, connect_timeout: nil, **opts)
|
|
23
|
+
unless connect_timeout.nil?
|
|
24
|
+
ms = ::Asterism.time_ms("Session.open connect_timeout:", connect_timeout, nil, nil, CONNECT_TIMEOUT_MS)
|
|
25
|
+
cfg = opts[:config]
|
|
26
|
+
if cfg.nil?
|
|
27
|
+
opts[:config] = { "connect/timeout_ms" => ms }
|
|
28
|
+
elsif cfg.is_a?(Hash)
|
|
29
|
+
if cfg.key?("connect/timeout_ms") || cfg.key?(:"connect/timeout_ms")
|
|
30
|
+
raise ArgumentError, "connect_timeout: and config: {\"connect/timeout_ms\" => ...} given together"
|
|
31
|
+
end
|
|
32
|
+
opts[:config] = cfg.merge("connect/timeout_ms" => ms)
|
|
33
|
+
else
|
|
34
|
+
raise ArgumentError, "connect_timeout: cannot be added to a config String; set connect/timeout_ms in it"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
s = __asterism_open(locator, **opts)
|
|
38
|
+
return s unless block_given?
|
|
39
|
+
begin
|
|
40
|
+
yield s
|
|
41
|
+
ensure
|
|
42
|
+
s.close
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
alias_method :__asterism_querier, :querier
|
|
48
|
+
alias_method :__asterism_advanced_subscriber, :advanced_subscriber
|
|
49
|
+
alias_method :__asterism_transport_events, :transport_events
|
|
50
|
+
alias_method :__asterism_link_events, :link_events
|
|
51
|
+
|
|
52
|
+
# querier(key, timeout: 2.0, ...) -> Querier (or timeout_ms:).
|
|
53
|
+
def querier(key, timeout: nil, timeout_ms: nil, **opts)
|
|
54
|
+
ms = ::Asterism.time_ms("Session#querier", timeout, timeout_ms, nil, nil)
|
|
55
|
+
opts[:timeout_ms] = ms unless ms.nil?
|
|
56
|
+
__asterism_querier(key, **opts)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# advanced_subscriber(key, depth = 16, query_timeout: seconds, ...)
|
|
60
|
+
# (or depth:, query_timeout_ms:).
|
|
61
|
+
def advanced_subscriber(key, *args, depth: nil, query_timeout: nil, query_timeout_ms: nil, **opts)
|
|
62
|
+
d = ::Asterism.depth_of("advanced_subscriber", args, depth, 16)
|
|
63
|
+
ms = ::Asterism.time_ms("Session#advanced_subscriber query_timeout", query_timeout, query_timeout_ms, nil, nil)
|
|
64
|
+
opts[:query_timeout_ms] = ms unless ms.nil?
|
|
65
|
+
__asterism_advanced_subscriber(key, d, **opts)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# transport_events(depth = 16, history: false) or with depth:.
|
|
69
|
+
def transport_events(*args, depth: nil, **opts)
|
|
70
|
+
__asterism_transport_events(::Asterism.depth_of("transport_events", args, depth, 16), **opts)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# link_events(depth = 16, history: false) or with depth:.
|
|
74
|
+
def link_events(*args, depth: nil, **opts)
|
|
75
|
+
__asterism_link_events(::Asterism.depth_of("link_events", args, depth, 16), **opts)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# matching_listener(depth = 16) or matching_listener(depth: 16).
|
|
80
|
+
module MatchingDepth
|
|
81
|
+
def matching_listener(*args, depth: nil)
|
|
82
|
+
super(::Asterism.depth_of("matching_listener", args, depth, 16))
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
Publisher.prepend(MatchingDepth)
|
|
86
|
+
AdvancedPublisher.prepend(MatchingDepth)
|
|
87
|
+
|
|
88
|
+
class Querier
|
|
89
|
+
prepend MatchingDepth
|
|
90
|
+
alias_method :__asterism_get, :get
|
|
91
|
+
|
|
92
|
+
# get(params: nil, payload: nil, attachment:, encoding:, depth:) -> Get; the
|
|
93
|
+
# positional get(params, payload) still works.
|
|
94
|
+
def get(*args, params: nil, payload: nil, **opts)
|
|
95
|
+
raise ArgumentError, "get: wrong number of arguments (given #{args.size}, expected 0..2)" if args.size > 2
|
|
96
|
+
raise ArgumentError, "get: params given twice" if args.size > 0 && !params.nil?
|
|
97
|
+
raise ArgumentError, "get: payload given twice" if args.size > 1 && !payload.nil?
|
|
98
|
+
params = args[0] if args.size > 0
|
|
99
|
+
payload = args[1] if args.size > 1
|
|
100
|
+
__asterism_get(params, payload, **opts)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
class AdvancedSubscriber
|
|
105
|
+
alias_method :__asterism_miss_listener, :miss_listener
|
|
106
|
+
alias_method :__asterism_detect_publishers, :detect_publishers
|
|
107
|
+
|
|
108
|
+
def miss_listener(*args, depth: nil)
|
|
109
|
+
__asterism_miss_listener(::Asterism.depth_of("miss_listener", args, depth, 16))
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def detect_publishers(*args, depth: nil, **opts)
|
|
113
|
+
__asterism_detect_publishers(::Asterism.depth_of("detect_publishers", args, depth, 16), **opts)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
class Query
|
|
118
|
+
# The spelled-out names of reply_err and reply_del (those stay).
|
|
119
|
+
def reply_error(payload, **opts)
|
|
120
|
+
reply_err(payload, **opts)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def reply_delete(key = nil, **opts)
|
|
124
|
+
reply_del(key, **opts)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -26,6 +26,7 @@ module Asterism
|
|
|
26
26
|
|
|
27
27
|
def put? = kind == :put
|
|
28
28
|
def delete? = kind == :delete
|
|
29
|
+
def express? = express
|
|
29
30
|
|
|
30
31
|
def to_s
|
|
31
32
|
"#{key}: #{payload}"
|
|
@@ -59,22 +60,28 @@ module Asterism
|
|
|
59
60
|
Hello = Data.define(:zid, :whatami, :locators)
|
|
60
61
|
|
|
61
62
|
# A connection to another peer or router (Session#transports).
|
|
62
|
-
Transport = Data.define(:zid, :whatami, :qos, :multicast)
|
|
63
|
+
Transport = Data.define(:zid, :whatami, :qos, :multicast) do
|
|
64
|
+
def multicast? = multicast
|
|
65
|
+
end
|
|
63
66
|
|
|
64
67
|
# A transport that appeared (kind :added) or went (:removed), from
|
|
65
68
|
# Session#transport_events.
|
|
66
69
|
TransportEvent = Data.define(:kind, :zid, :whatami, :qos, :multicast) do
|
|
70
|
+
def multicast? = multicast
|
|
67
71
|
def added? = kind == :added
|
|
68
72
|
def removed? = kind == :removed
|
|
69
73
|
end
|
|
70
74
|
|
|
71
75
|
# A link (one connection of a transport; Session#links).
|
|
72
|
-
Link = Data.define(:zid, :src, :dst, :mtu, :streamed, :reliability, :interfaces, :group, :auth_identifier)
|
|
76
|
+
Link = Data.define(:zid, :src, :dst, :mtu, :streamed, :reliability, :interfaces, :group, :auth_identifier) do
|
|
77
|
+
def streamed? = streamed
|
|
78
|
+
end
|
|
73
79
|
|
|
74
80
|
# A link that opened (kind :added) or closed (:removed), from
|
|
75
81
|
# Session#link_events.
|
|
76
82
|
LinkEvent = Data.define(:kind, :zid, :src, :dst, :mtu, :streamed, :reliability, :interfaces, :group,
|
|
77
83
|
:auth_identifier) do
|
|
84
|
+
def streamed? = streamed
|
|
78
85
|
def added? = kind == :added
|
|
79
86
|
def removed? = kind == :removed
|
|
80
87
|
end
|
|
@@ -87,18 +94,18 @@ module Asterism
|
|
|
87
94
|
SCOUT_WHAT = { router: 1, peer: 2, client: 4 }.freeze
|
|
88
95
|
|
|
89
96
|
# Looks for routers and / or peers by multicast scouting for timeout
|
|
90
|
-
# seconds (or timeout_ms milliseconds) and returns what
|
|
91
|
-
# Array of Hello. what: :router, :peer, :client, an Array of them, or
|
|
97
|
+
# seconds (or timeout_ms milliseconds; not both) and returns what
|
|
98
|
+
# answered, as an Array of Hello. what: :router, :peer, :client, an Array of them, or
|
|
92
99
|
# :all. config: a Hash of zenoh configuration keys, as for
|
|
93
100
|
# Session.open (e.g. {"scouting/multicast/interface" => "eth0"}).
|
|
94
101
|
# Multicast must be allowed on the network (it often is not in
|
|
95
102
|
# containers and VPNs).
|
|
96
|
-
def self.scout(what: %i[router peer], timeout:
|
|
103
|
+
def self.scout(what: %i[router peer], timeout: nil, timeout_ms: nil, config: nil)
|
|
97
104
|
kinds = what == :all ? SCOUT_WHAT.keys : Array(what)
|
|
98
105
|
mask = kinds.sum do |k|
|
|
99
106
|
SCOUT_WHAT.fetch(k.to_sym) { raise ArgumentError, "what must be :router, :peer, :client or :all" }
|
|
100
107
|
end
|
|
101
|
-
ms =
|
|
108
|
+
ms = ::Asterism.time_ms("Asterism::Zenoh.scout", timeout, timeout_ms, nil, 1000)
|
|
102
109
|
_scout(mask, ms, config)
|
|
103
110
|
end
|
|
104
111
|
end
|
data/lib/asterism/zenoh.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: asterism-zenoh
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Katsuhiko Kageyama
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Sessions, put / subscribe, get / queryable, liveliness and attachments,
|
|
14
14
|
received by polling. The same Ruby API as Asterism's mruby / PicoRuby binding, plus
|
|
@@ -22,6 +22,7 @@ extensions:
|
|
|
22
22
|
- ext/asterism_zenoh/extconf.rb
|
|
23
23
|
extra_rdoc_files: []
|
|
24
24
|
files:
|
|
25
|
+
- CHANGELOG.md
|
|
25
26
|
- LICENSE
|
|
26
27
|
- README.md
|
|
27
28
|
- ZENOH_C_PIN
|
|
@@ -30,6 +31,8 @@ files:
|
|
|
30
31
|
- ext/asterism_zenoh/zenoh.c
|
|
31
32
|
- ext/asterism_zenoh/zenoh_c.rb
|
|
32
33
|
- lib/asterism/zenoh.rb
|
|
34
|
+
- lib/asterism/zenoh/common.rb
|
|
35
|
+
- lib/asterism/zenoh/cruby.rb
|
|
33
36
|
- lib/asterism/zenoh/global.rb
|
|
34
37
|
- lib/asterism/zenoh/values.rb
|
|
35
38
|
- lib/asterism/zenoh/version.rb
|