asterism-zenoh 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e69691b1bce645a0c919495f5b666dd315f94cc6f2c34707cee76eeeccc1d9f7
4
- data.tar.gz: efff8d1807c7752b2d2cadd9d71a082ac96da2acf95af0e9f33873686b5be2d1
3
+ metadata.gz: 67d782b46dad2501a9bb2ae1eed359b376c337ba0395f00dcf80d4d410df16a7
4
+ data.tar.gz: 394689733273761f4cd8e52be3c7e4339f55ae72501a4cdb247ce2c2cd48e4c0
5
5
  SHA512:
6
- metadata.gz: 18f12c15339bae03cbbe9116933d3eccbbf3c740376c5f348830cc7f8e2cf163bd5b0a86876b471955b08dcefa888e51bbcd8de5c4cf141816770e55b42f860f
7
- data.tar.gz: e25ab4b30899f357f9440a9c14d3cb12a7e8b80e36ff1962aa280726237c44b5a8af4091a14585273031e392658155f41d7946da2a2ebe092ef7184c9c8e1117
6
+ metadata.gz: 33b506497a568ba6851979bf141d53954ec221417f866c7e8438cb3e8e12bcf6d5530206b3854a18522d3bc46626037860aeb7f35065eb2338b8a24156c4afcc
7
+ data.tar.gz: 6db7c0db2a026ab7e6517d24fa996c0b31b5d90cd49f2e47fe335e3424703b62222788eeae631cef621d11a69d6f97bb3231baa52ccb06d654fe0a1ac107cf09
data/README.md CHANGED
@@ -18,6 +18,28 @@ loop do
18
18
  end
