mqtt-v5 0.0.1.ci.release
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 +7 -0
- data/lib/mqtt/v5/async/client.rb +27 -0
- data/lib/mqtt/v5/client/authenticator.rb +83 -0
- data/lib/mqtt/v5/client/connection.rb +192 -0
- data/lib/mqtt/v5/client/session.rb +45 -0
- data/lib/mqtt/v5/client.rb +61 -0
- data/lib/mqtt/v5/errors.rb +19 -0
- data/lib/mqtt/v5/packet/auth.rb +57 -0
- data/lib/mqtt/v5/packet/connack.rb +110 -0
- data/lib/mqtt/v5/packet/connect.rb +130 -0
- data/lib/mqtt/v5/packet/disconnect.rb +78 -0
- data/lib/mqtt/v5/packet/ping_req.rb +20 -0
- data/lib/mqtt/v5/packet/ping_resp.rb +20 -0
- data/lib/mqtt/v5/packet/pub_ack.rb +60 -0
- data/lib/mqtt/v5/packet/pub_comp.rb +53 -0
- data/lib/mqtt/v5/packet/pub_rec.rb +60 -0
- data/lib/mqtt/v5/packet/pub_rel.rb +53 -0
- data/lib/mqtt/v5/packet/publish.rb +122 -0
- data/lib/mqtt/v5/packet/reason_code.rb +112 -0
- data/lib/mqtt/v5/packet/sub_ack.rb +66 -0
- data/lib/mqtt/v5/packet/subscribe.rb +87 -0
- data/lib/mqtt/v5/packet/unsub_ack.rb +59 -0
- data/lib/mqtt/v5/packet/unsubscribe.rb +112 -0
- data/lib/mqtt/v5/packet.rb +147 -0
- data/lib/mqtt/v5/packets.rb +25 -0
- data/lib/mqtt/v5/topic_alias/cache.rb +87 -0
- data/lib/mqtt/v5/topic_alias/frequency_weighted_policy.rb +50 -0
- data/lib/mqtt/v5/topic_alias/length_weighted_policy.rb +20 -0
- data/lib/mqtt/v5/topic_alias/lru_policy.rb +36 -0
- data/lib/mqtt/v5/topic_alias/manager.rb +143 -0
- data/lib/mqtt/v5/topic_alias/policy.rb +34 -0
- data/lib/mqtt/v5/topic_alias/weighted_policy.rb +48 -0
- data/lib/mqtt/v5/topic_alias.rb +27 -0
- data/lib/mqtt/v5/version.rb +11 -0
- data/lib/mqtt/v5.rb +4 -0
- metadata +88 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../packet'
|
|
4
|
+
require_relative '../version'
|
|
5
|
+
require 'mqtt/core/packet/connect'
|
|
6
|
+
|
|
7
|
+
module MQTT
|
|
8
|
+
module V5
|
|
9
|
+
module Packet
|
|
10
|
+
# MQTT 5.0 CONNECT packet
|
|
11
|
+
#
|
|
12
|
+
# Sent by client to establish connection with the broker.
|
|
13
|
+
#
|
|
14
|
+
# @see Core::Client#connect
|
|
15
|
+
# @see https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901033 MQTT 5.0 Spec §3.1
|
|
16
|
+
class Connect
|
|
17
|
+
include Packet
|
|
18
|
+
include Core::Packet::Connect
|
|
19
|
+
|
|
20
|
+
# Avoid name clashes between sub-properties
|
|
21
|
+
def self.sub_property_method(name, property_name)
|
|
22
|
+
case name
|
|
23
|
+
when :will_properties
|
|
24
|
+
return :will_user_properties if property_name == :user_properties
|
|
25
|
+
end
|
|
26
|
+
property_name
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
fixed(1)
|
|
30
|
+
|
|
31
|
+
# @!attribute [r] protocol_name
|
|
32
|
+
# @return [String<UTF8>] protocol name (managed automatically)
|
|
33
|
+
# @!attribute [r] protocol_version
|
|
34
|
+
# @return [Integer] protocol version (managed automatically)
|
|
35
|
+
# @!attribute [r] clean_start
|
|
36
|
+
# @return [Boolean] if true server will abandon any stored session (managed automatically from session store)
|
|
37
|
+
# @!attribute [r] will_qos
|
|
38
|
+
# @return [Integer] QoS level for the Will message: 0, 1, or 2 (default 0)
|
|
39
|
+
# @!attribute [r] will_retain
|
|
40
|
+
# @return [Boolean] should the Will message be retained (default false)
|
|
41
|
+
# @!attribute [r] keep_alive
|
|
42
|
+
# @return [Integer] maximum duration in seconds between packets sent by the client (default 60)
|
|
43
|
+
|
|
44
|
+
# @!group Properties
|
|
45
|
+
|
|
46
|
+
# @!attribute [r] session_expiry_interval
|
|
47
|
+
# @return [Integer] session expiry interval in seconds (managed automatically from session store)
|
|
48
|
+
# @!attribute [r] receive_maximum
|
|
49
|
+
# @return [Integer] maximum number of QoS 1 and 2 messages the client will process concurrently
|
|
50
|
+
# @!attribute [r] maximum_packet_size
|
|
51
|
+
# @return [Integer] maximum packet size the client is willing to accept
|
|
52
|
+
# @!attribute [r] topic_alias_maximum
|
|
53
|
+
# @return [Integer] maximum topic alias value the client accepts
|
|
54
|
+
# @!attribute [r] request_response_information
|
|
55
|
+
# @return [Boolean] whether the client requests response information
|
|
56
|
+
# @!attribute [r] request_problem_information
|
|
57
|
+
# @return [Boolean] whether the client requests problem information
|
|
58
|
+
# @!attribute [r] user_properties
|
|
59
|
+
# @return [Array<String, String>] user-defined properties as key-value pairs
|
|
60
|
+
# @!attribute [r] authentication_method
|
|
61
|
+
# @return [String<UTF8>] authentication method name
|
|
62
|
+
# @!attribute [r] authentication_data
|
|
63
|
+
# @return [String<Binary>] authentication data
|
|
64
|
+
|
|
65
|
+
# @!endgroup
|
|
66
|
+
|
|
67
|
+
# @!attribute [r] client_id
|
|
68
|
+
# @return [String<UTF8>] client identifier string (managed from session store, default '')
|
|
69
|
+
# @!attribute [r] will_topic
|
|
70
|
+
# @return [String<UTF8>] topic name to send the Will message to
|
|
71
|
+
# @!attribute [r] will_payload
|
|
72
|
+
# @return [String<Binary>] payload of the Will message
|
|
73
|
+
# @!attribute [r] will_properties
|
|
74
|
+
# @return [Hash<Symbol>] properties for the Will message
|
|
75
|
+
# @!attribute [r] username
|
|
76
|
+
# @return [String<UTF8>] username for authenticating with the server
|
|
77
|
+
# @!attribute [r] password
|
|
78
|
+
# @return [String<Binary>] password for authenticating with the server
|
|
79
|
+
|
|
80
|
+
variable(
|
|
81
|
+
protocol_name: :utf8string,
|
|
82
|
+
protocol_version: :int8,
|
|
83
|
+
connect_flags: flags(
|
|
84
|
+
:username_flag, :password_flag,
|
|
85
|
+
:will_retain,
|
|
86
|
+
[:will_qos, 2],
|
|
87
|
+
:will_flag,
|
|
88
|
+
:clean_start,
|
|
89
|
+
:reserved
|
|
90
|
+
),
|
|
91
|
+
keep_alive: :int16,
|
|
92
|
+
properties: properties(:connect)
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
payload(
|
|
96
|
+
client_id: :utf8string,
|
|
97
|
+
will_properties: { type: properties(:will), if: :will_flag },
|
|
98
|
+
will_topic: { type: :utf8string, if: :will_flag },
|
|
99
|
+
will_payload: { type: :binary, if: :will_flag },
|
|
100
|
+
username: { type: :utf8string, if: :username },
|
|
101
|
+
password: { type: :binary, if: :password }
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
alias clean_requested? clean_start
|
|
105
|
+
alias username? :username_flag
|
|
106
|
+
alias password? :password_flag
|
|
107
|
+
alias will_flag? :will_flag
|
|
108
|
+
|
|
109
|
+
# @!visibility private
|
|
110
|
+
def defaults
|
|
111
|
+
super.merge!(client_id: '', keep_alive: 60, will_retain: false, will_qos: 0, clean_start: false)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# @!visibility private
|
|
115
|
+
def apply_overrides(data)
|
|
116
|
+
super
|
|
117
|
+
data.merge!(
|
|
118
|
+
protocol_name: 'MQTT',
|
|
119
|
+
protocol_version: PROTOCOL_VERSION
|
|
120
|
+
)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# @!visibility private
|
|
124
|
+
def success!(connack)
|
|
125
|
+
connack.success!
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MQTT
|
|
4
|
+
module V5
|
|
5
|
+
module Packet
|
|
6
|
+
# MQTT 5.0 DISCONNECT packet
|
|
7
|
+
#
|
|
8
|
+
# Sent by client to gracefully disconnect, or received from broker to indicate disconnection.
|
|
9
|
+
#
|
|
10
|
+
# @see Core::Client#disconnect
|
|
11
|
+
# @see https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901205 MQTT 5.0 Spec §3.14
|
|
12
|
+
class Disconnect
|
|
13
|
+
include Packet
|
|
14
|
+
|
|
15
|
+
fixed(14)
|
|
16
|
+
|
|
17
|
+
# @!parse include ReasonCodeAck
|
|
18
|
+
# @!attribute [r] reason_code
|
|
19
|
+
# disconnection reason
|
|
20
|
+
#
|
|
21
|
+
# ✅ Success:
|
|
22
|
+
#
|
|
23
|
+
# - `0x00` Normal disconnection
|
|
24
|
+
# - `0x04` Disconnect with Will Message
|
|
25
|
+
#
|
|
26
|
+
# ❌ Error:
|
|
27
|
+
#
|
|
28
|
+
# - `0x80` Unspecified error
|
|
29
|
+
# - `0x81` Malformed Packet
|
|
30
|
+
# - `0x82` Protocol Error
|
|
31
|
+
# - `0x83` Implementation specific error
|
|
32
|
+
# - `0x87` Not authorized
|
|
33
|
+
# - `0x89` Server busy
|
|
34
|
+
# - `0x8B` Server shutting down
|
|
35
|
+
# - `0x8C` Bad authentication method
|
|
36
|
+
# - `0x8D` Keep alive timeout
|
|
37
|
+
# - `0x8E` Session taken over
|
|
38
|
+
# - `0x8F` Topic Filter invalid
|
|
39
|
+
# - `0x90` Topic Name invalid
|
|
40
|
+
# - `0x93` Receive Maximum exceeded
|
|
41
|
+
# - `0x94` Topic Alias invalid
|
|
42
|
+
# - `0x95` Packet too large
|
|
43
|
+
# - `0x96` Message rate too high
|
|
44
|
+
# - `0x97` Quota exceeded
|
|
45
|
+
# - `0x98` Administrative action
|
|
46
|
+
# - `0x99` Payload format invalid
|
|
47
|
+
# - `0x9A` Retain not supported
|
|
48
|
+
# - `0x9B` QoS not supported
|
|
49
|
+
# - `0x9C` Use another server
|
|
50
|
+
# - `0x9E` Shared Subscriptions not supported
|
|
51
|
+
# - `0x9F` Connection rate exceeded
|
|
52
|
+
# - `0xA0` Maximum connect time
|
|
53
|
+
# - `0xA1` Subscription Identifiers not supported
|
|
54
|
+
# - `0xA2` Wildcard Subscriptions not supported
|
|
55
|
+
#
|
|
56
|
+
# @return [ReasonCode]
|
|
57
|
+
|
|
58
|
+
# @!group Properties
|
|
59
|
+
|
|
60
|
+
# @!attribute [r] session_expiry_interval
|
|
61
|
+
# @return [Integer] session expiry interval in seconds
|
|
62
|
+
# @!attribute [r] reason_string
|
|
63
|
+
# @return [String<UTF8>] human-readable reason for disconnection
|
|
64
|
+
# @!attribute [r] user_properties
|
|
65
|
+
# @return [Array<String, String>] user-defined properties as key-value pairs
|
|
66
|
+
# @!attribute [r] server_reference
|
|
67
|
+
# @return [String<UTF8>] server reference for redirection
|
|
68
|
+
|
|
69
|
+
# @!endgroup
|
|
70
|
+
|
|
71
|
+
variable(
|
|
72
|
+
reason_code:, # automatically includes ReasonCodeAck
|
|
73
|
+
properties:
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../packet'
|
|
4
|
+
|
|
5
|
+
module MQTT
|
|
6
|
+
module V5
|
|
7
|
+
module Packet
|
|
8
|
+
# MQTT 5.0 PINGREQ packet
|
|
9
|
+
#
|
|
10
|
+
# Sent by client to keep the connection alive.
|
|
11
|
+
#
|
|
12
|
+
# @see https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901195 MQTT 5.0 Spec §3.12
|
|
13
|
+
class PingReq
|
|
14
|
+
include Packet
|
|
15
|
+
|
|
16
|
+
fixed(12)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../packet'
|
|
4
|
+
|
|
5
|
+
module MQTT
|
|
6
|
+
module V5
|
|
7
|
+
module Packet
|
|
8
|
+
# MQTT 5.0 PINGRESP packet
|
|
9
|
+
#
|
|
10
|
+
# Sent by broker in response to a PINGREQ packet.
|
|
11
|
+
#
|
|
12
|
+
# @see https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901200 MQTT 5.0 Spec §3.13
|
|
13
|
+
class PingResp
|
|
14
|
+
include Packet
|
|
15
|
+
|
|
16
|
+
fixed(13)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../packet'
|
|
4
|
+
|
|
5
|
+
module MQTT
|
|
6
|
+
module V5
|
|
7
|
+
module Packet
|
|
8
|
+
# MQTT 5.0 PUBACK packet
|
|
9
|
+
#
|
|
10
|
+
# QoS 1 acknowledgement sent by broker in response to a PUBLISH packet.
|
|
11
|
+
#
|
|
12
|
+
# @see Core::Client#publish
|
|
13
|
+
# @see https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901121 MQTT 5.0 Spec §3.4
|
|
14
|
+
class PubAck
|
|
15
|
+
include Packet
|
|
16
|
+
|
|
17
|
+
fixed(4)
|
|
18
|
+
|
|
19
|
+
# @!attribute [r] packet_identifier
|
|
20
|
+
# @return [Integer] packet identifier matching the PUBLISH packet (receive only)
|
|
21
|
+
|
|
22
|
+
# @!parse include ReasonCodeAck
|
|
23
|
+
# @!attribute [r] reason_code
|
|
24
|
+
# acknowledgement status
|
|
25
|
+
#
|
|
26
|
+
# ✅ Success:
|
|
27
|
+
#
|
|
28
|
+
# - `0x00` Success
|
|
29
|
+
# - `0x10` No matching subscribers
|
|
30
|
+
#
|
|
31
|
+
# ❌ Error:
|
|
32
|
+
#
|
|
33
|
+
# - `0x80` Unspecified error
|
|
34
|
+
# - `0x83` Implementation specific error
|
|
35
|
+
# - `0x87` Not authorized
|
|
36
|
+
# - `0x90` Topic Name invalid
|
|
37
|
+
# - `0x91` Packet Identifier in use
|
|
38
|
+
# - `0x97` Quota exceeded
|
|
39
|
+
# - `0x99` Payload format invalid
|
|
40
|
+
#
|
|
41
|
+
# @return [ReasonCode]
|
|
42
|
+
|
|
43
|
+
# @!group Properties
|
|
44
|
+
|
|
45
|
+
# @!attribute [r] reason_string
|
|
46
|
+
# @return [String<UTF8>] human-readable reason for the response
|
|
47
|
+
# @!attribute [r] user_properties
|
|
48
|
+
# @return [Array<String, String>] user-defined properties as key-value pairs
|
|
49
|
+
|
|
50
|
+
# @!endgroup
|
|
51
|
+
|
|
52
|
+
variable(
|
|
53
|
+
packet_identifier: :int16,
|
|
54
|
+
reason_code:, # automatically includes ReasonCodeAck
|
|
55
|
+
properties:
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../packet'
|
|
4
|
+
|
|
5
|
+
module MQTT
|
|
6
|
+
module V5
|
|
7
|
+
module Packet
|
|
8
|
+
# MQTT 5.0 PUBCOMP packet
|
|
9
|
+
#
|
|
10
|
+
# QoS 2 publish complete (part 3) sent by broker in response to a PUBREL packet.
|
|
11
|
+
#
|
|
12
|
+
# @see Core::Client#publish
|
|
13
|
+
# @see https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901151 MQTT 5.0 Spec §3.7
|
|
14
|
+
class PubComp
|
|
15
|
+
include Packet
|
|
16
|
+
|
|
17
|
+
fixed(7)
|
|
18
|
+
|
|
19
|
+
# @!attribute [r] packet_identifier
|
|
20
|
+
# @return [Integer] packet identifier matching the PUBREL packet (receive only)
|
|
21
|
+
|
|
22
|
+
# @!parse include ReasonCodeAck
|
|
23
|
+
# @!attribute [r] reason_code
|
|
24
|
+
# acknowledgement status
|
|
25
|
+
#
|
|
26
|
+
# ✅ Success:
|
|
27
|
+
#
|
|
28
|
+
# - `0x00` Success
|
|
29
|
+
#
|
|
30
|
+
# ❌ Error:
|
|
31
|
+
#
|
|
32
|
+
# - `0x92` Packet Identifier not found
|
|
33
|
+
#
|
|
34
|
+
# @return [ReasonCode]
|
|
35
|
+
|
|
36
|
+
# @!group Properties
|
|
37
|
+
|
|
38
|
+
# @!attribute [r] reason_string
|
|
39
|
+
# @return [String<UTF8>] human-readable reason for the response
|
|
40
|
+
# @!attribute [r] user_properties
|
|
41
|
+
# @return [Array<String, String>] user-defined properties as key-value pairs
|
|
42
|
+
|
|
43
|
+
# @!endgroup
|
|
44
|
+
|
|
45
|
+
variable(
|
|
46
|
+
packet_identifier: :int16,
|
|
47
|
+
reason_code:, # automatically includes ReasonCodeAck
|
|
48
|
+
properties:
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../packet'
|
|
4
|
+
|
|
5
|
+
module MQTT
|
|
6
|
+
module V5
|
|
7
|
+
module Packet
|
|
8
|
+
# MQTT 5.0 PUBREC packet
|
|
9
|
+
#
|
|
10
|
+
# QoS 2 acknowledgement (part 1) sent by broker in response to a PUBLISH packet.
|
|
11
|
+
#
|
|
12
|
+
# @see Core::Client#publish
|
|
13
|
+
# @see https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901131 MQTT 5.0 Spec §3.5
|
|
14
|
+
class PubRec
|
|
15
|
+
include Packet
|
|
16
|
+
|
|
17
|
+
fixed(5)
|
|
18
|
+
|
|
19
|
+
# @!attribute [r] packet_identifier
|
|
20
|
+
# @return [Integer] packet identifier matching the PUBLISH packet (receive only)
|
|
21
|
+
|
|
22
|
+
# @!parse include ReasonCodeAck
|
|
23
|
+
# @!attribute [r] reason_code
|
|
24
|
+
# acknowledgement status
|
|
25
|
+
#
|
|
26
|
+
# ✅ Success:
|
|
27
|
+
#
|
|
28
|
+
# - `0x00` Success
|
|
29
|
+
# - `0x10` No matching subscribers
|
|
30
|
+
#
|
|
31
|
+
# ❌ Error:
|
|
32
|
+
#
|
|
33
|
+
# - `0x80` Unspecified error
|
|
34
|
+
# - `0x83` Implementation specific error
|
|
35
|
+
# - `0x87` Not authorized
|
|
36
|
+
# - `0x90` Topic Name invalid
|
|
37
|
+
# - `0x91` Packet Identifier in use
|
|
38
|
+
# - `0x97` Quota exceeded
|
|
39
|
+
# - `0x99` Payload format invalid
|
|
40
|
+
#
|
|
41
|
+
# @return [ReasonCode]
|
|
42
|
+
|
|
43
|
+
# @!group Properties
|
|
44
|
+
|
|
45
|
+
# @!attribute [r] reason_string
|
|
46
|
+
# @return [String<UTF8>] human-readable reason for the response
|
|
47
|
+
# @!attribute [r] user_properties
|
|
48
|
+
# @return [Array<String, String>] user-defined properties as key-value pairs
|
|
49
|
+
|
|
50
|
+
# @!endgroup
|
|
51
|
+
|
|
52
|
+
variable(
|
|
53
|
+
packet_identifier: :int16,
|
|
54
|
+
reason_code:, # automatically includes ReasonCodeAck
|
|
55
|
+
properties:
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../packet'
|
|
4
|
+
|
|
5
|
+
module MQTT
|
|
6
|
+
module V5
|
|
7
|
+
module Packet
|
|
8
|
+
# MQTT 5.0 PUBREL packet
|
|
9
|
+
#
|
|
10
|
+
# QoS 2 publish release (part 2) sent by client in response to a PUBREC packet.
|
|
11
|
+
#
|
|
12
|
+
# @see Core::Client#publish
|
|
13
|
+
# @see https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901141 MQTT 5.0 Spec §3.6
|
|
14
|
+
class PubRel
|
|
15
|
+
include Packet
|
|
16
|
+
|
|
17
|
+
fixed(6, [:reserved, 4, 0b0010])
|
|
18
|
+
|
|
19
|
+
# @!attribute [r] packet_identifier
|
|
20
|
+
# @return [Integer] packet identifier matching the PUBREC packet (receive only)
|
|
21
|
+
|
|
22
|
+
# @!parse include ReasonCodeAck
|
|
23
|
+
# @!attribute [r] reason_code
|
|
24
|
+
# acknowledgement status
|
|
25
|
+
#
|
|
26
|
+
# ✅ Success:
|
|
27
|
+
#
|
|
28
|
+
# - `0x00` Success
|
|
29
|
+
#
|
|
30
|
+
# ❌ Error:
|
|
31
|
+
#
|
|
32
|
+
# - `0x92` Packet Identifier not found
|
|
33
|
+
#
|
|
34
|
+
# @return [ReasonCode]
|
|
35
|
+
|
|
36
|
+
# @!group Properties
|
|
37
|
+
|
|
38
|
+
# @!attribute [r] reason_string
|
|
39
|
+
# @return [String<UTF8>] human-readable reason for the response
|
|
40
|
+
# @!attribute [r] user_properties
|
|
41
|
+
# @return [Array<String, String>] user-defined properties as key-value pairs
|
|
42
|
+
|
|
43
|
+
# @!endgroup
|
|
44
|
+
|
|
45
|
+
variable(
|
|
46
|
+
packet_identifier: :int16,
|
|
47
|
+
reason_code:, # automatically includes ReasonCodeAck
|
|
48
|
+
properties:
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../packet'
|
|
4
|
+
require 'mqtt/core/packet/publish'
|
|
5
|
+
|
|
6
|
+
module MQTT
|
|
7
|
+
module V5
|
|
8
|
+
module Packet
|
|
9
|
+
# MQTT 5.0 PUBLISH packet
|
|
10
|
+
#
|
|
11
|
+
# Sent by client to publish a message to the broker, or received from broker when subscribed to a topic.
|
|
12
|
+
#
|
|
13
|
+
# @see Client#publish
|
|
14
|
+
# @see https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901100 MQTT 5.0 Spec §3.3
|
|
15
|
+
class Publish
|
|
16
|
+
include Packet
|
|
17
|
+
include Core::Packet::Publish
|
|
18
|
+
|
|
19
|
+
# @!attribute [r] dup
|
|
20
|
+
# @return [Boolean] duplicate delivery flag (managed automatically by session)
|
|
21
|
+
# @!attribute [r] qos
|
|
22
|
+
# @return [Integer] QoS level: 0, 1, or 2 (default 0)
|
|
23
|
+
# @!attribute [r] retain
|
|
24
|
+
# @return [Boolean] should this message be retained by the broker (default false)
|
|
25
|
+
fixed(3, :dup, [:qos, 2], :retain)
|
|
26
|
+
|
|
27
|
+
# @!attribute [r] packet_identifier
|
|
28
|
+
# @return [Integer] packet identifier for QoS 1/2 exchanges (managed automatically by session)
|
|
29
|
+
|
|
30
|
+
# @!group Properties
|
|
31
|
+
|
|
32
|
+
# @!attribute [r] payload_format_indicator
|
|
33
|
+
# @return [Integer] 0 = unspecified, 1 = UTF-8 encoded payload (auto-detected from payload encoding)
|
|
34
|
+
# @!attribute [r] message_expiry_interval
|
|
35
|
+
# @return [Integer] message expiry interval in seconds
|
|
36
|
+
# @!attribute [r] response_topic
|
|
37
|
+
# @return [String<UTF8>] topic name for response messages
|
|
38
|
+
# @!attribute [r] correlation_data
|
|
39
|
+
# @return [String<Binary>] correlation data for request/response
|
|
40
|
+
# @!attribute [r] user_properties
|
|
41
|
+
# @return [Array<String, String>] user-defined properties as key-value pairs
|
|
42
|
+
# @!attribute [r] subscription_identifiers
|
|
43
|
+
# @return [Array<Integer>] subscription identifiers (receive only, set by broker)
|
|
44
|
+
# @!attribute [r] content_type
|
|
45
|
+
# @return [String<UTF8>] content type description
|
|
46
|
+
|
|
47
|
+
variable(
|
|
48
|
+
topic_name: :utf8string,
|
|
49
|
+
packet_identifier: { type: :int16, if: -> { qos.positive? } },
|
|
50
|
+
properties:
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# @!visibility private
|
|
54
|
+
alias orig_topic_alias topic_alias
|
|
55
|
+
|
|
56
|
+
# @!attribute [r] topic_alias
|
|
57
|
+
# Managed automatically by {TopicAlias::Manager}. See {Client#publish}.
|
|
58
|
+
# @return [Integer|nil] the assigned topic alias id
|
|
59
|
+
def topic_alias
|
|
60
|
+
(@alias_info && @alias_info[:alias]) || orig_topic_alias
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @!endgroup
|
|
64
|
+
|
|
65
|
+
# @return [Boolean] whether {TopicAlias::Manager} will try to assign an outgoing {#topic_alias}
|
|
66
|
+
# @see Client#publish
|
|
67
|
+
def assign_alias?
|
|
68
|
+
@assign_alias
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# @!visibility private
|
|
72
|
+
attr_reader :alias_info
|
|
73
|
+
|
|
74
|
+
# @!visibility private
|
|
75
|
+
alias orig_topic_name topic_name
|
|
76
|
+
|
|
77
|
+
# @!attribute [r] topic_name
|
|
78
|
+
# @return [String<UTF8>] topic name to publish to
|
|
79
|
+
def topic_name
|
|
80
|
+
(@alias_info && @alias_info[:name]) || orig_topic_name
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
alias topic topic_name
|
|
84
|
+
|
|
85
|
+
# @!attribute [r] payload
|
|
86
|
+
# @return [String<Binary>] message payload
|
|
87
|
+
payload(payload: :remaining)
|
|
88
|
+
|
|
89
|
+
# @!visibility private
|
|
90
|
+
def apply_alias(alias: nil, name: nil)
|
|
91
|
+
@alias_info = { alias:, name: }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# @!visibility private
|
|
95
|
+
# Check if this packet matches a subscription identifier
|
|
96
|
+
# @param [Integer] sub_id subscription identifier to check
|
|
97
|
+
# @return [Boolean]
|
|
98
|
+
def match_subscription_identifier?(sub_id)
|
|
99
|
+
(subscription_identifiers || []).include?(sub_id)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# @!visibility private
|
|
103
|
+
def apply_data(data)
|
|
104
|
+
@assign_alias = data.delete(:assign_alias) if data.key?(:assign_alias)
|
|
105
|
+
super
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# @!visibility private
|
|
109
|
+
def apply_overrides(data)
|
|
110
|
+
super
|
|
111
|
+
data[:payload_format_indicator] = 1 if payload&.encoding == Encoding::UTF_8
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# @!visibility private
|
|
115
|
+
def validate
|
|
116
|
+
super
|
|
117
|
+
raise ArgumentError, 'Response topic cannot contain wildcards' if response_topic&.match?(/[#+]/)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|