Line data Source code
1 : /*
2 : * Package : mqtt_client
3 : * Author : S. Hamblett <steve.hamblett@linux.com>
4 : * Date : 10/07/2017
5 : * Copyright : S.Hamblett
6 : */
7 :
8 : part of mqtt_client;
9 :
10 : /// A client class for interacting with MQTT Data Packets
11 : class MqttClient {
12 : /// Initializes a new instance of the MqttClient class using the default Mqtt Port.
13 : /// The server hostname to connect to
14 : /// The client identifier to use to connect with
15 2 : MqttClient(this.server, this.clientIdentifier) {
16 2 : this.port = Constants.defaultMqttPort;
17 : }
18 :
19 : /// Initializes a new instance of the MqttClient class using the supplied Mqtt Port.
20 : /// The server hostname to connect to
21 : /// The client identifier to use to connect with
22 : /// The port to use
23 0 : MqttClient.withPort(this.server, this.clientIdentifier, this.port);
24 :
25 : String server;
26 : int port;
27 : String clientIdentifier;
28 :
29 : /// If set use a websocket connection, otherwise use the default TCP one
30 : bool useWebSocket = false;
31 :
32 : /// If set use a secure connection, note TCP only, not websocket.
33 : bool secure = false;
34 :
35 : /// Trusted certificate file path for use in secure working
36 : String trustedCertPath;
37 :
38 : /// Private key file path
39 : String privateKeyFilePath;
40 :
41 : /// The Handler that is managing the connection to the remote server.
42 : MqttConnectionHandler _connectionHandler;
43 :
44 : /// The subscriptions manager responsible for tracking subscriptions.
45 : SubscriptionsManager _subscriptionsManager;
46 :
47 : /// Handles the connection management while idle.
48 : MqttConnectionKeepAlive _keepAlive;
49 :
50 : /// Keep alive period, seconds
51 : int keepAlivePeriod = Constants.defaultKeepAlive;
52 :
53 : /// Handles everything to do with publication management.
54 : PublishingManager _publishingManager;
55 :
56 : /// Gets the current conneciton state of the Mqtt Client.
57 : ConnectionState get connectionState =>
58 1 : _connectionHandler != null
59 2 : ? _connectionHandler.connectionState
60 : : ConnectionState.disconnected;
61 :
62 : /// The connection message to use to override the default
63 : MqttConnectMessage connectionMessage;
64 :
65 : /// Performs a synchronous connect to the message broker with an optional username and password
66 : /// for the purposes of authentication.
67 : Future<ConnectionState> connect([String username, String password]) async {
68 : if (username != null) {
69 0 : print(
70 0 : "Authenticating with username '{$username}' and password '{$password}'");
71 : if (username
72 0 : .trim()
73 0 : .length >
74 : Constants.recommendedMaxUsernamePasswordLength) {
75 0 : print("Username length (${username
76 0 : .trim()
77 0 : .length}) exceeds the max recommended in the MQTT spec. ");
78 : }
79 : }
80 : if (password != null &&
81 : password
82 0 : .trim()
83 0 : .length >
84 : Constants.recommendedMaxUsernamePasswordLength) {
85 0 : print("Password length (${ password
86 0 : .trim()
87 0 : .length}) exceeds the max recommended in the MQTT spec. ");
88 : }
89 2 : _connectionHandler = new SynchronousMqttConnectionHandler();
90 1 : if (useWebSocket) {
91 0 : _connectionHandler.secure = false;
92 0 : _connectionHandler.useWebSocket = true;
93 : }
94 1 : if (secure) {
95 0 : _connectionHandler.secure = true;
96 0 : _connectionHandler.useWebSocket = false;
97 0 : _connectionHandler.trustedCertPath = trustedCertPath;
98 0 : _connectionHandler.privateKeyFilePath = privateKeyFilePath;
99 : }
100 3 : _publishingManager = new PublishingManager(_connectionHandler);
101 1 : _subscriptionsManager =
102 3 : new SubscriptionsManager(_connectionHandler, _publishingManager);
103 2 : _keepAlive = new MqttConnectionKeepAlive(
104 2 : _connectionHandler, keepAlivePeriod);
105 1 : final connectMessage = _getConnectMessage(username, password);
106 3 : return await _connectionHandler.connect(
107 2 : this.server, this.port, connectMessage);
108 0 : }
109 :
110 : /// Gets a pre-configured connect message if one has not been supplied by the user.
111 : /// Returns an MqttConnectMessage that can be used to connect to a message broker
112 : MqttConnectMessage _getConnectMessage(String username, String password) {
113 1 : if (connectionMessage == null) {
114 2 : connectionMessage = new MqttConnectMessage()
115 2 : .withClientIdentifier(clientIdentifier)
116 1 : .keepAliveFor(Constants.defaultKeepAlive)
117 1 : .authenticateAs(username, password)
118 1 : .startClean();
119 : }
120 1 : return connectionMessage;
121 : }
122 :
123 : /// Initiates a topic subscription request to the connected broker with a strongly typed data processor callback.
124 : /// The topic to subscribe to.
125 : /// The qos level the message was published at.
126 : /// Returns the change notifier assigned to the subscription.
127 : /// Raises InvalidTopicException If a topic that does not meet the MQTT topic spec rules is provided.
128 : ChangeNotifier<MqttReceivedMessage> listenTo(String topic, MqttQos qosLevel) {
129 0 : if (_connectionHandler.connectionState != ConnectionState.connected) {
130 0 : throw new ConnectionException(_connectionHandler.connectionState);
131 : }
132 0 : return _subscriptionsManager.registerSubscription(topic, qosLevel);
133 : }
134 :
135 : /// Publishes a message to the message broker.
136 : /// Returns The message identifer assigned to the message.
137 : /// Raises InvalidTopicException if the topic supplied violates the MQTT topic format rules.
138 : int publishMessage(String topic, MqttQos qualityOfService,
139 : typed.Uint8Buffer data) {
140 3 : if (_connectionHandler.connectionState != ConnectionState.connected) {
141 0 : throw new ConnectionException(_connectionHandler.connectionState);
142 : }
143 : try {
144 1 : final PublicationTopic pubTopic = new PublicationTopic(topic);
145 2 : return _publishingManager.publish(pubTopic, qualityOfService, data);
146 : } catch (Exception) {
147 0 : throw new InvalidTopicException(Exception.toString(), topic);
148 : }
149 : }
150 :
151 : /// Unsubscribe from a topic
152 : void unsubscribe(String topic) {
153 0 : _subscriptionsManager.unsubscribe(topic);
154 : }
155 :
156 : /// Gets the current status of a subscription.
157 : SubscriptionStatus getSubscriptionsStatus(String topic) {
158 0 : return _subscriptionsManager.getSubscriptionsStatus(topic);
159 : }
160 :
161 : /// Disconnect from the broker
162 : void disconnect() {
163 2 : _connectionHandler.disconnect();
164 1 : _publishingManager = null;
165 1 : _subscriptionsManager = null;
166 2 : _keepAlive.stop();
167 1 : _keepAlive = null;
168 1 : _connectionHandler = null;
169 : }
170 :
171 : /// Turn on logging, true to start, false to stop
172 : void logging(bool on) {
173 : MqttLogger.loggingOn = false;
174 : if (on) {
175 : MqttLogger.loggingOn = true;
176 : }
177 : }
178 :
179 : /// Set the protocol version to V3.1 - default
180 : void setProtocolV31() {
181 : Protocol.version = Constants.mqttV31ProtocolVersion;
182 : Protocol.name = Constants.mqttV31ProtocolName;
183 : }
184 :
185 : /// Set the protocol version to V3.1.1
186 : void setProtocolV311() {
187 : Protocol.version = Constants.mqttV311ProtocolVersion;
188 : Protocol.name = Constants.mqttV311ProtocolName;
189 : }
190 : }
|