19
19
  ```
20
20
 
21
+ ## Feature coverage
22
+
23
+ Supported: sessions (client, peer, listening, multicast scouting), any
24
+ zenoh configuration (a Hash of keys, a JSON5 String or file: TLS, QUIC,
25
+ WebSocket, authentication, timeouts), put / delete with encoding, priority,
26
+ congestion control, express, reliability and timestamps, declared
27
+ publishers and queriers with matching status, subscribers with the full
28
+ sample (kind, encoding, timestamp, ...), get / queryable with error and
29
+ delete replies, liveliness, the advanced publisher / subscriber (history
30
+ for late subscribers, recovery, publisher detection; ROS 2 transient
31
+ local), transport and link events, key expression operations and declared
32
+ key expressions, HLC timestamps, zenoh-c's log.
33
+
34
+ Not exposed: shared memory, background declarations, zenoh's own
35
+ serializer (MessagePack and CDR are used instead), the publication cache /
36
+ querying subscriber (the older form of the advanced ones), cancelling a
37
+ get.
38
+
39
+ The table, with the reasons and what the boards' zenoh-pico could offer:
40
+ [docs/feature_coverage.md](docs/feature_coverage.md). The calls added in
41
+ 0.3.0 are CRuby only.
42
+
21
43
  ## API
22
44
 
23
45
  The same calls, arguments and results as the mruby / PicoRuby gem
@@ -41,6 +63,65 @@ The same calls, arguments and results as the mruby / PicoRuby gem
41
63
  Keys come back as UTF-8 Strings, payloads and attachments as binary
42
64
  (ASCII-8BIT) Strings.
43
65
 
66
+ ### Added in 0.3.0 (CRuby only)
67
+
68
+ Every 0.2.0 call works as before; these are new keywords and methods.
69
+
70
+ | Call | Notes |
71
+ |---|---|
72
+ | `Session.open(locator = nil, mode:, listen:, scouting:, timestamping:, config:, config_file:)` | `config:` a Hash (`{"transport/link/tls/root_ca_certificate" => "ca.pem"}`, Ruby values sent as JSON) or a JSON5 String; `config_file:` a JSON5 file. Lowest first: zenoh's defaults, the gem's own settings (no scouting, the time limits), the file / String, the arguments, the Hash. `scouting: true` needs no locator |
73
+ | `Asterism::Zenoh.scout(what: [:router, :peer], timeout: 1.0, config: nil)` | Array of `Hello` (`zid`, `whatami`, `locators`) |
74
+ | `session.put(key, payload, attachment:, encoding:, priority:, congestion_control:, express:, reliability:, timestamp:, allowed_destination:)` | `priority:` `:real_time` .. `:background` (or 1..7), `congestion_control:` `:drop` / `:block` / `:block_first`, `reliability:` `:reliable` / `:best_effort`, `timestamp:` `true` or a `Timestamp`, `allowed_destination:` `:any` / `:remote` / `:session_local` |
75
+ | `session.delete(key, ...)` | the same options without payload, attachment and encoding |
76
+ | `session.publisher(key, encoding:, priority:, ...)` -> `Publisher` | `put(payload, attachment:, encoding:, timestamp:)`, `delete(timestamp:)`, `matching?`, `matching_listener(depth = 16)`, `close` / `closed?` |
77
+ | `session.querier(key, target:, consolidation:, timeout_ms:, ...)` -> `Querier` | `get(params = nil, payload = nil, attachment:, encoding:)` -> `Get`, `matching?`, `matching_listener`, `close` |
78
+ | `sub.each_sample { \|sample\| }` | `Sample` (`key`, `payload`, `attachment`, `kind`, `encoding`, `timestamp`, `priority`, `congestion_control`, `express`, `reliability`, `source_zid`); same queue as `each_pending` |
79
+ | `get.each_result { \|reply\| }` | `Reply` (`ok?` / `error?`, `key`, `payload`, `encoding`, `kind`, `timestamp`, `replier_zid`); error replies included. `each_reply` still leaves them out |
80
+ | `session.get(..., encoding:, priority:, congestion_control:, express:, accept_replies:)` | |
81
+ | `q.reply(..., encoding:, timestamp:, priority:, congestion_control:, express:)`, `q.reply_err(payload, encoding:)`, `q.reply_del(key = nil)`, `q.encoding` | |
82
+ | `session.advanced_publisher(key, cache:, sample_miss_detection:, publisher_detection:, ...)` -> `AdvancedPublisher` | as `Publisher`. `cache: N` keeps the last N samples for late subscribers |
83
+ | `session.advanced_subscriber(key, depth = 16, history:, recovery:, subscriber_detection:, query_timeout_ms:)` -> `AdvancedSubscriber` | as `Subscriber`, plus `detect_publishers` (a `LivelinessWatch`) and `miss_listener` (`Miss`: `source_zid`, `source_eid`, `count`) |
84
+ | `session.transport_events(depth = 16, history: false)`, `session.link_events(...)` -> `EventListener` | `each_pending` gives `TransportEvent` / `LinkEvent` (`kind` `:added` / `:removed`, `zid`, ...) |
85
+ | `session.peer_zids`, `router_zids`, `transports`, `links` | the IDs, `Transport` and `Link` values connected now |
86
+ | `session.new_timestamp` -> `Timestamp` | `ntp64`, `id`, `to_time`, Comparable. From the session's HLC with `timestamping: true` (strictly increasing); otherwise from the system clock, so two in a row may be equal |
87
+ | `Asterism::Zenoh::KeyExpr.new(str, autocanonize: false)` | `intersects?`, `includes?`, `relation_to` (`:disjoint` / `:intersects` / `:includes` / `:equals`), `join`, `concat`, `==`; `KeyExpr.canonize(str)`, `KeyExpr.valid?(str)`. Accepted wherever a key String is |
88
+ | `session.declare_keyexpr(key)` -> `KeyExpr` | declared on the session (sent as a number afterwards); `undeclare` |
89
+ | `Asterism::Zenoh.init_log(level = nil)` | zenoh-c's log on standard output (`"info"`, `"debug"`, or a filter); `RUST_LOG` wins |
90
+
91
+ Listeners (`MatchingListener`, `EventListener`) are polled like the
92
+ subscribers: `each_pending` (yields or returns an Array), `pending`,
93
+ `received`, `dropped`, `close` / `closed?`. The values are `Data` objects
94
+ (`lib/asterism/zenoh/values.rb`), so they work with pattern matching.
95
+
96
+ ```ruby
97
+ Z = Asterism::Zenoh
98
+ s = Z::Session.open("tls/192.0.2.2:7447",
99
+ config: { "transport/link/tls/root_ca_certificate" => "ca.pem" })
100
+ pub = s.publisher("demo/temp", encoding: "text/plain", priority: :data_high)
101
+ watch = pub.matching_listener
102
+ sub = s.subscribe("demo/**")
103
+ loop do
104
+ watch.each_pending { |listening| puts "listened to: #{listening}" }
105
+ pub.put("21.5", timestamp: true)
106
+ sub.each_sample do |sm|
107
+ case sm
108
+ in {kind: :delete, key:} then puts "#{key} deleted"
109
+ in {encoding: "application/json", payload:} then p payload
110
+ else puts "#{sm.key} at #{sm.timestamp&.to_time}"
111
+ end
112
+ end
113
+ sleep 0.1
114
+ end
115
+
116
+ # A late subscriber gets the last values (ROS 2's transient local works this way)
117
+ latched = s.advanced_publisher("demo/mode", cache: 1, sample_miss_detection: true)
118
+ latched.put("eco")
119
+ late = s.advanced_subscriber("demo/mode", history: true)
120
+
121
+ Z.scout(what: :peer, timeout: 1.0).each { |h| puts "#{h.zid} #{h.locators}" }
122
+ Z::KeyExpr.new("demo/*").includes?("demo/temp") # => true
123
+ ```
124
+
44
125
  `require "asterism/zenoh/global"` defines `Zenoh = Asterism::Zenoh` for
45
126
  those who want the short name; nothing defines it by default.
46
127
 
@@ -67,14 +148,14 @@ thread and Enumerators on top of this API are in the CRuby layer of the
67
148
 
68
149
  ## Behaviour kept from the mruby gem
69
150
 
70
- - **No scouting**: the locator is given. A peer that only connects does not
71
- listen.
151
+ - **No scouting** unless asked for (`scouting: true`): the locator is
152
+ given. A peer that only connects does not listen.
72
153
  - **Remote only**: a session's own puts do not reach its own subscribers,
73
154
  and its gets do not reach its own queryables (zenoh-pico's behaviour;
74
155
  Asterism calls its own objects in place).
75
156
  - **Losing the connection**: a client session is closed when it has no
76
157
  router left, a peer session that only connects when it has no peer left;
77
- a listening session stays open. From then on `poll` is false, `closed?`
158
+ a listening (or scouting) session stays open. From then on `poll` is false, `closed?`
78
159
  true, and `put` raises `Asterism::Zenoh::Error`. No reconnection.
79
160
  - **Full queues drop the oldest** entry and count it in `dropped` (a dropped
80
161
  query is finished, so its requester gets no answer from it).
@@ -0,0 +1,54 @@
1
+ # zenoh-c feature coverage of asterism-zenoh
2
+
3
+ Which zenoh-c 1.10.1 features the Ruby binding exposes (asterism-zenoh 0.3.0).
4
+ "Yes" = usable from Ruby, "Partial" = usable with fixed settings or a subset,
5
+ "No" = not exposed, with the reason. The Ruby-like layer of the `asterism`
6
+ gem builds on the same methods. The mruby gem (picoruby-asterism-zenoh) has
7
+ the 0.2.0 part of the API; its column says whether zenoh-pico could offer
8
+ the feature. Everything added in 0.3.0 is CRuby only for now.
9
+
10
+ | Area | zenoh-c | asterism-zenoh (CRuby) | Ruby | Possible on the boards (zenoh-pico) |
11
+ |---|---|---|---|---|
12
+ | Session: client / peer / listen | `z_open` | Yes | `Session.open(loc, mode:, listen:)` | Yes (done) |
13
+ | Session configuration | `zc_config_insert_json5`, `zc_config_from_str`, `zc_config_from_file` | Yes (0.3.0) | `config: {"key/path" => value}` (Ruby values sent as JSON), `config: "<JSON5>"`, `config_file:`. TLS, QUIC, WebSocket, authentication and timeouts are reachable this way; TLS is tested between two sessions | Partial (zenoh-pico has its own, smaller set of keys; no TLS on ESP32) |
14
+ | Scouting (finding peers / routers) | `z_scout`, multicast scouting, gossip | Yes (0.3.0) | `Asterism::Zenoh.scout(what:, timeout:)` -> `Hello` (zid, whatami, locators); `Session.open(scouting: true)` | Yes (off on purpose: the locator is given) |
15
+ | Session information | `z_info_zid`, `z_info_peers_zid`, `z_info_routers_zid`, `z_info_transports`, `z_info_links` | Yes (0.3.0) | `zid`, `peers` (count, as before), `peer_zids`, `router_zids`, `transports`, `links` | Yes (zid lists); transports / links: No |
16
+ | put | `z_put` | Yes (0.3.0) | `put(key, payload, attachment:, encoding:, priority:, congestion_control:, express:, reliability:, timestamp:, allowed_destination:)` | Partial (encoding, priority, congestion control, express: yes) |
17
+ | delete | `z_delete` | Yes (0.3.0) | `session.delete(key, ...)` | Yes |
18
+ | Declared publisher | `z_declare_publisher`, `z_publisher_put`, `z_publisher_delete` | Yes (0.3.0) | `session.publisher(key, ...)` -> `put`, `delete`, `close` | Yes |
19
+ | Matching status (is anyone listening?) | `z_*_get_matching_status`, `z_*_declare_matching_listener` | Yes (0.3.0) | `matching?`, `matching_listener` -> `MatchingListener#each_pending` (polled) | Partial (zenoh-pico has it behind a build option) |
20
+ | Subscriber | `z_declare_subscriber` + FIFO channel | Yes | `each_pending { \|k, v, a\| }` as before; `each_sample` -> `Sample` (kind, encoding, timestamp, priority, congestion_control, express, reliability, source_zid) | Yes (done; the fields: Partial) |
21
+ | get | `z_get` | Yes | timeout, parameters, payload, attachment, target, consolidation; 0.3.0: encoding, priority, congestion control, express, accept_replies; `each_result` -> `Reply` with error replies | Yes (done) |
22
+ | Declared querier | `z_declare_querier`, `z_querier_get` | Yes (0.3.0) | `session.querier(key, target:, consolidation:, timeout_ms:, ...)` -> `get(params, payload, attachment:, encoding:)`, `matching?`, `matching_listener` | Yes |
23
+ | Queryable | `z_declare_queryable`, `z_query_reply`, `z_query_reply_err`, `z_query_reply_del` | Yes (0.3.0) | `reply(..., encoding:, timestamp:, priority:, congestion_control:, express:)`, `reply_err(payload, encoding:)`, `reply_del(key)`, `query.encoding` | Yes |
24
+ | Liveliness | tokens, subscriber, get | Yes | `liveliness`, `liveliness_watch`, `liveliness_get` | Yes (done) |
25
+ | Encoding (content types) | `z_encoding_from_str`, `z_encoding_to_string` | Yes (0.3.0) | Strings ("application/json", "text/plain;charset=utf-8"); default "zenoh/bytes" | Yes |
26
+ | Timestamps (HLC) | `z_timestamp_new`, `z_sample_timestamp`, timestamping | Yes (0.3.0) | `session.new_timestamp`, `Timestamp` (`ntp64`, `id`, `to_time`, Comparable), `put(timestamp: true)`, `Session.open(timestamping: true)` | Partial |
27
+ | Key expression operations | `z_keyexpr_intersects`, `includes`, `relation_to`, `join`, `concat`, `canonize`, `z_declare_keyexpr` | Yes (0.3.0) | `KeyExpr.new(str, autocanonize:)`, `intersects?`, `includes?`, `relation_to`, `join`, `concat`, `KeyExpr.canonize`, `KeyExpr.valid?`; `session.declare_keyexpr(key)`. A KeyExpr goes wherever a key String does | Yes |
28
+ | Advanced publisher / subscriber | `ze_declare_advanced_publisher`, `ze_declare_advanced_subscriber`, publisher detection, sample miss listener | Yes (0.3.0) | `advanced_publisher(key, cache:, sample_miss_detection:, publisher_detection:)`, `advanced_subscriber(key, history:, recovery:, subscriber_detection:)`, `detect_publishers`, `miss_listener`. A late rmw_zenoh subscriber with transient-local durability got the cached values | Partial (RAM to be measured) |
29
+ | Transport / link events | `z_declare_transport_events_listener`, `z_declare_link_events_listener` | Yes (0.3.0) | `session.transport_events(history:)`, `link_events` -> `EventListener#each_pending` (polled) of `TransportEvent` / `LinkEvent` | No |
30
+ | Logging | `zc_init_log_from_env_or`, `zc_try_init_log_from_env` | Yes (0.3.0) | `Asterism::Zenoh.init_log(level)`; written to standard output by zenoh-c; `RUST_LOG` wins | No |
31
+ | Error text | `zc_get_last_error` | Yes (0.3.0) | appended to the `Asterism::Zenoh::Error` messages of failed opens and declarations | No |
32
+ | Serialization helpers | `ze_serialize_*`, `ze_deserialize_*` | No | Not needed: MessagePack (objects) and CDR (ROS 2) are used; payloads stay Strings | Partial |
33
+ | Publication cache / querying subscriber | `ze_declare_publication_cache`, `ze_declare_querying_subscriber` | No | The older form of the advanced publisher / subscriber, which covers it | Partial |
34
+ | Shared memory | `z_shm_*` | No | Same-host only, and a Ruby String is copied anyway, so it would gain nothing | No |
35
+ | Background declarations | `z_declare_background_*` | No | Not needed: every object is closed by `close`, by its session or when it is freed | Partial |
36
+ | Cancellation of gets, source info on puts | `cancellation_token`, `source_info` | No | Rarely needed; a get ends by its time limit | No |
37
+
38
+ How receiving works, for all of the above: zenoh-c's callbacks copy what
39
+ arrives into a queue of plain C memory (no Ruby, no GVL), dropping the
40
+ oldest entry when it is full; Ruby takes the entries out by polling
41
+ (`each_pending`, `each_sample`, `each_result`). This holds for the matching
42
+ listeners, the transport / link events and the missed samples too.
43
+
44
+ Notes:
45
+
46
+ - The prebuilt zenoh-c that `gem install` downloads contains all of the above
47
+ (the "unstable" API included).
48
+ - An advanced publisher with a cache and without `sample_miss_detection`
49
+ needs a session with timestamping (`Session.open(..., timestamping: true)`).
50
+ - For ROS 2 transient-local, publish on the rmw_zenoh topic key with an
51
+ advanced publisher (`cache:`, `publisher_detection: true`,
52
+ `sample_miss_detection: true`) and declare the liveliness token with
53
+ durability transient local in its QoS (`":1:,10:,:,:,,"`).
54
+ `Asterism::ROS` does not do this by itself yet.