├── .travis.yml ├── LICENSE ├── README.md ├── package.json ├── plugin.xml ├── sampleapp ├── index.html └── js │ └── index.js ├── src ├── android │ └── CordovaMqTTPlugin.java └── ios │ ├── CordovaMQTTPlugin.m │ ├── MQTTAsync.h │ └── MQTTClientPersistence.h └── www ├── MQTTEmitter.js ├── cordova-plugin-mqtt.js └── mqtt.min.js /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | node_js: 4 | - "4.2" 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Arcoiris Labs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cordova-plugin-mqtt 2 | 3 | [![npm version](https://badge.fury.io/js/cordova-plugin-mqtt.svg)](https://badge.fury.io/js/cordova-plugin-mqtt) 4 | [![Join the chat at https://gitter.im/arcoirislabs/cordova-plugin-mqtt](https://badges.gitter.im/arcoirislabs/cordova-plugin-mqtt.svg)](https://gitter.im/arcoirislabs/cordova-plugin-mqtt?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 5 | 6 | Important Notice 7 | 8 | This project is not abandoned or inactive. On 20th Feb 2019, major updates will be pushed. 9 | 10 | Updates: 11 | 12 | 1. Native Support for iOS & Windows (UWP only) 13 | 2. New API 14 | 3. SSL/TLS support on Android, iOS & Windows 15 | 4. Better config validation. 16 | 5. Resolution of bugs 17 | 18 | 19 | cordova-plugin-mqtt is plugin for building MQTT client for multiple platforms in Apache Cordova. Currently Android platform is present and next support is planned for iOS & Windows Phone. 20 | 21 | ### Cordova platform support 22 | 5.x (CLI) 23 | 4.x (Cordova Android) & above. 24 | 25 | ### Note 26 | From v0.3.x, the eventListner implementation shall be deprecated. Kindly take a note of this. 27 | 28 | ### Installation 29 | 30 | Install plugins via plugin repository or GitHub 31 | 32 | ```sh 33 | $ cordova plugin add cordova-plugin-mqtt 34 | ``` 35 | 36 | ```sh 37 | $ cordova plugin add https://github.com/arcoirislabs/cordova-plugin-mqtt.git 38 | ``` 39 | 40 | ### Changelog 41 | 42 | 1. Adding temporary support to iOS platform until a stable native support arrives. 43 | 44 | ### Documentation 45 | 46 | [UPDATE] 47 | 48 | We have written a tutorial for this plugin over [here](https://medium.com/@arcoirislabs/using-mqtt-on-apache-cordova-564d4fab526b). Kindly check out before you start developing. Cheers 49 | ##### Methods 50 | 1. [connect](#connect) 51 | 2. [publish](#publish) 52 | 3. [subscribe](#subscribe) 53 | 4. [unsubscribe](#unsubscribe) 54 | 5. [disconnect](#disconnect) 55 | 6. [router](#router) 56 | 7. [listen](#listen) 57 | 58 | ##### Events 59 | Default listeners you can program anywhere for following events 60 | - connected 61 | - disconnected 62 | - failure (connection) 63 | - subscribed 64 | - not subscribed 65 | - published 66 | - not published 67 | 68 | For example you can configure the event in this way 69 | 70 | ```javascript 71 | //Deprecated 72 | document.addEventListener("connected",function(e){ 73 | console.log(e.type) 74 | },false) 75 | ``` 76 | 77 | 78 | ##### connect 79 | To connect to a broker. This plugin doesn't supports mqtt:// protocol. Use tcp:// instead. 80 | 81 | ```javascript 82 | cordova.plugins.CordovaMqTTPlugin.connect({ 83 | url:"tcp://test.mosquitto.org", //a public broker used for testing purposes only. Try using a self hosted broker for production. 84 | port:1883, 85 | clientId:"YOUR_USER_ID_LESS_THAN_24_CHARS", 86 | connectionTimeout:3000, 87 | willTopicConfig:{ 88 | qos:0, //default is 0 89 | retain:true, //default is true 90 | topic:"", 91 | payload:"" 92 | }, 93 | username:"uname", 94 | password:'pass', 95 | keepAlive:60, 96 | isBinaryPayload: false, //setting this 'true' will make plugin treat all data as binary and emit ArrayBuffer instead of string on events 97 | success:function(s){ 98 | console.log("connect success"); 99 | }, 100 | error:function(e){ 101 | console.log("connect error"); 102 | }, 103 | onConnectionLost:function (){ 104 | console.log("disconnect"); 105 | }, 106 | routerConfig:{ 107 | router:routerObject //instantiated router object 108 | publishMethod:"emit", //refer your custom router documentation to get the emitter/publishing function name. The parameter should be a string and not a function. 109 | useDefaultRouter:false //Set false to use your own topic router implementation. Set true to use the stock topic router implemented in the plugin. 110 | } 111 | }) 112 | ``` 113 | 114 | ##### publish 115 | To publish to a channel. You can use this function. 116 | 117 | ```javascript 118 | cordova.plugins.CordovaMqTTPlugin.publish({ 119 | topic:"sampletopic", 120 | payload:"hello from the plugin", 121 | qos:0, 122 | retain:false, 123 | success:function(s){ 124 | 125 | }, 126 | error:function(e){ 127 | 128 | } 129 | }) 130 | ``` 131 | In order to debug the publish call you can either go for callbacks in the function or events. Once published the function will call the "published" event & the success callback else the function will call both "not published" event & error callback. 132 | 133 | ##### subscribe 134 | To subscribe to a channel. You can use this function. You can also use wildcard based subscription using following ways 135 | 136 | ```javascript 137 | //Simple subscribe 138 | cordova.plugins.CordovaMqTTPlugin.subscribe({ 139 | topic:"sampletopic", 140 | qos:0, 141 | success:function(s){ 142 | 143 | }, 144 | error:function(e){ 145 | 146 | } 147 | }); 148 | 149 | //Single level wildcard subscribe 150 | cordova.plugins.CordovaMqTTPlugin.subscribe({ 151 | topic:"/+/sampletopic", 152 | qos:0, 153 | success:function(s){ 154 | 155 | }, 156 | error:function(e){ 157 | 158 | } 159 | }); 160 | 161 | //multi level wildcard subscribe 162 | cordova.plugins.CordovaMqTTPlugin.subscribe({ 163 | topic:"/sampletopic/#", 164 | qos:0, 165 | success:function(s){ 166 | 167 | }, 168 | error:function(e){ 169 | 170 | } 171 | }); 172 | 173 | //Using both kinds of wildcards 174 | 175 | cordova.plugins.CordovaMqTTPlugin.subscribe({ 176 | topic:"/+/sampletopic/#", 177 | qos:0, 178 | success:function(s){ 179 | 180 | }, 181 | error:function(e){ 182 | 183 | } 184 | }) 185 | ``` 186 | The success callback can notify you once you are successfully subscribed, so it will be called only once. The onPublish method is deprecated. 187 | If you want to read the payload, you can listen to the event by the name of the topic. For example if you have subscribed to the topic called "sampletopic". You can read the payload in this way. 188 | 189 | #####Update:- 190 | We are introducing topic pattern support to listen to certain topics in a way the developer wishes to. This topic pattern helps developer to make a common listener to different topics sharing same levels using single and multi-level wildcards. 191 | 192 | ```javascript 193 | //Deprecated 194 | document.addEventListener("sampletopic",function(e){ 195 | console.log(e.payload) 196 | },false); 197 | 198 | //New way to listen to topics 199 | cordova.plugins.CordovaMqTTPlugin.listen("/topic/+singlewc/#multiwc",function(payload,params){ 200 | //Callback:- (If the user has published to /topic/room/hall) 201 | //payload : contains payload data 202 | //params : {singlewc:room,multiwc:hall} 203 | }) 204 | ``` 205 | 206 | ##### unsubscribe 207 | 208 | To unsubscribe to a channel. You can use this function. 209 | 210 | ```javascript 211 | cordova.plugins.CordovaMqTTPlugin.unsubscribe({ 212 | topic:"sampletopic", 213 | success:function(s){ 214 | 215 | }, 216 | error:function(e){ 217 | 218 | } 219 | }) 220 | ``` 221 | This function will also fire the unsubscribe event which yiu can listen to using the document.addEventListener function. Also the event listener for the topic is removed automatically once the client successfully unsubscibes. 222 | 223 | 224 | ##### disconnect 225 | 226 | To disconnect yourself from a server, use following function 227 | ```javascript 228 | cordova.plugins.CordovaMqTTPlugin.disconnect({ 229 | success:function(s){ 230 | 231 | }, 232 | error:function(e){ 233 | 234 | } 235 | }) 236 | ``` 237 | 238 | ##### router 239 | 240 | This function provides you the access to all the topic router functions you have used. If you have used a the stock topic router you can access the payload for a topic by this method. 241 | ```javascript 242 | //Declare this function in any scope to access the router function "on" to receive the payload for certain topic 243 | cordova.plugins.CordovaMqTTPlugin.router.on("/topic/+singlewc/#multiwc",function(payload,params){ 244 | //Callback:- (If the user has published to /topic/room/hall) 245 | //payload : contains payload data 246 | //params : {singlewc:room,multiwc:hall} 247 | }); 248 | 249 | //To get a callback on topic subscribe/unsubscribe event, you can listen by this method 250 | cordova.plugins.CordovaMqTTPlugin.router.onadd(function(topic){ 251 | 252 | }); 253 | cordova.plugins.CordovaMqTTPlugin.router.onremove(function(topic){ 254 | 255 | }); 256 | ``` 257 | 258 | ##### listen 259 | 260 | This function lets you listen to certain topic pattern specifically constructed by topic patters as shown below. 261 | ```javascript 262 | //Declare this function in any scope to access the router function "on" to receive the payload for certain topic 263 | cordova.plugins.CordovaMqTTPlugin.listen("/topic/+singlewc/#multiwc",function(payload,params){ 264 | //Callback:- (If the user has published to /topic/room/hall) 265 | //payload : contains payload data 266 | //params : {singlewc:room,multiwc:hall} 267 | }); 268 | 269 | 270 | ``` 271 | 272 | ### Todos 273 | 274 | - Add a stable iOS support in v0.3.0 275 | - Plan support for new platform (Windows Phone) 276 | - Add background service support in Android version to save the payload related from certain topics in a DB when the app is in background. 277 | 278 | 279 | License 280 | ---- 281 | 282 | MIT 283 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cordova-plugin-mqtt", 3 | "version": "0.3.8", 4 | "description": "Cordova plugin for MQTT (Message Queuing Telemetry Transport) protocol. Supports 3.x protocol. More platforms to be added in coming future.", 5 | "cordova": { 6 | "id": "cordova-plugin-mqtt", 7 | "platforms": [ 8 | "android" 9 | ] 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/arcoirislabs/mqtt-cordova.git" 14 | }, 15 | "bugs": { 16 | "url": "https://github.com/arcoirislabs/mqtt-cordova/issues" 17 | }, 18 | "keywords": [ 19 | "cordova", 20 | "ecosystem:cordova", 21 | "mqtt", 22 | "arcoirislabs" 23 | ], 24 | "author": { 25 | "name": "Arcoiris Labs", 26 | "email": "amey@arcoirislabs.com" 27 | }, 28 | "license": "MIT" 29 | } 30 | -------------------------------------------------------------------------------- /plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | CordovaMqTTPlugin 4 | The new MqTT plugin for Cordova 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /sampleapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Mqtt Test 13 | 14 | 15 |
16 |

Connect

17 |

P.S:- "mqtt://" protocol is not supported by this plugin. Instead use "tcp://" which works with any broker.

18 |
19 |
20 |
21 | 22 |
23 |
24 |

Subscribe

25 |
26 | 27 |
28 |
29 |

Publish

30 |
31 | 32 | 33 |
34 |
35 |

Activity Log

36 |
37 |
38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /sampleapp/js/index.js: -------------------------------------------------------------------------------- 1 | 2 | var connect = false; 3 | var app = { 4 | // Application Constructor 5 | initialize: function() { 6 | this.bindEvents(); 7 | }, 8 | // Bind Event Listeners 9 | // 10 | // Bind any events that are required on startup. Common events are: 11 | // 'load', 'deviceready', 'offline', and 'online'. 12 | bindEvents: function() { 13 | document.addEventListener('deviceready', this.onDeviceReady, false); 14 | }, 15 | // deviceready Event Handler 16 | // 17 | // The scope of 'this' is the event. In order to call the 'receivedEvent' 18 | // function, we must explicitly call 'app.receivedEvent(...);' 19 | onDeviceReady: function() { 20 | app.receivedEvent('deviceready'); 21 | }, 22 | // Update DOM on a Received Event 23 | receivedEvent: function(id) { 24 | document.getElementById("connect").addEventListener('touchend',function(ev){ 25 | cordova.plugins.CordovaMqTTPlugin.connect({ 26 | url:document.getElementById("url").value, //a public broker used for testing purposes only. Try using a self hosted broker for production. 27 | port:document.getElementById("port").value, 28 | clientId:document.getElementById("clientId").value, 29 | success:function(s){ 30 | connect = true; 31 | console.log(JSON.stringify(s)); 32 | document.getElementById("connect").style.display = "none"; 33 | document.getElementById("disconnect").style.display = "block"; 34 | document.getElementById("activity").innerHTML += "--> Success: you are connected to, "+document.getElementById("url").value+":"+document.getElementById("port").value+"
" 35 | }, 36 | error:function(e){ 37 | connect = false; 38 | document.getElementById("activity").innerHTML += "--> Error: something is wrong,\n "+JSON.stringify(e)+"
"; 39 | document.getElementById("connect").style.display = "block"; 40 | document.getElementById("disconnect").style.display = "none"; 41 | alert("err!! something is wrong. check the console") 42 | console.log(e); 43 | }, 44 | onConnectionLost:function (){ 45 | connect = false; 46 | document.getElementById("activity").innerHTML += "--> You got disconnected"; 47 | document.getElementById("connect").style.display = "block"; 48 | document.getElementById("disconnect").style.display = "none"; 49 | } 50 | }) 51 | }); 52 | document.getElementById("disconnect").addEventListener('touchend',function(e){ 53 | document.getElementById("connect").style.display = "block"; 54 | document.getElementById("disconnect").style.display = "none"; 55 | cordova.plugins.CordovaMqTTPlugin.disconnect({ 56 | success:function(s){ 57 | connect = false; 58 | document.getElementById("connect").style.display = "block"; 59 | document.getElementById("disconnect").style.display = "none"; 60 | document.getElementById("activity").innerHTML += "--> Success: you are now disconnected"+"
" 61 | }, 62 | error:function(e){ 63 | document.getElementById("activity").innerHTML += "--> Error: something is wrong, "+e+"
"; 64 | document.getElementById("connect").style.display = "none"; 65 | document.getElementById("disconnect").style.display = "block"; 66 | //alert("err!! something is wrong. check the console") 67 | console.log(e); 68 | } 69 | }); 70 | }); 71 | document.getElementById("subscribe").addEventListener('touchend',function(ev){ 72 | if (!connect) { 73 | alert("First establish connection then try to subscribe"); 74 | } else { 75 | cordova.plugins.CordovaMqTTPlugin.subscribe({ 76 | topic:document.getElementById("topic_sub").value, 77 | qos:0, 78 | success:function(s){ 79 | document.getElementById("subscribe").style.display = "none"; 80 | document.getElementById("unsubscribe").style.display = "block"; 81 | document.getElementById("activity").innerHTML += "--> Success: you are subscribed to the topic, "+document.getElementById("topic_sub").value+"
" 82 | //get your payload here 83 | //Deprecated method 84 | document.addEventListener(document.getElementById("topic_sub").value,function (e) { 85 | e.preventDefault(); 86 | 87 | document.getElementById("activity").innerHTML += "--> Payload for"+e.topic+" topic: "+JSON.stringify(e.payload)+"
" 88 | }); 89 | 90 | cordova.plugins.CordovaMqTTPlugin.listen(document.getElementById("topic_sub").value,function (payload,params,topic,topic_pattern) { 91 | //params will be an empty object if topic pattern is NOT used. 92 | document.getElementById("activity").innerHTML += "--> Payload for"+topic+" topic: "+JSON.stringify(payload)+"
" 93 | }) 94 | }, 95 | error:function(e){ 96 | document.getElementById("activity").innerHTML += "--> Error: something is wrong when subscribing to this topic, "+e+"
"; 97 | document.getElementById("subscribe").style.display = "block"; 98 | document.getElementById("unsubscribe").style.display = "none"; 99 | //alert("err!! something is wrong. check the console") 100 | console.log(e); 101 | } 102 | }); 103 | } 104 | }); 105 | document.getElementById("unsubscribe").addEventListener('touchend',function(ev){ 106 | cordova.plugins.CordovaMqTTPlugin.unsubscribe({ 107 | topic:document.getElementById("topic_sub").value, 108 | success:function(s){ 109 | document.removeEventListener(document.getElementById("topic_sub").value); 110 | document.getElementById("unsubscribe").style.display = "none"; 111 | document.getElementById("subscribe").style.display = "block"; 112 | document.getElementById("activity").innerHTML += "--> Success: you are unsubscribed to the topic, "+document.getElementById("topic_sub").value+"
" 113 | document.getElementById("topic_sub").value = ""; 114 | }, 115 | error:function(e){ 116 | document.getElementById("activity").innerHTML += "--> Error: something is wrong, "+e+"
"; 117 | document.getElementById("subscribe").style.display = "block"; 118 | document.getElementById("unsubscribe").style.display = "none"; 119 | //alert("err!! something is wrong. check the console") 120 | console.log(e); 121 | } 122 | }); 123 | }); 124 | document.getElementById("publish").addEventListener('touchend',function(ev){ 125 | if (!connect) { 126 | alert("First establish connection then try to publish") 127 | } else { 128 | cordova.plugins.CordovaMqTTPlugin.publish({ 129 | topic:document.getElementById("topic_pub").value, 130 | payload:document.getElementById("payload").value, 131 | qos:0, 132 | retain:false, 133 | success:function(s){ 134 | document.getElementById("activity").innerHTML += "--> Success: you have published to the topic, "+document.getElementById("topic_sub").value+"
"; 135 | }, 136 | error:function(e){ 137 | document.getElementById("activity").innerHTML += "--> Error: something is wrong, "+e+"
"; 138 | //alert("err!! something is wrong. check the console") 139 | console.log(e); 140 | } 141 | }); 142 | } 143 | }); 144 | console.log('Received Event: ' + id); 145 | }, 146 | append:function (id,s) { 147 | // it is just a string append function. Nothing to do with the MQTT functions 148 | var node = document.createElement("p"); // Create a
  • node 149 | var textnode = document.createTextNode(s); // Create a text node 150 | node.appendChild(textnode); // Append the text to
  • 151 | document.getElementById(id).appendChild(node); // Append
  • to
      with id="myList" 152 | } 153 | }; 154 | 155 | app.initialize(); 156 | -------------------------------------------------------------------------------- /src/android/CordovaMqTTPlugin.java: -------------------------------------------------------------------------------- 1 | package com.arcoirislabs.plugin.mqtt; 2 | 3 | import android.util.Base64; 4 | import android.util.Log; 5 | 6 | import org.apache.cordova.CallbackContext; 7 | import org.apache.cordova.CordovaPlugin; 8 | import org.apache.cordova.PluginResult; 9 | import org.eclipse.paho.client.mqttv3.IMqttActionListener; 10 | import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; 11 | import org.eclipse.paho.client.mqttv3.IMqttToken; 12 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; 13 | import org.eclipse.paho.client.mqttv3.MqttCallback; 14 | import org.eclipse.paho.client.mqttv3.MqttConnectOptions; 15 | import org.eclipse.paho.client.mqttv3.MqttException; 16 | import org.eclipse.paho.client.mqttv3.MqttMessage; 17 | import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; 18 | import org.json.JSONArray; 19 | import org.json.JSONException; 20 | import org.json.JSONObject; 21 | 22 | /** 23 | * This class echoes a string called from JavaScript. 24 | */ 25 | public class CordovaMqTTPlugin extends CordovaPlugin { 26 | CallbackContext syncCB,asyncCB; 27 | MqttAsyncClient client; 28 | boolean connected; 29 | @Override 30 | public boolean execute(String action, final JSONArray args, CallbackContext callbackContext) throws JSONException { 31 | if(action.equals("connect")){ 32 | this.asyncCB = callbackContext; 33 | // if (connection== null){ 34 | // 35 | // }else{ 36 | // sendOnceUpdate("already connected"); 37 | // } 38 | 39 | cordova.getThreadPool().execute(new Runnable() { 40 | @Override 41 | public void run() { 42 | try { 43 | connect(args.getString(0), args.getString(1), args.getInt(2), args.getBoolean(3), args.getInt(4), args.getString(5), args.getString(6), args.getString(7), args.getString(8), args.getInt(9), args.getBoolean(10), args.getString(11), args.getBoolean(12), args.getBoolean(13)); 44 | } catch (JSONException e) { 45 | e.printStackTrace(); 46 | } 47 | } 48 | }); 49 | return true; 50 | } 51 | if(action.equals("publish")){ 52 | this.syncCB = callbackContext; 53 | // if (connection!= null){ 54 | // 55 | // }else{ 56 | // sendOnceUpdate("already connected"); 57 | // } 58 | cordova.getActivity().runOnUiThread(new Runnable() { 59 | @Override 60 | public void run() { 61 | try { 62 | publish(args); 63 | } catch (JSONException e) { 64 | e.printStackTrace(); 65 | } 66 | } 67 | }); 68 | return true; 69 | } 70 | if(action.equals("subscribe")){ 71 | 72 | this.syncCB = callbackContext; 73 | cordova.getActivity().runOnUiThread(new Runnable() { 74 | @Override 75 | public void run() { 76 | try { 77 | subscribe(args); 78 | } catch (JSONException e) { 79 | e.printStackTrace(); 80 | } 81 | } 82 | }); 83 | return true; 84 | } 85 | if(action.equals("disconnect")){ 86 | this.syncCB = callbackContext; 87 | cordova.getActivity().runOnUiThread(new Runnable() { 88 | @Override 89 | public void run() { 90 | disconnect(); 91 | } 92 | }); 93 | return true; 94 | } 95 | if(action.equals("unsubscribe")){ 96 | this.syncCB = callbackContext; 97 | cordova.getActivity().runOnUiThread(new Runnable() { 98 | @Override 99 | public void run() { 100 | try { 101 | unsubscribe(args); 102 | } catch (JSONException e) { 103 | e.printStackTrace(); 104 | } 105 | } 106 | }); 107 | return true; 108 | } 109 | 110 | return false; 111 | } 112 | 113 | private void connect(String url,String cid,int ka,boolean cleanSess,int connTimeOut,String uname, String pass,String willTopic,String willPayload,int willQos,boolean willRetain,String version,boolean isBinaryPayload,boolean isBinaryWillPayload) { 114 | MemoryPersistence persistence = new MemoryPersistence(); 115 | final MqttConnectOptions connOpts = new MqttConnectOptions(); 116 | connected = false; 117 | try { 118 | //Log.i("mqttalabs", "client id is " + cid); 119 | if (cid==null){ 120 | cid = client.generateClientId(); 121 | } 122 | connOpts.setCleanSession(cleanSess); 123 | connOpts.setKeepAliveInterval(ka); 124 | Log.i("mqttalabs", "username " + uname +" . Password is " + pass); 125 | 126 | client = new MqttAsyncClient(url, cid, persistence); 127 | client.setCallback(new MqttCallback() { 128 | @Override 129 | public void connectionLost(Throwable cause) { 130 | connected = false; 131 | Log.i("mqttalabs", cause.toString()); 132 | JSONObject dis = new JSONObject(); 133 | try { 134 | dis.put("type", "connectionLost"); 135 | dis.put("message", cause.toString()); 136 | dis.put("call", "disconnected"); 137 | dis.put("connectionStatus", client.isConnected()); 138 | sendUpdate(dis); 139 | } catch (JSONException e) { 140 | e.printStackTrace(); 141 | } 142 | } 143 | @Override 144 | public void messageArrived(String topic, MqttMessage message) throws Exception { 145 | //Log.i("mqttalabs", "topic is " + topic + ". payload is " + message.toString()); 146 | JSONObject dis = new JSONObject(); 147 | try { 148 | dis.put("type", "messageArrived"); 149 | dis.put("topic", topic); 150 | if (isBinaryPayload) { 151 | dis.put("payload", Base64.encodeToString(message.getPayload(), Base64.DEFAULT)); 152 | } else { 153 | dis.put("payload", message.toString()); 154 | } 155 | dis.put("call", "onPublish"); 156 | dis.put("connectionStatus", client.isConnected()); 157 | dis.put("qos",message.getQos()); 158 | dis.put("isRetained",message.isRetained()); 159 | dis.put("isDuplicate",message.isDuplicate()); 160 | sendUpdate(dis); 161 | } catch (JSONException e) { 162 | e.printStackTrace(); 163 | } 164 | } 165 | 166 | @Override 167 | public void deliveryComplete(IMqttDeliveryToken token) { 168 | try { 169 | token.waitForCompletion(); 170 | } catch (MqttException e) { 171 | e.printStackTrace(); 172 | } 173 | } 174 | }); 175 | if (willTopic!=null&&willPayload!=null&&willQos>-1){ 176 | byte[] willPayloadBytes; 177 | if (isBinaryWillPayload) { 178 | willPayloadBytes = Base64.decode(willPayload, Base64.DEFAULT); 179 | } else { 180 | willPayloadBytes = willPayload.getBytes(); 181 | } 182 | connOpts.setWill(willTopic,willPayloadBytes,willQos,willRetain); 183 | } 184 | 185 | if(uname.toString()=="null"&&pass.toString()=="null"){ 186 | Log.i("mqttalabs","not applying creds"); 187 | 188 | }else{ 189 | Log.i("mqttalabs","applying creds"); 190 | connOpts.setUserName(uname); 191 | connOpts.setPassword(pass.toCharArray()); 192 | } 193 | //connOpts.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1); 194 | connOpts.setConnectionTimeout(connTimeOut); 195 | client.connect(connOpts, null, new IMqttActionListener() { 196 | @Override 197 | public void onSuccess(IMqttToken asyncActionToken) { 198 | connected = true; 199 | JSONObject dis = new JSONObject(); 200 | try { 201 | dis.put("type", "connected"); 202 | dis.put("call", "connected"); 203 | dis.put("response", "connected"); 204 | dis.put("connectionStatus", client.isConnected()); 205 | sendUpdate(dis); 206 | } catch (JSONException e) { 207 | e.printStackTrace(); 208 | } 209 | } 210 | 211 | @Override 212 | public void onFailure(IMqttToken asyncActionToken, Throwable exception) { 213 | connected = false; 214 | JSONObject dis = new JSONObject(); 215 | try { 216 | dis.put("type", "failure"); 217 | dis.put("call", "failure"); 218 | dis.put("response", "fail to connect"); 219 | dis.put("message", exception.toString()); 220 | dis.put("connectionStatus", client.isConnected()); 221 | sendUpdate(dis); 222 | } catch (JSONException e) { 223 | e.printStackTrace(); 224 | } 225 | 226 | } 227 | }); 228 | } catch (MqttException e) { 229 | e.printStackTrace(); 230 | } 231 | } 232 | private void publish(JSONArray args) throws JSONException { 233 | final MqttMessage payload = new MqttMessage(); 234 | boolean binaryPayload = args.getBoolean(4); 235 | if (binaryPayload) { 236 | payload.setPayload(Base64.decode(args.getString(1), Base64.DEFAULT)); 237 | } else { 238 | payload.setPayload(args.getString(1).getBytes()); 239 | } 240 | payload.setQos(args.getInt(2)); 241 | payload.setRetained(args.getBoolean(3)); 242 | Log.i("mqttalabs", "Topic is " + args.getString(0) + ". Payload is " + args.getString(1)); 243 | try { 244 | if (client!=null){ 245 | client.publish(args.getString(0), payload, null, new IMqttActionListener() { 246 | @Override 247 | public void onSuccess(IMqttToken asyncActionToken) { 248 | JSONObject dis = new JSONObject(); 249 | try { 250 | dis.put("type", "publish"); 251 | dis.put("call", "success"); 252 | dis.put("response", "published"); 253 | dis.put("isPayloadDuplicate", payload.isDuplicate()); 254 | dis.put("qos", payload.getQos()); 255 | dis.put("connectionStatus", client.isConnected()); 256 | sendOnceUpdate(dis); 257 | } catch (JSONException e) { 258 | e.printStackTrace(); 259 | } 260 | } 261 | @Override 262 | public void onFailure(IMqttToken asyncActionToken, Throwable exception) { 263 | JSONObject dis = new JSONObject(); 264 | try { 265 | dis.put("type", "publish"); 266 | dis.put("call", "failure"); 267 | dis.put("response", "not published"); 268 | dis.put("isPayloadDuplicate", payload.isDuplicate()); 269 | dis.put("qos", payload.getQos()); 270 | dis.put("connectionStatus", client.isConnected()); 271 | sendOnceUpdate(dis); 272 | } catch (JSONException e) { 273 | e.printStackTrace(); 274 | } 275 | } 276 | }); 277 | }else{ 278 | Log.e("mqttalabs","client var is null"); 279 | } 280 | 281 | } catch (MqttException e) { 282 | e.printStackTrace(); 283 | } 284 | 285 | } 286 | private void subscribe(final JSONArray args) throws JSONException { 287 | try { 288 | client.subscribe(args.getString(0), args.getInt(1), null, new IMqttActionListener() { 289 | @Override 290 | public void onSuccess(IMqttToken asyncActionToken) { 291 | JSONObject dis = new JSONObject(); 292 | try { 293 | dis.put("type", "subscribe"); 294 | dis.put("call", "success"); 295 | dis.put("response", "subscribed to " + args.getString(0)); 296 | dis.put("connectionStatus", client.isConnected()); 297 | sendOnceUpdate(dis); 298 | } catch (JSONException e) { 299 | e.printStackTrace(); 300 | } 301 | } 302 | 303 | @Override 304 | public void onFailure(IMqttToken asyncActionToken, Throwable exception) { 305 | JSONObject dis = new JSONObject(); 306 | try { 307 | dis.put("type", "subscribe"); 308 | dis.put("call", "failure"); 309 | dis.put("response", "subscribed to " + args.getString(0)); 310 | dis.put("message", exception.getMessage()); 311 | dis.put("connectionStatus", client.isConnected()); 312 | sendOnceUpdate(dis); 313 | } catch (JSONException e) { 314 | e.printStackTrace(); 315 | } 316 | } 317 | }); 318 | } catch (MqttException e) { 319 | e.printStackTrace(); 320 | } 321 | } 322 | private void disconnect(){ 323 | try { 324 | 325 | client.disconnect(4, null, new IMqttActionListener() { 326 | @Override 327 | public void onSuccess(IMqttToken asyncActionToken) { 328 | try { 329 | JSONObject res = new JSONObject(); 330 | try { 331 | res.put("type","disconnect"); 332 | res.put("call","success"); 333 | res.put("connectionStatus",client.isConnected()); 334 | sendOnceUpdate(res); 335 | } catch (JSONException e) { 336 | e.printStackTrace(); 337 | } 338 | asyncActionToken.waitForCompletion(); 339 | } catch (MqttException e) { 340 | e.printStackTrace(); 341 | } 342 | Log.i("mqttalabs","disconnected"); 343 | } 344 | 345 | @Override 346 | public void onFailure(IMqttToken asyncActionToken, Throwable exception) { 347 | Log.i("mqttalabs"," cannot disconnect --> "+ exception.getMessage()); 348 | try { 349 | JSONObject res = new JSONObject(); 350 | try { 351 | res.put("type","disconnect"); 352 | res.put("call","failure"); 353 | res.put("connectionStatus",client.isConnected()); 354 | res.put("message",exception.toString()); 355 | sendOnceUpdate(res); 356 | } catch (JSONException e) { 357 | e.printStackTrace(); 358 | } 359 | asyncActionToken.waitForCompletion(); 360 | } catch (MqttException e) { 361 | e.printStackTrace(); 362 | } 363 | } 364 | }); 365 | } catch (MqttException e) { 366 | e.printStackTrace(); 367 | } 368 | } 369 | private void unsubscribe(final JSONArray args) throws JSONException { 370 | try { 371 | client.unsubscribe(args.getString(0), null, new IMqttActionListener() { 372 | @Override 373 | public void onSuccess(IMqttToken asyncActionToken) { 374 | try { 375 | JSONObject res = new JSONObject(); 376 | try { 377 | res.put("type","unsubscribe"); 378 | res.put("call","success"); 379 | res.put("connectionStatus",client.isConnected()); 380 | res.put("unsubscribedTopic",args.getString(0)); 381 | sendOnceUpdate(res); 382 | } catch (JSONException e) { 383 | e.printStackTrace(); 384 | } 385 | asyncActionToken.waitForCompletion(); 386 | } catch (MqttException e) { 387 | e.printStackTrace(); 388 | } 389 | } 390 | 391 | @Override 392 | public void onFailure(IMqttToken asyncActionToken, Throwable exception) { 393 | try { 394 | JSONObject res = new JSONObject(); 395 | try { 396 | res.put("type","unsubscribe"); 397 | res.put("call","failure"); 398 | res.put("connectionStatus",client.isConnected()); 399 | res.put("unsubscribedTopic",args.getString(0)); 400 | res.put("message",exception.toString()); 401 | sendOnceUpdate(res); 402 | } catch (JSONException e) { 403 | e.printStackTrace(); 404 | } 405 | asyncActionToken.waitForCompletion(); 406 | } catch (MqttException e) { 407 | e.printStackTrace(); 408 | } 409 | } 410 | }); 411 | } catch (MqttException e) { 412 | e.printStackTrace(); 413 | } 414 | } 415 | private void sendOnceUpdate(JSONObject message){ 416 | if (syncCB != null) { 417 | PluginResult result = new PluginResult(PluginResult.Status.OK,message); 418 | result.setKeepCallback(false); 419 | syncCB.sendPluginResult(result); 420 | 421 | Log.i("mqttalabs","\nfor subscribe the callback id is "+syncCB.getCallbackId()); 422 | } 423 | } 424 | private void sendUpdate(JSONObject message){ 425 | if (asyncCB != null) { 426 | PluginResult result = new PluginResult(PluginResult.Status.OK,message); 427 | result.setKeepCallback(true); 428 | asyncCB.sendPluginResult(result); 429 | 430 | Log.i("mqttalabs","\nfor subscribe the callback id is "+asyncCB.getCallbackId()); 431 | } 432 | } 433 | 434 | } 435 | -------------------------------------------------------------------------------- /src/ios/CordovaMQTTPlugin.m: -------------------------------------------------------------------------------- 1 | /********* CDVCordovaMQTTPlugin.m Cordova Plugin Implementation *******/ 2 | 3 | #import 4 | #import "MQTTAsync.h" 5 | @interface CDVCordovaMQTTPlugin : CDVPlugin { 6 | // Member variables go here. 7 | } 8 | 9 | - (void)coolMethod:(CDVInvokedUrlCommand*)command; 10 | @end 11 | 12 | @implementation CDVCordovaMQTTPlugin 13 | 14 | - (void)coolMethod:(CDVInvokedUrlCommand*)command 15 | { 16 | CDVPluginResult* pluginResult = nil; 17 | NSString* echo = [command.arguments objectAtIndex:0]; 18 | 19 | if (echo != nil && [echo length] > 0) { 20 | pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:echo]; 21 | } else { 22 | pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR]; 23 | } 24 | 25 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /src/ios/MQTTAsync.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2009, 2016 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation 15 | * Ian Craggs, Allan Stockdill-Mander - SSL connections 16 | * Ian Craggs - multiple server connection support 17 | * Ian Craggs - MQTT 3.1.1 support 18 | * Ian Craggs - fix for bug 444103 - success/failure callbacks not invoked 19 | * Ian Craggs - automatic reconnect and offline buffering (send while disconnected) 20 | *******************************************************************************/ 21 | 22 | /********************************************************************/ 23 | 24 | /** 25 | * @cond MQTTAsync_main 26 | * @mainpage Asynchronous MQTT client library for C 27 | * 28 | * © Copyright IBM Corp. 2009, 2016 29 | * 30 | * @brief An Asynchronous MQTT client library for C. 31 | * 32 | * An MQTT client application connects to MQTT-capable servers. 33 | * A typical client is responsible for collecting information from a telemetry 34 | * device and publishing the information to the server. It can also subscribe 35 | * to topics, receive messages, and use this information to control the 36 | * telemetry device. 37 | * 38 | * MQTT clients implement the published MQTT v3 protocol. You can write your own 39 | * API to the MQTT protocol using the programming language and platform of your 40 | * choice. This can be time-consuming and error-prone. 41 | * 42 | * To simplify writing MQTT client applications, this library encapsulates 43 | * the MQTT v3 protocol for you. Using this library enables a fully functional 44 | * MQTT client application to be written in a few lines of code. 45 | * The information presented here documents the API provided 46 | * by the Asynchronous MQTT Client library for C. 47 | * 48 | * Using the client
      49 | * Applications that use the client library typically use a similar structure: 50 | *
        51 | *
      • Create a client object
      • 52 | *
      • Set the options to connect to an MQTT server
      • 53 | *
      • Set up callback functions
      • 54 | *
      • Connect the client to an MQTT server
      • 55 | *
      • Subscribe to any topics the client needs to receive
      • 56 | *
      • Repeat until finished:
      • 57 | *
          58 | *
        • Publish any messages the client needs to
        • 59 | *
        • Handle any incoming messages
        • 60 | *
        61 | *
      • Disconnect the client
      • 62 | *
      • Free any memory being used by the client
      • 63 | *
      64 | * Some simple examples are shown here: 65 | *
        66 | *
      • @ref publish
      • 67 | *
      • @ref subscribe
      • 68 | *
      69 | * Additional information about important concepts is provided here: 70 | *
        71 | *
      • @ref async
      • 72 | *
      • @ref wildcard
      • 73 | *
      • @ref qos
      • 74 | *
      • @ref tracing
      • 75 | *
      76 | * @endcond 77 | */ 78 | 79 | 80 | /// @cond EXCLUDE 81 | #if defined(__cplusplus) 82 | extern "C" { 83 | #endif 84 | 85 | #if !defined(MQTTASYNC_H) 86 | #define MQTTASYNC_H 87 | 88 | #if defined(WIN32) || defined(WIN64) 89 | #define DLLImport __declspec(dllimport) 90 | #define DLLExport __declspec(dllexport) 91 | #else 92 | #define DLLImport extern 93 | #define DLLExport __attribute__ ((visibility ("default"))) 94 | #endif 95 | 96 | #include 97 | /// @endcond 98 | 99 | #if !defined(NO_PERSISTENCE) 100 | #include "MQTTClientPersistence.h" 101 | #endif 102 | 103 | /** 104 | * Return code: No error. Indicates successful completion of an MQTT client 105 | * operation. 106 | */ 107 | #define MQTTASYNC_SUCCESS 0 108 | /** 109 | * Return code: A generic error code indicating the failure of an MQTT client 110 | * operation. 111 | */ 112 | #define MQTTASYNC_FAILURE -1 113 | 114 | /* error code -2 is MQTTAsync_PERSISTENCE_ERROR */ 115 | 116 | #define MQTTASYNC_PERSISTENCE_ERROR -2 117 | 118 | /** 119 | * Return code: The client is disconnected. 120 | */ 121 | #define MQTTASYNC_DISCONNECTED -3 122 | /** 123 | * Return code: The maximum number of messages allowed to be simultaneously 124 | * in-flight has been reached. 125 | */ 126 | #define MQTTASYNC_MAX_MESSAGES_INFLIGHT -4 127 | /** 128 | * Return code: An invalid UTF-8 string has been detected. 129 | */ 130 | #define MQTTASYNC_BAD_UTF8_STRING -5 131 | /** 132 | * Return code: A NULL parameter has been supplied when this is invalid. 133 | */ 134 | #define MQTTASYNC_NULL_PARAMETER -6 135 | /** 136 | * Return code: The topic has been truncated (the topic string includes 137 | * embedded NULL characters). String functions will not access the full topic. 138 | * Use the topic length value to access the full topic. 139 | */ 140 | #define MQTTASYNC_TOPICNAME_TRUNCATED -7 141 | /** 142 | * Return code: A structure parameter does not have the correct eyecatcher 143 | * and version number. 144 | */ 145 | #define MQTTASYNC_BAD_STRUCTURE -8 146 | /** 147 | * Return code: A qos parameter is not 0, 1 or 2 148 | */ 149 | #define MQTTASYNC_BAD_QOS -9 150 | /** 151 | * Return code: All 65535 MQTT msgids are being used 152 | */ 153 | #define MQTTASYNC_NO_MORE_MSGIDS -10 154 | /** 155 | * Return code: the request is being discarded when not complete 156 | */ 157 | #define MQTTASYNC_OPERATION_INCOMPLETE -11 158 | /** 159 | * Return code: no more messages can be buffered 160 | */ 161 | #define MQTTASYNC_MAX_BUFFERED_MESSAGES -12 162 | 163 | /** 164 | * Default MQTT version to connect with. Use 3.1.1 then fall back to 3.1 165 | */ 166 | #define MQTTVERSION_DEFAULT 0 167 | /** 168 | * MQTT version to connect with: 3.1 169 | */ 170 | #define MQTTVERSION_3_1 3 171 | /** 172 | * MQTT version to connect with: 3.1.1 173 | */ 174 | #define MQTTVERSION_3_1_1 4 175 | /** 176 | * Bad return code from subscribe, as defined in the 3.1.1 specification 177 | */ 178 | #define MQTT_BAD_SUBSCRIBE 0x80 179 | 180 | /** 181 | * A handle representing an MQTT client. A valid client handle is available 182 | * following a successful call to MQTTAsync_create(). 183 | */ 184 | typedef void* MQTTAsync; 185 | /** 186 | * A value representing an MQTT message. A token is returned to the 187 | * client application when a message is published. The token can then be used to 188 | * check that the message was successfully delivered to its destination (see 189 | * MQTTAsync_publish(), 190 | * MQTTAsync_publishMessage(), 191 | * MQTTAsync_deliveryComplete(), and 192 | * MQTTAsync_getPendingTokens()). 193 | */ 194 | typedef int MQTTAsync_token; 195 | 196 | /** 197 | * A structure representing the payload and attributes of an MQTT message. The 198 | * message topic is not part of this structure (see MQTTAsync_publishMessage(), 199 | * MQTTAsync_publish(), MQTTAsync_receive(), MQTTAsync_freeMessage() 200 | * and MQTTAsync_messageArrived()). 201 | */ 202 | typedef struct 203 | { 204 | /** The eyecatcher for this structure. must be MQTM. */ 205 | char struct_id[4]; 206 | /** The version number of this structure. Must be 0 */ 207 | int struct_version; 208 | /** The length of the MQTT message payload in bytes. */ 209 | int payloadlen; 210 | /** A pointer to the payload of the MQTT message. */ 211 | void* payload; 212 | /** 213 | * The quality of service (QoS) assigned to the message. 214 | * There are three levels of QoS: 215 | *
      216 | *
      QoS0
      217 | *
      Fire and forget - the message may not be delivered
      218 | *
      QoS1
      219 | *
      At least once - the message will be delivered, but may be 220 | * delivered more than once in some circumstances.
      221 | *
      QoS2
      222 | *
      Once and one only - the message will be delivered exactly once.
      223 | *
      224 | */ 225 | int qos; 226 | /** 227 | * The retained flag serves two purposes depending on whether the message 228 | * it is associated with is being published or received. 229 | * 230 | * retained = true
      231 | * For messages being published, a true setting indicates that the MQTT 232 | * server should retain a copy of the message. The message will then be 233 | * transmitted to new subscribers to a topic that matches the message topic. 234 | * For subscribers registering a new subscription, the flag being true 235 | * indicates that the received message is not a new one, but one that has 236 | * been retained by the MQTT server. 237 | * 238 | * retained = false
      239 | * For publishers, this ndicates that this message should not be retained 240 | * by the MQTT server. For subscribers, a false setting indicates this is 241 | * a normal message, received as a result of it being published to the 242 | * server. 243 | */ 244 | int retained; 245 | /** 246 | * The dup flag indicates whether or not this message is a duplicate. 247 | * It is only meaningful when receiving QoS1 messages. When true, the 248 | * client application should take appropriate action to deal with the 249 | * duplicate message. 250 | */ 251 | int dup; 252 | /** The message identifier is normally reserved for internal use by the 253 | * MQTT client and server. 254 | */ 255 | int msgid; 256 | } MQTTAsync_message; 257 | 258 | #define MQTTAsync_message_initializer { {'M', 'Q', 'T', 'M'}, 0, 0, NULL, 0, 0, 0, 0 } 259 | 260 | /** 261 | * This is a callback function. The client application 262 | * must provide an implementation of this function to enable asynchronous 263 | * receipt of messages. The function is registered with the client library by 264 | * passing it as an argument to MQTTAsync_setCallbacks(). It is 265 | * called by the client library when a new message that matches a client 266 | * subscription has been received from the server. This function is executed on 267 | * a separate thread to the one on which the client application is running. 268 | * @param context A pointer to the context value originally passed to 269 | * MQTTAsync_setCallbacks(), which contains any application-specific context. 270 | * @param topicName The topic associated with the received message. 271 | * @param topicLen The length of the topic if there are one 272 | * more NULL characters embedded in topicName, otherwise topicLen 273 | * is 0. If topicLen is 0, the value returned by strlen(topicName) 274 | * can be trusted. If topicLen is greater than 0, the full topic name 275 | * can be retrieved by accessing topicName as a byte array of length 276 | * topicLen. 277 | * @param message The MQTTAsync_message structure for the received message. 278 | * This structure contains the message payload and attributes. 279 | * @return This function must return a boolean value indicating whether or not 280 | * the message has been safely received by the client application. Returning 281 | * true indicates that the message has been successfully handled. 282 | * Returning false indicates that there was a problem. In this 283 | * case, the client library will reinvoke MQTTAsync_messageArrived() to 284 | * attempt to deliver the message to the application again. 285 | */ 286 | typedef int MQTTAsync_messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* message); 287 | 288 | /** 289 | * This is a callback function. The client application 290 | * must provide an implementation of this function to enable asynchronous 291 | * notification of delivery of messages to the server. The function is 292 | * registered with the client library by passing it as an argument to MQTTAsync_setCallbacks(). 293 | * It is called by the client library after the client application has 294 | * published a message to the server. It indicates that the necessary 295 | * handshaking and acknowledgements for the requested quality of service (see 296 | * MQTTAsync_message.qos) have been completed. This function is executed on a 297 | * separate thread to the one on which the client application is running. 298 | * @param context A pointer to the context value originally passed to 299 | * MQTTAsync_setCallbacks(), which contains any application-specific context. 300 | * @param token The ::MQTTAsync_token associated with 301 | * the published message. Applications can check that all messages have been 302 | * correctly published by matching the tokens returned from calls to 303 | * MQTTAsync_send() and MQTTAsync_sendMessage() with the tokens passed 304 | * to this callback. 305 | */ 306 | typedef void MQTTAsync_deliveryComplete(void* context, MQTTAsync_token token); 307 | 308 | /** 309 | * This is a callback function. The client application 310 | * must provide an implementation of this function to enable asynchronous 311 | * notification of the loss of connection to the server. The function is 312 | * registered with the client library by passing it as an argument to 313 | * MQTTAsync_setCallbacks(). It is called by the client library if the client 314 | * loses its connection to the server. The client application must take 315 | * appropriate action, such as trying to reconnect or reporting the problem. 316 | * This function is executed on a separate thread to the one on which the 317 | * client application is running. 318 | * @param context A pointer to the context value originally passed to 319 | * MQTTAsync_setCallbacks(), which contains any application-specific context. 320 | * @param cause The reason for the disconnection. 321 | * Currently, cause is always set to NULL. 322 | */ 323 | typedef void MQTTAsync_connectionLost(void* context, char* cause); 324 | 325 | 326 | /** 327 | * This is a callback function, which will be called when the client 328 | * library successfully connects. This is superfluous when the connection 329 | * is made in response to a MQTTAsync_connect call, because the onSuccess 330 | * callback can be used. It is intended for use when automatic reconnect 331 | * is enabled, so that when a reconnection attempt succeeds in the background, 332 | * the application is notified and can take any required actions. 333 | * @param context A pointer to the context value originally passed to 334 | * MQTTAsync_setCallbacks(), which contains any application-specific context. 335 | * @param cause The reason for the disconnection. 336 | * Currently, cause is always set to NULL. 337 | */ 338 | typedef void MQTTAsync_connected(void* context, char* cause); 339 | 340 | 341 | 342 | /** The data returned on completion of an unsuccessful API call in the response callback onFailure. */ 343 | typedef struct 344 | { 345 | /** A token identifying the failed request. */ 346 | MQTTAsync_token token; 347 | /** A numeric code identifying the error. */ 348 | int code; 349 | /** Optional text explaining the error. Can be NULL. */ 350 | char* message; 351 | } MQTTAsync_failureData; 352 | 353 | /** The data returned on completion of a successful API call in the response callback onSuccess. */ 354 | typedef struct 355 | { 356 | /** A token identifying the successful request. Can be used to refer to the request later. */ 357 | MQTTAsync_token token; 358 | /** A union of the different values that can be returned for subscribe, unsubscribe and publish. */ 359 | union 360 | { 361 | /** For subscribe, the granted QoS of the subscription returned by the server. */ 362 | int qos; 363 | /** For subscribeMany, the list of granted QoSs of the subscriptions returned by the server. */ 364 | int* qosList; 365 | /** For publish, the message being sent to the server. */ 366 | struct 367 | { 368 | MQTTAsync_message message; 369 | char* destinationName; 370 | } pub; 371 | /* For connect, the server connected to, MQTT version used, and sessionPresent flag */ 372 | struct 373 | { 374 | char* serverURI; 375 | int MQTTVersion; 376 | int sessionPresent; 377 | } connect; 378 | } alt; 379 | } MQTTAsync_successData; 380 | 381 | /** 382 | * This is a callback function. The client application 383 | * must provide an implementation of this function to enable asynchronous 384 | * notification of the successful completion of an API call. The function is 385 | * registered with the client library by passing it as an argument in 386 | * ::MQTTAsync_responseOptions. 387 | * @param context A pointer to the context value originally passed to 388 | * ::MQTTAsync_responseOptions, which contains any application-specific context. 389 | * @param response Any success data associated with the API completion. 390 | */ 391 | typedef void MQTTAsync_onSuccess(void* context, MQTTAsync_successData* response); 392 | 393 | /** 394 | * This is a callback function. The client application 395 | * must provide an implementation of this function to enable asynchronous 396 | * notification of the unsuccessful completion of an API call. The function is 397 | * registered with the client library by passing it as an argument in 398 | * ::MQTTAsync_responseOptions. 399 | * @param context A pointer to the context value originally passed to 400 | * ::MQTTAsync_responseOptions, which contains any application-specific context. 401 | * @param response Any failure data associated with the API completion. 402 | */ 403 | typedef void MQTTAsync_onFailure(void* context, MQTTAsync_failureData* response); 404 | 405 | typedef struct 406 | { 407 | /** The eyecatcher for this structure. Must be MQTR */ 408 | char struct_id[4]; 409 | /** The version number of this structure. Must be 0 */ 410 | int struct_version; 411 | /** 412 | * A pointer to a callback function to be called if the API call successfully 413 | * completes. Can be set to NULL, in which case no indication of successful 414 | * completion will be received. 415 | */ 416 | MQTTAsync_onSuccess* onSuccess; 417 | /** 418 | * A pointer to a callback function to be called if the API call fails. 419 | * Can be set to NULL, in which case no indication of unsuccessful 420 | * completion will be received. 421 | */ 422 | MQTTAsync_onFailure* onFailure; 423 | /** 424 | * A pointer to any application-specific context. The 425 | * the context pointer is passed to success or failure callback functions to 426 | * provide access to the context information in the callback. 427 | */ 428 | void* context; 429 | MQTTAsync_token token; /* output */ 430 | } MQTTAsync_responseOptions; 431 | 432 | #define MQTTAsync_responseOptions_initializer { {'M', 'Q', 'T', 'R'}, 0, NULL, NULL, 0, 0 } 433 | 434 | 435 | /** 436 | * This function sets the global callback functions for a specific client. 437 | * If your client application doesn't use a particular callback, set the 438 | * relevant parameter to NULL. Any necessary message acknowledgements and 439 | * status communications are handled in the background without any intervention 440 | * from the client application. If you do not set a messageArrived callback 441 | * function, you will not be notified of the receipt of any messages as a 442 | * result of a subscription. 443 | * 444 | * Note: The MQTT client must be disconnected when this function is 445 | * called. 446 | * @param handle A valid client handle from a successful call to 447 | * MQTTAsync_create(). 448 | * @param context A pointer to any application-specific context. The 449 | * the context pointer is passed to each of the callback functions to 450 | * provide access to the context information in the callback. 451 | * @param cl A pointer to an MQTTAsync_connectionLost() callback 452 | * function. You can set this to NULL if your application doesn't handle 453 | * disconnections. 454 | * @param ma A pointer to an MQTTAsync_messageArrived() callback 455 | * function. You can set this to NULL if your application doesn't handle 456 | * receipt of messages. 457 | * @param dc A pointer to an MQTTAsync_deliveryComplete() callback 458 | * function. You can set this to NULL if you do not want to check 459 | * for successful delivery. 460 | * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set, 461 | * ::MQTTASYNC_FAILURE if an error occurred. 462 | */ 463 | DLLExport int MQTTAsync_setCallbacks(MQTTAsync handle, void* context, MQTTAsync_connectionLost* cl, 464 | MQTTAsync_messageArrived* ma, MQTTAsync_deliveryComplete* dc); 465 | 466 | 467 | /** 468 | * Sets the MQTTAsync_connected() callback function for a client. 469 | * @param handle A valid client handle from a successful call to 470 | * MQTTAsync_create(). 471 | * @param context A pointer to any application-specific context. The 472 | * the context pointer is passed to each of the callback functions to 473 | * provide access to the context information in the callback. 474 | * @param co A pointer to an MQTTAsync_connected() callback 475 | * function. NULL removes the callback setting. 476 | * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set, 477 | * ::MQTTASYNC_FAILURE if an error occurred. 478 | */ 479 | DLLExport int MQTTAsync_setConnected(MQTTAsync handle, void* context, MQTTAsync_connected* co); 480 | 481 | 482 | /** 483 | * Reconnects a client with the previously used connect options. Connect 484 | * must have previously been called for this to work. 485 | * @param handle A valid client handle from a successful call to 486 | * MQTTAsync_create(). 487 | * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set, 488 | * ::MQTTASYNC_FAILURE if an error occurred. 489 | */ 490 | DLLExport int MQTTAsync_reconnect(MQTTAsync handle); 491 | 492 | 493 | /** 494 | * This function creates an MQTT client ready for connection to the 495 | * specified server and using the specified persistent storage (see 496 | * MQTTAsync_persistence). See also MQTTAsync_destroy(). 497 | * @param handle A pointer to an ::MQTTAsync handle. The handle is 498 | * populated with a valid client reference following a successful return from 499 | * this function. 500 | * @param serverURI A null-terminated string specifying the server to 501 | * which the client will connect. It takes the form protocol://host:port. 502 | * protocol must be tcp or ssl. For host, you can 503 | * specify either an IP address or a host name. For instance, to connect to 504 | * a server running on the local machines with the default MQTT port, specify 505 | * tcp://localhost:1883. 506 | * @param clientId The client identifier passed to the server when the 507 | * client connects to it. It is a null-terminated UTF-8 encoded string. 508 | * ClientIDs must be no longer than 23 characters according to the MQTT 509 | * specification. 510 | * @param persistence_type The type of persistence to be used by the client: 511 | *
      512 | * ::MQTTCLIENT_PERSISTENCE_NONE: Use in-memory persistence. If the device or 513 | * system on which the client is running fails or is switched off, the current 514 | * state of any in-flight messages is lost and some messages may not be 515 | * delivered even at QoS1 and QoS2. 516 | *
      517 | * ::MQTTCLIENT_PERSISTENCE_DEFAULT: Use the default (file system-based) 518 | * persistence mechanism. Status about in-flight messages is held in persistent 519 | * storage and provides some protection against message loss in the case of 520 | * unexpected failure. 521 | *
      522 | * ::MQTTCLIENT_PERSISTENCE_USER: Use an application-specific persistence 523 | * implementation. Using this type of persistence gives control of the 524 | * persistence mechanism to the application. The application has to implement 525 | * the MQTTClient_persistence interface. 526 | * @param persistence_context If the application uses 527 | * ::MQTTCLIENT_PERSISTENCE_NONE persistence, this argument is unused and should 528 | * be set to NULL. For ::MQTTCLIENT_PERSISTENCE_DEFAULT persistence, it 529 | * should be set to the location of the persistence directory (if set 530 | * to NULL, the persistence directory used is the working directory). 531 | * Applications that use ::MQTTCLIENT_PERSISTENCE_USER persistence set this 532 | * argument to point to a valid MQTTClient_persistence structure. 533 | * @return ::MQTTASYNC_SUCCESS if the client is successfully created, otherwise 534 | * an error code is returned. 535 | */ 536 | DLLExport int MQTTAsync_create(MQTTAsync* handle, const char* serverURI, const char* clientId, 537 | int persistence_type, void* persistence_context); 538 | 539 | typedef struct 540 | { 541 | /** The eyecatcher for this structure. must be MQCO. */ 542 | const char struct_id[4]; 543 | /** The version number of this structure. Must be 0 */ 544 | int struct_version; 545 | /** Whether to allow messages to be sent when the client library is not connected. */ 546 | int sendWhileDisconnected; 547 | /** the maximum number of messages allowed to be buffered while not connected. */ 548 | int maxBufferedMessages; 549 | } MQTTAsync_createOptions; 550 | 551 | #define MQTTAsync_createOptions_initializer { {'M', 'Q', 'C', 'O'}, 0, 0, 100 } 552 | 553 | 554 | DLLExport int MQTTAsync_createWithOptions(MQTTAsync* handle, const char* serverURI, const char* clientId, 555 | int persistence_type, void* persistence_context, MQTTAsync_createOptions* options); 556 | 557 | /** 558 | * MQTTAsync_willOptions defines the MQTT "Last Will and Testament" (LWT) settings for 559 | * the client. In the event that a client unexpectedly loses its connection to 560 | * the server, the server publishes the LWT message to the LWT topic on 561 | * behalf of the client. This allows other clients (subscribed to the LWT topic) 562 | * to be made aware that the client has disconnected. To enable the LWT 563 | * function for a specific client, a valid pointer to an MQTTAsync_willOptions 564 | * structure is passed in the MQTTAsync_connectOptions structure used in the 565 | * MQTTAsync_connect() call that connects the client to the server. The pointer 566 | * to MQTTAsync_willOptions can be set to NULL if the LWT function is not 567 | * required. 568 | */ 569 | typedef struct 570 | { 571 | /** The eyecatcher for this structure. must be MQTW. */ 572 | const char struct_id[4]; 573 | /** The version number of this structure. Must be 0 */ 574 | int struct_version; 575 | /** The LWT topic to which the LWT message will be published. */ 576 | const char* topicName; 577 | /** The LWT payload. */ 578 | const char* message; 579 | /** 580 | * The retained flag for the LWT message (see MQTTAsync_message.retained). 581 | */ 582 | int retained; 583 | /** 584 | * The quality of service setting for the LWT message (see 585 | * MQTTAsync_message.qos and @ref qos). 586 | */ 587 | int qos; 588 | } MQTTAsync_willOptions; 589 | 590 | #define MQTTAsync_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, NULL, NULL, 0, 0 } 591 | 592 | /** 593 | * MQTTAsync_sslProperties defines the settings to establish an SSL/TLS connection using the 594 | * OpenSSL library. It covers the following scenarios: 595 | * - Server authentication: The client needs the digital certificate of the server. It is included 596 | * in a store containting trusted material (also known as "trust store"). 597 | * - Mutual authentication: Both client and server are authenticated during the SSL handshake. In 598 | * addition to the digital certificate of the server in a trust store, the client will need its own 599 | * digital certificate and the private key used to sign its digital certificate stored in a "key store". 600 | * - Anonymous connection: Both client and server do not get authenticated and no credentials are needed 601 | * to establish an SSL connection. Note that this scenario is not fully secure since it is subject to 602 | * man-in-the-middle attacks. 603 | */ 604 | typedef struct 605 | { 606 | /** The eyecatcher for this structure. Must be MQTS */ 607 | const char struct_id[4]; 608 | /** The version number of this structure. Must be 0 */ 609 | int struct_version; 610 | 611 | /** The file in PEM format containing the public digital certificates trusted by the client. */ 612 | const char* trustStore; 613 | 614 | /** The file in PEM format containing the public certificate chain of the client. It may also include 615 | * the client's private key. 616 | */ 617 | const char* keyStore; 618 | 619 | /** If not included in the sslKeyStore, this setting points to the file in PEM format containing 620 | * the client's private key. 621 | */ 622 | const char* privateKey; 623 | /** The password to load the client's privateKey if encrypted. */ 624 | const char* privateKeyPassword; 625 | 626 | /** 627 | * The list of cipher suites that the client will present to the server during the SSL handshake. For a 628 | * full explanation of the cipher list format, please see the OpenSSL on-line documentation: 629 | * http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT 630 | * If this setting is ommitted, its default value will be "ALL", that is, all the cipher suites -excluding 631 | * those offering no encryption- will be considered. 632 | * This setting can be used to set an SSL anonymous connection ("aNULL" string value, for instance). 633 | */ 634 | const char* enabledCipherSuites; 635 | 636 | /** True/False option to enable verification of the server certificate **/ 637 | int enableServerCertAuth; 638 | 639 | } MQTTAsync_SSLOptions; 640 | 641 | #define MQTTAsync_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 0, NULL, NULL, NULL, NULL, NULL, 1 } 642 | 643 | /** 644 | * MQTTAsync_connectOptions defines several settings that control the way the 645 | * client connects to an MQTT server. Default values are set in 646 | * MQTTAsync_connectOptions_initializer. 647 | */ 648 | typedef struct 649 | { 650 | /** The eyecatcher for this structure. must be MQTC. */ 651 | const char struct_id[4]; 652 | /** The version number of this structure. Must be 0, 1, 2, 3 or 4. 653 | * 0 signifies no SSL options and no serverURIs 654 | * 1 signifies no serverURIs 655 | * 2 signifies no MQTTVersion 656 | * 3 signifies no automatic reconnect options 657 | */ 658 | int struct_version; 659 | /** The "keep alive" interval, measured in seconds, defines the maximum time 660 | * that should pass without communication between the client and the server 661 | * The client will ensure that at least one message travels across the 662 | * network within each keep alive period. In the absence of a data-related 663 | * message during the time period, the client sends a very small MQTT 664 | * "ping" message, which the server will acknowledge. The keep alive 665 | * interval enables the client to detect when the server is no longer 666 | * available without having to wait for the long TCP/IP timeout. 667 | * Set to 0 if you do not want any keep alive processing. 668 | */ 669 | int keepAliveInterval; 670 | /** 671 | * This is a boolean value. The cleansession setting controls the behaviour 672 | * of both the client and the server at connection and disconnection time. 673 | * The client and server both maintain session state information. This 674 | * information is used to ensure "at least once" and "exactly once" 675 | * delivery, and "exactly once" receipt of messages. Session state also 676 | * includes subscriptions created by an MQTT client. You can choose to 677 | * maintain or discard state information between sessions. 678 | * 679 | * When cleansession is true, the state information is discarded at 680 | * connect and disconnect. Setting cleansession to false keeps the state 681 | * information. When you connect an MQTT client application with 682 | * MQTTAsync_connect(), the client identifies the connection using the 683 | * client identifier and the address of the server. The server checks 684 | * whether session information for this client 685 | * has been saved from a previous connection to the server. If a previous 686 | * session still exists, and cleansession=true, then the previous session 687 | * information at the client and server is cleared. If cleansession=false, 688 | * the previous session is resumed. If no previous session exists, a new 689 | * session is started. 690 | */ 691 | int cleansession; 692 | /** 693 | * This controls how many messages can be in-flight simultaneously. 694 | */ 695 | int maxInflight; 696 | /** 697 | * This is a pointer to an MQTTAsync_willOptions structure. If your 698 | * application does not make use of the Last Will and Testament feature, 699 | * set this pointer to NULL. 700 | */ 701 | MQTTAsync_willOptions* will; 702 | /** 703 | * MQTT servers that support the MQTT v3.1 protocol provide authentication 704 | * and authorisation by user name and password. This is the user name 705 | * parameter. 706 | */ 707 | const char* username; 708 | /** 709 | * MQTT servers that support the MQTT v3.1 protocol provide authentication 710 | * and authorisation by user name and password. This is the password 711 | * parameter. 712 | */ 713 | const char* password; 714 | /** 715 | * The time interval in seconds to allow a connect to complete. 716 | */ 717 | int connectTimeout; 718 | /** 719 | * The time interval in seconds 720 | */ 721 | int retryInterval; 722 | /** 723 | * This is a pointer to an MQTTAsync_SSLOptions structure. If your 724 | * application does not make use of SSL, set this pointer to NULL. 725 | */ 726 | MQTTAsync_SSLOptions* ssl; 727 | /** 728 | * A pointer to a callback function to be called if the connect successfully 729 | * completes. Can be set to NULL, in which case no indication of successful 730 | * completion will be received. 731 | */ 732 | MQTTAsync_onSuccess* onSuccess; 733 | /** 734 | * A pointer to a callback function to be called if the connect fails. 735 | * Can be set to NULL, in which case no indication of unsuccessful 736 | * completion will be received. 737 | */ 738 | MQTTAsync_onFailure* onFailure; 739 | /** 740 | * A pointer to any application-specific context. The 741 | * the context pointer is passed to success or failure callback functions to 742 | * provide access to the context information in the callback. 743 | */ 744 | void* context; 745 | /** 746 | * The number of entries in the serverURIs array. 747 | */ 748 | int serverURIcount; 749 | /** 750 | * An array of null-terminated strings specifying the servers to 751 | * which the client will connect. Each string takes the form protocol://host:port. 752 | * protocol must be tcp or ssl. For host, you can 753 | * specify either an IP address or a domain name. For instance, to connect to 754 | * a server running on the local machines with the default MQTT port, specify 755 | * tcp://localhost:1883. 756 | */ 757 | char* const* serverURIs; 758 | /** 759 | * Sets the version of MQTT to be used on the connect. 760 | * MQTTVERSION_DEFAULT (0) = default: start with 3.1.1, and if that fails, fall back to 3.1 761 | * MQTTVERSION_3_1 (3) = only try version 3.1 762 | * MQTTVERSION_3_1_1 (4) = only try version 3.1.1 763 | */ 764 | int MQTTVersion; 765 | /** 766 | * Reconnect automatically in the case of a connection being lost? 767 | */ 768 | int automaticReconnect; 769 | /** 770 | * Minimum retry interval in seconds. Doubled on each failed retry. 771 | */ 772 | int minRetryInterval; 773 | /** 774 | * Maximum retry interval in seconds. The doubling stops here on failed retries. 775 | */ 776 | int maxRetryInterval; 777 | } MQTTAsync_connectOptions; 778 | 779 | 780 | #define MQTTAsync_connectOptions_initializer { {'M', 'Q', 'T', 'C'}, 4, 60, 1, 10, NULL, NULL, NULL, 30, 0,\ 781 | NULL, NULL, NULL, NULL, 0, NULL, 0, 0, 1, 60} 782 | 783 | /** 784 | * This function attempts to connect a previously-created client (see 785 | * MQTTAsync_create()) to an MQTT server using the specified options. If you 786 | * want to enable asynchronous message and status notifications, you must call 787 | * MQTTAsync_setCallbacks() prior to MQTTAsync_connect(). 788 | * @param handle A valid client handle from a successful call to 789 | * MQTTAsync_create(). 790 | * @param options A pointer to a valid MQTTAsync_connectOptions 791 | * structure. 792 | * @return ::MQTTASYNC_SUCCESS if the client connect request was accepted. 793 | * If the client was unable to connect to the server, an error code is 794 | * returned via the onFailure callback, if set. 795 | * Error codes greater than 0 are returned by the MQTT protocol:

      796 | * 1: Connection refused: Unacceptable protocol version
      797 | * 2: Connection refused: Identifier rejected
      798 | * 3: Connection refused: Server unavailable
      799 | * 4: Connection refused: Bad user name or password
      800 | * 5: Connection refused: Not authorized
      801 | * 6-255: Reserved for future use
      802 | */ 803 | DLLExport int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options); 804 | 805 | 806 | typedef struct 807 | { 808 | /** The eyecatcher for this structure. Must be MQTD. */ 809 | const char struct_id[4]; 810 | /** The version number of this structure. Must be 0 or 1. 0 signifies no SSL options */ 811 | int struct_version; 812 | /** 813 | * The client delays disconnection for up to this time (in 814 | * milliseconds) in order to allow in-flight message transfers to complete. 815 | */ 816 | int timeout; 817 | /** 818 | * A pointer to a callback function to be called if the disconnect successfully 819 | * completes. Can be set to NULL, in which case no indication of successful 820 | * completion will be received. 821 | */ 822 | MQTTAsync_onSuccess* onSuccess; 823 | /** 824 | * A pointer to a callback function to be called if the disconnect fails. 825 | * Can be set to NULL, in which case no indication of unsuccessful 826 | * completion will be received. 827 | */ 828 | MQTTAsync_onFailure* onFailure; 829 | /** 830 | * A pointer to any application-specific context. The 831 | * the context pointer is passed to success or failure callback functions to 832 | * provide access to the context information in the callback. 833 | */ 834 | void* context; 835 | } MQTTAsync_disconnectOptions; 836 | 837 | #define MQTTAsync_disconnectOptions_initializer { {'M', 'Q', 'T', 'D'}, 0, 0, NULL, NULL, NULL } 838 | 839 | 840 | /** 841 | * This function attempts to disconnect the client from the MQTT 842 | * server. In order to allow the client time to complete handling of messages 843 | * that are in-flight when this function is called, a timeout period is 844 | * specified. When the timeout period has expired, the client disconnects even 845 | * if there are still outstanding message acknowledgements. 846 | * The next time the client connects to the same server, any QoS 1 or 2 847 | * messages which have not completed will be retried depending on the 848 | * cleansession settings for both the previous and the new connection (see 849 | * MQTTAsync_connectOptions.cleansession and MQTTAsync_connect()). 850 | * @param handle A valid client handle from a successful call to 851 | * MQTTAsync_create(). 852 | * @param options The client delays disconnection for up to this time (in 853 | * milliseconds) in order to allow in-flight message transfers to complete. 854 | * @return ::MQTTASYNC_SUCCESS if the client successfully disconnects from 855 | * the server. An error code is returned if the client was unable to disconnect 856 | * from the server 857 | */ 858 | DLLExport int MQTTAsync_disconnect(MQTTAsync handle, const MQTTAsync_disconnectOptions* options); 859 | 860 | 861 | /** 862 | * This function allows the client application to test whether or not a 863 | * client is currently connected to the MQTT server. 864 | * @param handle A valid client handle from a successful call to 865 | * MQTTAsync_create(). 866 | * @return Boolean true if the client is connected, otherwise false. 867 | */ 868 | DLLExport int MQTTAsync_isConnected(MQTTAsync handle); 869 | 870 | 871 | /** 872 | * This function attempts to subscribe a client to a single topic, which may 873 | * contain wildcards (see @ref wildcard). This call also specifies the 874 | * @ref qos requested for the subscription 875 | * (see also MQTTAsync_subscribeMany()). 876 | * @param handle A valid client handle from a successful call to 877 | * MQTTAsync_create(). 878 | * @param topic The subscription topic, which may include wildcards. 879 | * @param qos The requested quality of service for the subscription. 880 | * @param response A pointer to a response options structure. Used to set callback functions. 881 | * @return ::MQTTASYNC_SUCCESS if the subscription request is successful. 882 | * An error code is returned if there was a problem registering the 883 | * subscription. 884 | */ 885 | DLLExport int MQTTAsync_subscribe(MQTTAsync handle, const char* topic, int qos, MQTTAsync_responseOptions* response); 886 | 887 | 888 | /** 889 | * This function attempts to subscribe a client to a list of topics, which may 890 | * contain wildcards (see @ref wildcard). This call also specifies the 891 | * @ref qos requested for each topic (see also MQTTAsync_subscribe()). 892 | * @param handle A valid client handle from a successful call to 893 | * MQTTAsync_create(). 894 | * @param count The number of topics for which the client is requesting 895 | * subscriptions. 896 | * @param topic An array (of length count) of pointers to 897 | * topics, each of which may include wildcards. 898 | * @param qos An array (of length count) of @ref qos 899 | * values. qos[n] is the requested QoS for topic[n]. 900 | * @param response A pointer to a response options structure. Used to set callback functions. 901 | * @return ::MQTTASYNC_SUCCESS if the subscription request is successful. 902 | * An error code is returned if there was a problem registering the 903 | * subscriptions. 904 | */ 905 | DLLExport int MQTTAsync_subscribeMany(MQTTAsync handle, int count, char* const* topic, int* qos, MQTTAsync_responseOptions* response); 906 | 907 | /** 908 | * This function attempts to remove an existing subscription made by the 909 | * specified client. 910 | * @param handle A valid client handle from a successful call to 911 | * MQTTAsync_create(). 912 | * @param topic The topic for the subscription to be removed, which may 913 | * include wildcards (see @ref wildcard). 914 | * @param response A pointer to a response options structure. Used to set callback functions. 915 | * @return ::MQTTASYNC_SUCCESS if the subscription is removed. 916 | * An error code is returned if there was a problem removing the 917 | * subscription. 918 | */ 919 | DLLExport int MQTTAsync_unsubscribe(MQTTAsync handle, const char* topic, MQTTAsync_responseOptions* response); 920 | 921 | /** 922 | * This function attempts to remove existing subscriptions to a list of topics 923 | * made by the specified client. 924 | * @param handle A valid client handle from a successful call to 925 | * MQTTAsync_create(). 926 | * @param count The number subscriptions to be removed. 927 | * @param topic An array (of length count) of pointers to the topics of 928 | * the subscriptions to be removed, each of which may include wildcards. 929 | * @param response A pointer to a response options structure. Used to set callback functions. 930 | * @return ::MQTTASYNC_SUCCESS if the subscriptions are removed. 931 | * An error code is returned if there was a problem removing the subscriptions. 932 | */ 933 | DLLExport int MQTTAsync_unsubscribeMany(MQTTAsync handle, int count, char* const* topic, MQTTAsync_responseOptions* response); 934 | 935 | 936 | /** 937 | * This function attempts to publish a message to a given topic (see also 938 | * ::MQTTAsync_sendMessage()). An ::MQTTAsync_token is issued when 939 | * this function returns successfully. If the client application needs to 940 | * test for successful delivery of messages, a callback should be set 941 | * (see ::MQTTAsync_onSuccess() and ::MQTTAsync_deliveryComplete()). 942 | * @param handle A valid client handle from a successful call to 943 | * MQTTAsync_create(). 944 | * @param destinationName The topic associated with this message. 945 | * @param payloadlen The length of the payload in bytes. 946 | * @param payload A pointer to the byte array payload of the message. 947 | * @param qos The @ref qos of the message. 948 | * @param retained The retained flag for the message. 949 | * @param response A pointer to an ::MQTTAsync_responseOptions structure. Used to set callback functions. 950 | * This is optional and can be set to NULL. 951 | * @return ::MQTTASYNC_SUCCESS if the message is accepted for publication. 952 | * An error code is returned if there was a problem accepting the message. 953 | */ 954 | DLLExport int MQTTAsync_send(MQTTAsync handle, const char* destinationName, int payloadlen, void* payload, int qos, int retained, 955 | MQTTAsync_responseOptions* response); 956 | 957 | 958 | /** 959 | * This function attempts to publish a message to a given topic (see also 960 | * MQTTAsync_publish()). An ::MQTTAsync_token is issued when 961 | * this function returns successfully. If the client application needs to 962 | * test for successful delivery of messages, a callback should be set 963 | * (see ::MQTTAsync_onSuccess() and ::MQTTAsync_deliveryComplete()). 964 | * @param handle A valid client handle from a successful call to 965 | * MQTTAsync_create(). 966 | * @param destinationName The topic associated with this message. 967 | * @param msg A pointer to a valid MQTTAsync_message structure containing 968 | * the payload and attributes of the message to be published. 969 | * @param response A pointer to an ::MQTTAsync_responseOptions structure. Used to set callback functions. 970 | * @return ::MQTTASYNC_SUCCESS if the message is accepted for publication. 971 | * An error code is returned if there was a problem accepting the message. 972 | */ 973 | DLLExport int MQTTAsync_sendMessage(MQTTAsync handle, const char* destinationName, const MQTTAsync_message* msg, MQTTAsync_responseOptions* response); 974 | 975 | 976 | /** 977 | * This function sets a pointer to an array of tokens for 978 | * messages that are currently in-flight (pending completion). 979 | * 980 | * Important note: The memory used to hold the array of tokens is 981 | * malloc()'d in this function. The client application is responsible for 982 | * freeing this memory when it is no longer required. 983 | * @param handle A valid client handle from a successful call to 984 | * MQTTAsync_create(). 985 | * @param tokens The address of a pointer to an ::MQTTAsync_token. 986 | * When the function returns successfully, the pointer is set to point to an 987 | * array of tokens representing messages pending completion. The last member of 988 | * the array is set to -1 to indicate there are no more tokens. If no tokens 989 | * are pending, the pointer is set to NULL. 990 | * @return ::MQTTASYNC_SUCCESS if the function returns successfully. 991 | * An error code is returned if there was a problem obtaining the list of 992 | * pending tokens. 993 | */ 994 | DLLExport int MQTTAsync_getPendingTokens(MQTTAsync handle, MQTTAsync_token **tokens); 995 | 996 | /** 997 | * Tests whether a request corresponding to a token is complete. 998 | * 999 | * @param handle A valid client handle from a successful call to 1000 | * MQTTAsync_create(). 1001 | * @param token An ::MQTTAsync_token associated with a request. 1002 | * @return 1 if the request has been completed, 0 if not. 1003 | */ 1004 | #define MQTTASYNC_TRUE 1 1005 | DLLExport int MQTTAsync_isComplete(MQTTAsync handle, MQTTAsync_token token); 1006 | 1007 | 1008 | /** 1009 | * Waits for a request corresponding to a token to complete. 1010 | * 1011 | * @param handle A valid client handle from a successful call to 1012 | * MQTTAsync_create(). 1013 | * @param token An ::MQTTAsync_token associated with a request. 1014 | * @param timeout the maximum time to wait for completion, in milliseconds 1015 | * @return ::MQTTASYNC_SUCCESS if the request has been completed in the time allocated, 1016 | * ::MQTTASYNC_FAILURE if not. 1017 | */ 1018 | DLLExport int MQTTAsync_waitForCompletion(MQTTAsync handle, MQTTAsync_token token, unsigned long timeout); 1019 | 1020 | 1021 | /** 1022 | * This function frees memory allocated to an MQTT message, including the 1023 | * additional memory allocated to the message payload. The client application 1024 | * calls this function when the message has been fully processed. Important 1025 | * note: This function does not free the memory allocated to a message 1026 | * topic string. It is the responsibility of the client application to free 1027 | * this memory using the MQTTAsync_free() library function. 1028 | * @param msg The address of a pointer to the ::MQTTAsync_message structure 1029 | * to be freed. 1030 | */ 1031 | DLLExport void MQTTAsync_freeMessage(MQTTAsync_message** msg); 1032 | 1033 | /** 1034 | * This function frees memory allocated by the MQTT C client library, especially the 1035 | * topic name. This is needed on Windows when the client libary and application 1036 | * program have been compiled with different versions of the C compiler. It is 1037 | * thus good policy to always use this function when freeing any MQTT C client- 1038 | * allocated memory. 1039 | * @param ptr The pointer to the client library storage to be freed. 1040 | */ 1041 | DLLExport void MQTTAsync_free(void* ptr); 1042 | 1043 | /** 1044 | * This function frees the memory allocated to an MQTT client (see 1045 | * MQTTAsync_create()). It should be called when the client is no longer 1046 | * required. 1047 | * @param handle A pointer to the handle referring to the ::MQTTAsync 1048 | * structure to be freed. 1049 | */ 1050 | DLLExport void MQTTAsync_destroy(MQTTAsync* handle); 1051 | 1052 | 1053 | 1054 | enum MQTTASYNC_TRACE_LEVELS 1055 | { 1056 | MQTTASYNC_TRACE_MAXIMUM = 1, 1057 | MQTTASYNC_TRACE_MEDIUM, 1058 | MQTTASYNC_TRACE_MINIMUM, 1059 | MQTTASYNC_TRACE_PROTOCOL, 1060 | MQTTASYNC_TRACE_ERROR, 1061 | MQTTASYNC_TRACE_SEVERE, 1062 | MQTTASYNC_TRACE_FATAL, 1063 | }; 1064 | 1065 | 1066 | /** 1067 | * This function sets the level of trace information which will be 1068 | * returned in the trace callback. 1069 | * @param level the trace level required 1070 | */ 1071 | DLLExport void MQTTAsync_setTraceLevel(enum MQTTASYNC_TRACE_LEVELS level); 1072 | 1073 | 1074 | /** 1075 | * This is a callback function prototype which must be implemented if you want 1076 | * to receive trace information. 1077 | * @param level the trace level of the message returned 1078 | * @param meesage the trace message. This is a pointer to a static buffer which 1079 | * will be overwritten on each call. You must copy the data if you want to keep 1080 | * it for later. 1081 | */ 1082 | typedef void MQTTAsync_traceCallback(enum MQTTASYNC_TRACE_LEVELS level, char* message); 1083 | 1084 | /** 1085 | * This function sets the trace callback if needed. If set to NULL, 1086 | * no trace information will be returned. The default trace level is 1087 | * MQTTASYNC_TRACE_MINIMUM. 1088 | * @param callback a pointer to the function which will handle the trace information 1089 | */ 1090 | DLLExport void MQTTAsync_setTraceCallback(MQTTAsync_traceCallback* callback); 1091 | 1092 | 1093 | typedef struct 1094 | { 1095 | const char* name; 1096 | const char* value; 1097 | } MQTTAsync_nameValue; 1098 | 1099 | /** 1100 | * This function returns version information about the library. 1101 | * no trace information will be returned. The default trace level is 1102 | * MQTTASYNC_TRACE_MINIMUM 1103 | * @return an array of strings describing the library. The last entry is a NULL pointer. 1104 | */ 1105 | DLLExport MQTTAsync_nameValue* MQTTAsync_getVersionInfo(); 1106 | 1107 | 1108 | /** 1109 | * @cond MQTTAsync_main 1110 | * @page async Threading 1111 | * The client application runs on several threads. 1112 | * Processing of handshaking and maintaining 1113 | * the network connection is performed in the background. 1114 | * This API is thread safe: functions may be called by multiple application 1115 | * threads. 1116 | * Notifications of status and message reception are provided to the client 1117 | * application using callbacks registered with the library by the call to 1118 | * MQTTAsync_setCallbacks() (see MQTTAsync_messageArrived(), 1119 | * MQTTAsync_connectionLost() and MQTTAsync_deliveryComplete()). 1120 | * In addition, some functions allow success and failure callbacks to be set 1121 | * for individual requests, in the ::MQTTAsync_responseOptions structure. Applications 1122 | * can be written as a chain of callback functions. Note that it is a theoretically 1123 | * possible but unlikely event, that a success or failure callback could be called 1124 | * before function requesting the callback has returned. In this case the token 1125 | * delivered in the callback would not yet be known to the application program (see 1126 | * Race condition for MQTTAsync_token in MQTTAsync.c 1127 | * https://bugs.eclipse.org/bugs/show_bug.cgi?id=444093) 1128 | * 1129 | * @page wildcard Subscription wildcards 1130 | * Every MQTT message includes a topic that classifies it. MQTT servers use 1131 | * topics to determine which subscribers should receive messages published to 1132 | * the server. 1133 | * 1134 | * Consider the server receiving messages from several environmental sensors. 1135 | * Each sensor publishes its measurement data as a message with an associated 1136 | * topic. Subscribing applications need to know which sensor originally 1137 | * published each received message. A unique topic is thus used to identify 1138 | * each sensor and measurement type. Topics such as SENSOR1TEMP, 1139 | * SENSOR1HUMIDITY, SENSOR2TEMP and so on achieve this but are not very 1140 | * flexible. If additional sensors are added to the system at a later date, 1141 | * subscribing applications must be modified to receive them. 1142 | * 1143 | * To provide more flexibility, MQTT supports a hierarchical topic namespace. 1144 | * This allows application designers to organize topics to simplify their 1145 | * management. Levels in the hierarchy are delimited by the '/' character, 1146 | * such as SENSOR/1/HUMIDITY. Publishers and subscribers use these 1147 | * hierarchical topics as already described. 1148 | * 1149 | * For subscriptions, two wildcard characters are supported: 1150 | *
        1151 | *
      • A '#' character represents a complete sub-tree of the hierarchy and 1152 | * thus must be the last character in a subscription topic string, such as 1153 | * SENSOR/#. This will match any topic starting with SENSOR/, such as 1154 | * SENSOR/1/TEMP and SENSOR/2/HUMIDITY.
      • 1155 | *
      • A '+' character represents a single level of the hierarchy and is 1156 | * used between delimiters. For example, SENSOR/+/TEMP will match 1157 | * SENSOR/1/TEMP and SENSOR/2/TEMP.
      • 1158 | *
      1159 | * Publishers are not allowed to use the wildcard characters in their topic 1160 | * names. 1161 | * 1162 | * Deciding on your topic hierarchy is an important step in your system design. 1163 | * 1164 | * @page qos Quality of service 1165 | * The MQTT protocol provides three qualities of service for delivering 1166 | * messages between clients and servers: "at most once", "at least once" and 1167 | * "exactly once". 1168 | * 1169 | * Quality of service (QoS) is an attribute of an individual message being 1170 | * published. An application sets the QoS for a specific message by setting the 1171 | * MQTTAsync_message.qos field to the required value. 1172 | * 1173 | * A subscribing client can set the maximum quality of service a server uses 1174 | * to send messages that match the client subscriptions. The 1175 | * MQTTAsync_subscribe() and MQTTAsync_subscribeMany() functions set this 1176 | * maximum. The QoS of a message forwarded to a subscriber thus might be 1177 | * different to the QoS given to the message by the original publisher. 1178 | * The lower of the two values is used to forward a message. 1179 | * 1180 | * The three levels are: 1181 | * 1182 | * QoS0, At most once: The message is delivered at most once, or it 1183 | * may not be delivered at all. Its delivery across the network is not 1184 | * acknowledged. The message is not stored. The message could be lost if the 1185 | * client is disconnected, or if the server fails. QoS0 is the fastest mode of 1186 | * transfer. It is sometimes called "fire and forget". 1187 | * 1188 | * The MQTT protocol does not require servers to forward publications at QoS0 1189 | * to a client. If the client is disconnected at the time the server receives 1190 | * the publication, the publication might be discarded, depending on the 1191 | * server implementation. 1192 | * 1193 | * QoS1, At least once: The message is always delivered at least once. 1194 | * It might be delivered multiple times if there is a failure before an 1195 | * acknowledgment is received by the sender. The message must be stored 1196 | * locally at the sender, until the sender receives confirmation that the 1197 | * message has been published by the receiver. The message is stored in case 1198 | * the message must be sent again. 1199 | * 1200 | * QoS2, Exactly once: The message is always delivered exactly once. 1201 | * The message must be stored locally at the sender, until the sender receives 1202 | * confirmation that the message has been published by the receiver. The 1203 | * message is stored in case the message must be sent again. QoS2 is the 1204 | * safest, but slowest mode of transfer. A more sophisticated handshaking 1205 | * and acknowledgement sequence is used than for QoS1 to ensure no duplication 1206 | * of messages occurs. 1207 | 1208 | 1209 | * @page publish Publication example 1210 | @code 1211 | #include "stdio.h" 1212 | #include "stdlib.h" 1213 | #include "string.h" 1214 | #include "MQTTAsync.h" 1215 | 1216 | #define ADDRESS "tcp://localhost:1883" 1217 | #define CLIENTID "ExampleClientPub" 1218 | #define TOPIC "MQTT Examples" 1219 | #define PAYLOAD "Hello World!" 1220 | #define QOS 1 1221 | #define TIMEOUT 10000L 1222 | 1223 | volatile MQTTAsync_token deliveredtoken; 1224 | 1225 | int finished = 0; 1226 | 1227 | void connlost(void *context, char *cause) 1228 | { 1229 | MQTTAsync client = (MQTTAsync)context; 1230 | MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer; 1231 | int rc; 1232 | 1233 | printf("\nConnection lost\n"); 1234 | printf(" cause: %s\n", cause); 1235 | 1236 | printf("Reconnecting\n"); 1237 | conn_opts.keepAliveInterval = 20; 1238 | conn_opts.cleansession = 1; 1239 | if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS) 1240 | { 1241 | printf("Failed to start connect, return code %d\n", rc); 1242 | finished = 1; 1243 | } 1244 | } 1245 | 1246 | 1247 | void onDisconnect(void* context, MQTTAsync_successData* response) 1248 | { 1249 | printf("Successful disconnection\n"); 1250 | finished = 1; 1251 | } 1252 | 1253 | 1254 | void onSend(void* context, MQTTAsync_successData* response) 1255 | { 1256 | MQTTAsync client = (MQTTAsync)context; 1257 | MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer; 1258 | int rc; 1259 | 1260 | printf("Message with token value %d delivery confirmed\n", response->token); 1261 | 1262 | opts.onSuccess = onDisconnect; 1263 | opts.context = client; 1264 | 1265 | if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS) 1266 | { 1267 | printf("Failed to start sendMessage, return code %d\n", rc); 1268 | exit(-1); 1269 | } 1270 | } 1271 | 1272 | 1273 | void onConnectFailure(void* context, MQTTAsync_failureData* response) 1274 | { 1275 | printf("Connect failed, rc %d\n", response ? response->code : 0); 1276 | finished = 1; 1277 | } 1278 | 1279 | 1280 | void onConnect(void* context, MQTTAsync_successData* response) 1281 | { 1282 | MQTTAsync client = (MQTTAsync)context; 1283 | MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer; 1284 | MQTTAsync_message pubmsg = MQTTAsync_message_initializer; 1285 | int rc; 1286 | 1287 | printf("Successful connection\n"); 1288 | 1289 | opts.onSuccess = onSend; 1290 | opts.context = client; 1291 | 1292 | pubmsg.payload = PAYLOAD; 1293 | pubmsg.payloadlen = strlen(PAYLOAD); 1294 | pubmsg.qos = QOS; 1295 | pubmsg.retained = 0; 1296 | deliveredtoken = 0; 1297 | 1298 | if ((rc = MQTTAsync_sendMessage(client, TOPIC, &pubmsg, &opts)) != MQTTASYNC_SUCCESS) 1299 | { 1300 | printf("Failed to start sendMessage, return code %d\n", rc); 1301 | exit(-1); 1302 | } 1303 | } 1304 | 1305 | 1306 | int main(int argc, char* argv[]) 1307 | { 1308 | MQTTAsync client; 1309 | MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer; 1310 | MQTTAsync_message pubmsg = MQTTAsync_message_initializer; 1311 | MQTTAsync_token token; 1312 | int rc; 1313 | 1314 | MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL); 1315 | 1316 | MQTTAsync_setCallbacks(client, NULL, connlost, NULL, NULL); 1317 | 1318 | conn_opts.keepAliveInterval = 20; 1319 | conn_opts.cleansession = 1; 1320 | conn_opts.onSuccess = onConnect; 1321 | conn_opts.onFailure = onConnectFailure; 1322 | conn_opts.context = client; 1323 | if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS) 1324 | { 1325 | printf("Failed to start connect, return code %d\n", rc); 1326 | exit(-1); 1327 | } 1328 | 1329 | printf("Waiting for publication of %s\n" 1330 | "on topic %s for client with ClientID: %s\n", 1331 | PAYLOAD, TOPIC, CLIENTID); 1332 | while (!finished) 1333 | #if defined(WIN32) || defined(WIN64) 1334 | Sleep(100); 1335 | #else 1336 | usleep(10000L); 1337 | #endif 1338 | 1339 | MQTTAsync_destroy(&client); 1340 | return rc; 1341 | } 1342 | 1343 | * @endcode 1344 | * @page subscribe Subscription example 1345 | @code 1346 | #include "stdio.h" 1347 | #include "stdlib.h" 1348 | #include "string.h" 1349 | #include "MQTTAsync.h" 1350 | 1351 | #define ADDRESS "tcp://localhost:1883" 1352 | #define CLIENTID "ExampleClientSub" 1353 | #define TOPIC "MQTT Examples" 1354 | #define PAYLOAD "Hello World!" 1355 | #define QOS 1 1356 | #define TIMEOUT 10000L 1357 | 1358 | volatile MQTTAsync_token deliveredtoken; 1359 | 1360 | int disc_finished = 0; 1361 | int subscribed = 0; 1362 | int finished = 0; 1363 | 1364 | void connlost(void *context, char *cause) 1365 | { 1366 | MQTTAsync client = (MQTTAsync)context; 1367 | MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer; 1368 | int rc; 1369 | 1370 | printf("\nConnection lost\n"); 1371 | printf(" cause: %s\n", cause); 1372 | 1373 | printf("Reconnecting\n"); 1374 | conn_opts.keepAliveInterval = 20; 1375 | conn_opts.cleansession = 1; 1376 | if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS) 1377 | { 1378 | printf("Failed to start connect, return code %d\n", rc); 1379 | finished = 1; 1380 | } 1381 | } 1382 | 1383 | 1384 | int msgarrvd(void *context, char *topicName, int topicLen, MQTTAsync_message *message) 1385 | { 1386 | int i; 1387 | char* payloadptr; 1388 | 1389 | printf("Message arrived\n"); 1390 | printf(" topic: %s\n", topicName); 1391 | printf(" message: "); 1392 | 1393 | payloadptr = message->payload; 1394 | for(i=0; ipayloadlen; i++) 1395 | { 1396 | putchar(*payloadptr++); 1397 | } 1398 | putchar('\n'); 1399 | MQTTAsync_freeMessage(&message); 1400 | MQTTAsync_free(topicName); 1401 | return 1; 1402 | } 1403 | 1404 | 1405 | void onDisconnect(void* context, MQTTAsync_successData* response) 1406 | { 1407 | printf("Successful disconnection\n"); 1408 | disc_finished = 1; 1409 | } 1410 | 1411 | 1412 | void onSubscribe(void* context, MQTTAsync_successData* response) 1413 | { 1414 | printf("Subscribe succeeded\n"); 1415 | subscribed = 1; 1416 | } 1417 | 1418 | void onSubscribeFailure(void* context, MQTTAsync_failureData* response) 1419 | { 1420 | printf("Subscribe failed, rc %d\n", response ? response->code : 0); 1421 | finished = 1; 1422 | } 1423 | 1424 | 1425 | void onConnectFailure(void* context, MQTTAsync_failureData* response) 1426 | { 1427 | printf("Connect failed, rc %d\n", response ? response->code : 0); 1428 | finished = 1; 1429 | } 1430 | 1431 | 1432 | void onConnect(void* context, MQTTAsync_successData* response) 1433 | { 1434 | MQTTAsync client = (MQTTAsync)context; 1435 | MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer; 1436 | MQTTAsync_message pubmsg = MQTTAsync_message_initializer; 1437 | int rc; 1438 | 1439 | printf("Successful connection\n"); 1440 | 1441 | printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n" 1442 | "Press Q to quit\n\n", TOPIC, CLIENTID, QOS); 1443 | opts.onSuccess = onSubscribe; 1444 | opts.onFailure = onSubscribeFailure; 1445 | opts.context = client; 1446 | 1447 | deliveredtoken = 0; 1448 | 1449 | if ((rc = MQTTAsync_subscribe(client, TOPIC, QOS, &opts)) != MQTTASYNC_SUCCESS) 1450 | { 1451 | printf("Failed to start subscribe, return code %d\n", rc); 1452 | exit(-1); 1453 | } 1454 | } 1455 | 1456 | 1457 | int main(int argc, char* argv[]) 1458 | { 1459 | MQTTAsync client; 1460 | MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer; 1461 | MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer; 1462 | MQTTAsync_message pubmsg = MQTTAsync_message_initializer; 1463 | MQTTAsync_token token; 1464 | int rc; 1465 | int ch; 1466 | 1467 | MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL); 1468 | 1469 | MQTTAsync_setCallbacks(client, NULL, connlost, msgarrvd, NULL); 1470 | 1471 | conn_opts.keepAliveInterval = 20; 1472 | conn_opts.cleansession = 1; 1473 | conn_opts.onSuccess = onConnect; 1474 | conn_opts.onFailure = onConnectFailure; 1475 | conn_opts.context = client; 1476 | if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS) 1477 | { 1478 | printf("Failed to start connect, return code %d\n", rc); 1479 | exit(-1); 1480 | } 1481 | 1482 | while (!subscribed) 1483 | #if defined(WIN32) || defined(WIN64) 1484 | Sleep(100); 1485 | #else 1486 | usleep(10000L); 1487 | #endif 1488 | 1489 | if (finished) 1490 | goto exit; 1491 | 1492 | do 1493 | { 1494 | ch = getchar(); 1495 | } while (ch!='Q' && ch != 'q'); 1496 | 1497 | disc_opts.onSuccess = onDisconnect; 1498 | if ((rc = MQTTAsync_disconnect(client, &disc_opts)) != MQTTASYNC_SUCCESS) 1499 | { 1500 | printf("Failed to start disconnect, return code %d\n", rc); 1501 | exit(-1); 1502 | } 1503 | while (!disc_finished) 1504 | #if defined(WIN32) || defined(WIN64) 1505 | Sleep(100); 1506 | #else 1507 | usleep(10000L); 1508 | #endif 1509 | 1510 | exit: 1511 | MQTTAsync_destroy(&client); 1512 | return rc; 1513 | } 1514 | 1515 | * @endcode 1516 | * @page tracing Tracing 1517 | * 1518 | * Runtime tracing can be controlled by environment variables or API calls. 1519 | * 1520 | * #### Environment variables 1521 | * 1522 | * Tracing is switched on by setting the MQTT_C_CLIENT_TRACE environment variable. 1523 | * A value of ON, or stdout, prints to stdout, any other value is interpreted as a file name to use. 1524 | * 1525 | * The amount of trace detail is controlled with the MQTT_C_CLIENT_TRACE_LEVEL environment 1526 | * variable - valid values are ERROR, PROTOCOL, MINIMUM, MEDIUM and MAXIMUM 1527 | * (from least to most verbose). 1528 | * 1529 | * The variable MQTT_C_CLIENT_TRACE_MAX_LINES limits the number of lines of trace that are output 1530 | * to a file. Two files are used at most, when they are full, the last one is overwritten with the 1531 | * new trace entries. The default size is 1000 lines. 1532 | * 1533 | * #### Trace API calls 1534 | * 1535 | * MQTTAsync_traceCallback() is used to set a callback function which is called whenever trace 1536 | * information is available. This will be the same information as that printed if the 1537 | * environment variables were used to control the trace. 1538 | * 1539 | * The MQTTAsync_setTraceLevel() calls is used to set the maximum level of trace entries that will be 1540 | * passed to the callback function. The levels are: 1541 | * 1. ::MQTTASYNC_TRACE_MAXIMUM 1542 | * 2. ::MQTTASYNC_TRACE_MEDIUM 1543 | * 3. ::MQTTASYNC_TRACE_MINIMUM 1544 | * 4. ::MQTTASYNC_TRACE_PROTOCOL 1545 | * 5. ::MQTTASYNC_TRACE_ERROR 1546 | * 6. ::MQTTASYNC_TRACE_SEVERE 1547 | * 7. ::MQTTASYNC_TRACE_FATAL 1548 | * 1549 | * Selecting ::MQTTASYNC_TRACE_MAXIMUM will cause all trace entries at all levels to be returned. 1550 | * Choosing ::MQTTASYNC_TRACE_ERROR will cause ERROR, SEVERE and FATAL trace entries to be returned 1551 | * to the callback function. 1552 | * 1553 | * ### MQTT Packet Tracing 1554 | * 1555 | * A feature that can be very useful is printing the MQTT packets that are sent and received. To 1556 | * achieve this, use the following environment variable settings: 1557 | * @code 1558 | MQTT_C_CLIENT_TRACE=ON 1559 | MQTT_C_CLIENT_TRACE_LEVEL=PROTOCOL 1560 | * @endcode 1561 | * The output you should see looks like this: 1562 | * @code 1563 | 20130528 155936.813 3 stdout-subscriber -> CONNECT cleansession: 1 (0) 1564 | 20130528 155936.813 3 stdout-subscriber <- CONNACK rc: 0 1565 | 20130528 155936.813 3 stdout-subscriber -> SUBSCRIBE msgid: 1 (0) 1566 | 20130528 155936.813 3 stdout-subscriber <- SUBACK msgid: 1 1567 | 20130528 155941.818 3 stdout-subscriber -> DISCONNECT (0) 1568 | * @endcode 1569 | * where the fields are: 1570 | * 1. date 1571 | * 2. time 1572 | * 3. socket number 1573 | * 4. client id 1574 | * 5. direction (-> from client to server, <- from server to client) 1575 | * 6. packet details 1576 | * 1577 | * ### Default Level Tracing 1578 | * 1579 | * This is an extract of a default level trace of a call to connect: 1580 | * @code 1581 | 19700101 010000.000 (1152206656) (0)> MQTTClient_connect:893 1582 | 19700101 010000.000 (1152206656) (1)> MQTTClient_connectURI:716 1583 | 20130528 160447.479 Connecting to serverURI localhost:1883 1584 | 20130528 160447.479 (1152206656) (2)> MQTTProtocol_connect:98 1585 | 20130528 160447.479 (1152206656) (3)> MQTTProtocol_addressPort:48 1586 | 20130528 160447.479 (1152206656) (3)< MQTTProtocol_addressPort:73 1587 | 20130528 160447.479 (1152206656) (3)> Socket_new:599 1588 | 20130528 160447.479 New socket 4 for localhost, port 1883 1589 | 20130528 160447.479 (1152206656) (4)> Socket_addSocket:163 1590 | 20130528 160447.479 (1152206656) (5)> Socket_setnonblocking:73 1591 | 20130528 160447.479 (1152206656) (5)< Socket_setnonblocking:78 (0) 1592 | 20130528 160447.479 (1152206656) (4)< Socket_addSocket:176 (0) 1593 | 20130528 160447.479 (1152206656) (4)> Socket_error:95 1594 | 20130528 160447.479 (1152206656) (4)< Socket_error:104 (115) 1595 | 20130528 160447.479 Connect pending 1596 | 20130528 160447.479 (1152206656) (3)< Socket_new:683 (115) 1597 | 20130528 160447.479 (1152206656) (2)< MQTTProtocol_connect:131 (115) 1598 | * @endcode 1599 | * where the fields are: 1600 | * 1. date 1601 | * 2. time 1602 | * 3. thread id 1603 | * 4. function nesting level 1604 | * 5. function entry (>) or exit (<) 1605 | * 6. function name : line of source code file 1606 | * 7. return value (if there is one) 1607 | * 1608 | * ### Memory Allocation Tracing 1609 | * 1610 | * Setting the trace level to maximum causes memory allocations and frees to be traced along with 1611 | * the default trace entries, with messages like the following: 1612 | * @code 1613 | 20130528 161819.657 Allocating 16 bytes in heap at file /home/icraggs/workspaces/mqrtc/mqttv3c/src/MQTTPacket.c line 177 ptr 0x179f930 1614 | 1615 | 20130528 161819.657 Freeing 16 bytes in heap at file /home/icraggs/workspaces/mqrtc/mqttv3c/src/MQTTPacket.c line 201, heap use now 896 bytes 1616 | * @endcode 1617 | * When the last MQTT client object is destroyed, if the trace is being recorded 1618 | * and all memory allocated by the client library has not been freed, an error message will be 1619 | * written to the trace. This can help with fixing memory leaks. The message will look like this: 1620 | * @code 1621 | 20130528 163909.208 Some memory not freed at shutdown, possible memory leak 1622 | 20130528 163909.208 Heap scan start, total 880 bytes 1623 | 20130528 163909.208 Heap element size 32, line 354, file /home/icraggs/workspaces/mqrtc/mqttv3c/src/MQTTPacket.c, ptr 0x260cb00 1624 | 20130528 163909.208 Content 1625 | 20130528 163909.209 Heap scan end 1626 | * @endcode 1627 | * @endcond 1628 | */ 1629 | 1630 | 1631 | #endif 1632 | 1633 | #ifdef __cplusplus 1634 | } 1635 | #endif 1636 | -------------------------------------------------------------------------------- /src/ios/MQTTClientPersistence.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2009, 2012 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | /** 18 | * @file 19 | * \brief This structure represents a persistent data store, used to store 20 | * outbound and inbound messages, in order to achieve reliable messaging. 21 | * 22 | * The MQTT Client persists QoS1 and QoS2 messages in order to meet the 23 | * assurances of delivery associated with these @ref qos levels. The messages 24 | * are saved in persistent storage 25 | * The type and context of the persistence implementation are specified when 26 | * the MQTT client is created (see MQTTClient_create()). The default 27 | * persistence type (::MQTTCLIENT_PERSISTENCE_DEFAULT) uses a file system-based 28 | * persistence mechanism. The persistence_context argument passed to 29 | * MQTTClient_create() when using the default peristence is a string 30 | * representing the location of the persistence directory. If the context 31 | * argument is NULL, the working directory will be used. 32 | * 33 | * To use memory-based persistence, an application passes 34 | * ::MQTTCLIENT_PERSISTENCE_NONE as the persistence_type to 35 | * MQTTClient_create(). This can lead to message loss in certain situations, 36 | * but can be appropriate in some cases (see @ref qos). 37 | * 38 | * Client applications can provide their own persistence mechanism by passing 39 | * ::MQTTCLIENT_PERSISTENCE_USER as the persistence_type. To implement a 40 | * custom persistence mechanism, the application must pass an initialized 41 | * ::MQTTClient_persistence structure as the persistence_context 42 | * argument to MQTTClient_create(). 43 | * 44 | * If the functions defined return an ::MQTTCLIENT_PERSISTENCE_ERROR then the 45 | * state of the persisted data should remain as it was prior to the function 46 | * being called. For example, if Persistence_put() returns 47 | * ::MQTTCLIENT_PERSISTENCE_ERROR, then it is assumed tha tthe persistent store 48 | * does not contain the data that was passed to the function. Similarly, if 49 | * Persistence_remove() returns ::MQTTCLIENT_PERSISTENCE_ERROR then it is 50 | * assumed that the data to be removed is still held in the persistent store. 51 | * 52 | * It is up to the persistence implementation to log any error information that 53 | * may be required to diagnose a persistence mechanism failure. 54 | */ 55 | 56 | /// @cond EXCLUDE 57 | #if !defined(MQTTCLIENTPERSISTENCE_H) 58 | #define MQTTCLIENTPERSISTENCE_H 59 | /// @endcond 60 | 61 | /** 62 | * This persistence_type value specifies the default file system-based 63 | * persistence mechanism (see MQTTClient_create()). 64 | */ 65 | #define MQTTCLIENT_PERSISTENCE_DEFAULT 0 66 | /** 67 | * This persistence_type value specifies a memory-based 68 | * persistence mechanism (see MQTTClient_create()). 69 | */ 70 | #define MQTTCLIENT_PERSISTENCE_NONE 1 71 | /** 72 | * This persistence_type value specifies an application-specific 73 | * persistence mechanism (see MQTTClient_create()). 74 | */ 75 | #define MQTTCLIENT_PERSISTENCE_USER 2 76 | 77 | /** 78 | * Application-specific persistence functions must return this error code if 79 | * there is a problem executing the function. 80 | */ 81 | #define MQTTCLIENT_PERSISTENCE_ERROR -2 82 | 83 | /** 84 | * @brief Initialize the persistent store. 85 | * 86 | * Either open the existing persistent store for this client ID or create a new 87 | * one if one doesn't exist. If the persistent store is already open, return 88 | * without taking any action. 89 | * 90 | * An application can use the same client identifier to connect to many 91 | * different servers. The clientid in conjunction with the 92 | * serverURI uniquely identifies the persistence store required. 93 | * 94 | * @param handle The address of a pointer to a handle for this persistence 95 | * implementation. This function must set handle to a valid reference to the 96 | * persistence following a successful return. 97 | * The handle pointer is passed as an argument to all the other 98 | * persistence functions. It may include the context parameter and/or any other 99 | * data for use by the persistence functions. 100 | * @param clientID The client identifier for which the persistent store should 101 | * be opened. 102 | * @param serverURI The connection string specified when the MQTT client was 103 | * created (see MQTTClient_create()). 104 | * @param context A pointer to any data required to initialize the persistent 105 | * store (see ::MQTTClient_persistence). 106 | * @return Return 0 if the function completes successfully, otherwise return 107 | * ::MQTTCLIENT_PERSISTENCE_ERROR. 108 | */ 109 | typedef int (*Persistence_open)(void** handle, const char* clientID, const char* serverURI, void* context); 110 | 111 | /** 112 | * @brief Close the persistent store referred to by the handle. 113 | * 114 | * @param handle The handle pointer from a successful call to 115 | * Persistence_open(). 116 | * @return Return 0 if the function completes successfully, otherwise return 117 | * ::MQTTCLIENT_PERSISTENCE_ERROR. 118 | */ 119 | typedef int (*Persistence_close)(void* handle); 120 | 121 | /** 122 | * @brief Put the specified data into the persistent store. 123 | * 124 | * @param handle The handle pointer from a successful call to 125 | * Persistence_open(). 126 | * @param key A string used as the key for the data to be put in the store. The 127 | * key is later used to retrieve data from the store with Persistence_get(). 128 | * @param bufcount The number of buffers to write to the persistence store. 129 | * @param buffers An array of pointers to the data buffers associated with 130 | * this key. 131 | * @param buflens An array of lengths of the data buffers. buflen[n] 132 | * gives the length of buffer[n]. 133 | * @return Return 0 if the function completes successfully, otherwise return 134 | * ::MQTTCLIENT_PERSISTENCE_ERROR. 135 | */ 136 | typedef int (*Persistence_put)(void* handle, char* key, int bufcount, char* buffers[], int buflens[]); 137 | 138 | /** 139 | * @brief Retrieve the specified data from the persistent store. 140 | * 141 | * @param handle The handle pointer from a successful call to 142 | * Persistence_open(). 143 | * @param key A string that is the key for the data to be retrieved. This is 144 | * the same key used to save the data to the store with Persistence_put(). 145 | * @param buffer The address of a pointer to a buffer. This function sets the 146 | * pointer to point at the retrieved data, if successful. 147 | * @param buflen The address of an int that is set to the length of 148 | * buffer by this function if successful. 149 | * @return Return 0 if the function completes successfully, otherwise return 150 | * ::MQTTCLIENT_PERSISTENCE_ERROR. 151 | */ 152 | typedef int (*Persistence_get)(void* handle, char* key, char** buffer, int* buflen); 153 | 154 | /** 155 | * @brief Remove the data for the specified key from the store. 156 | * 157 | * @param handle The handle pointer from a successful call to 158 | * Persistence_open(). 159 | * @param key A string that is the key for the data to be removed from the 160 | * store. This is the same key used to save the data to the store with 161 | * Persistence_put(). 162 | * @return Return 0 if the function completes successfully, otherwise return 163 | * ::MQTTCLIENT_PERSISTENCE_ERROR. 164 | */ 165 | typedef int (*Persistence_remove)(void* handle, char* key); 166 | 167 | /** 168 | * @brief Returns the keys in this persistent data store. 169 | * 170 | * @param handle The handle pointer from a successful call to 171 | * Persistence_open(). 172 | * @param keys The address of a pointer to pointers to strings. Assuming 173 | * successful execution, this function allocates memory to hold the returned 174 | * keys (strings used to store the data with Persistence_put()). It also 175 | * allocates memory to hold an array of pointers to these strings. keys 176 | * is set to point to the array of pointers to strings. 177 | * @param nkeys A pointer to the number of keys in this persistent data store. 178 | * This function sets the number of keys, if successful. 179 | * @return Return 0 if the function completes successfully, otherwise return 180 | * ::MQTTCLIENT_PERSISTENCE_ERROR. 181 | */ 182 | typedef int (*Persistence_keys)(void* handle, char*** keys, int* nkeys); 183 | 184 | /** 185 | * @brief Clears the persistence store, so that it no longer contains any 186 | * persisted data. 187 | * 188 | * @param handle The handle pointer from a successful call to 189 | * Persistence_open(). 190 | * @return Return 0 if the function completes successfully, otherwise return 191 | * ::MQTTCLIENT_PERSISTENCE_ERROR. 192 | */ 193 | typedef int (*Persistence_clear)(void* handle); 194 | 195 | /** 196 | * @brief Returns whether any data has been persisted using the specified key. 197 | * 198 | * @param handle The handle pointer from a successful call to 199 | * Persistence_open(). 200 | * @param key The string to be tested for existence in the store. 201 | * @return Return 0 if the key was found in the store, otherwise return 202 | * ::MQTTCLIENT_PERSISTENCE_ERROR. 203 | */ 204 | typedef int (*Persistence_containskey)(void* handle, char* key); 205 | 206 | /** 207 | * @brief A structure containing the function pointers to a persistence 208 | * implementation and the context or state that will be shared across all 209 | * the persistence functions. 210 | */ 211 | typedef struct { 212 | /** 213 | * A pointer to any data required to initialize the persistent store. 214 | */ 215 | void* context; 216 | /** 217 | * A function pointer to an implementation of Persistence_open(). 218 | */ 219 | Persistence_open popen; 220 | /** 221 | * A function pointer to an implementation of Persistence_close(). 222 | */ 223 | Persistence_close pclose; 224 | /** 225 | * A function pointer to an implementation of Persistence_put(). 226 | */ 227 | Persistence_put pput; 228 | /** 229 | * A function pointer to an implementation of Persistence_get(). 230 | */ 231 | Persistence_get pget; 232 | /** 233 | * A function pointer to an implementation of Persistence_remove(). 234 | */ 235 | Persistence_remove premove; 236 | /** 237 | * A function pointer to an implementation of Persistence_keys(). 238 | */ 239 | Persistence_keys pkeys; 240 | /** 241 | * A function pointer to an implementation of Persistence_clear(). 242 | */ 243 | Persistence_clear pclear; 244 | /** 245 | * A function pointer to an implementation of Persistence_containskey(). 246 | */ 247 | Persistence_containskey pcontainskey; 248 | } MQTTClient_persistence; 249 | 250 | #endif 251 | -------------------------------------------------------------------------------- /www/MQTTEmitter.js: -------------------------------------------------------------------------------- 1 | !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.MQTTEmitter=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o0){ 42 | if (!args.routerConfig.useDefaultRouter&&args.routerConfig.useDefaultRouter!==undefined) { 43 | if(args.routerConfig.router!==undefined){ 44 | router = args.routerConfig.router; 45 | isDefault = useDefaultRouter; 46 | } else{ 47 | console.error("Please set your topic router object"); 48 | } 49 | } else { 50 | //using default topic router 51 | router = new ME(); 52 | } 53 | 54 | }else{ 55 | //setting mqtt-emitter instance as default router 56 | router = new ME(); 57 | } 58 | } else { 59 | router = new ME(); 60 | } 61 | if(url.length>0&&urgx.exec(url)!==null){ 62 | if (cordova.platformId === "android") { 63 | exec(function(cd){ 64 | //console.log("data",cd); 65 | switch(cd.call){ 66 | case "connected": 67 | delete cd.call; 68 | if(args.success!==undefined){ 69 | args.success(cd); 70 | } 71 | //cordova.fireDocumentEvent("connected",cd); 72 | console.warn("Cordova Plugin Warning: The eventListner implmentation to read the published payloads shall be discontinued from the 0.3.0 version. Kindly take a note of this change."); 73 | break; 74 | case "disconnected": 75 | delete cd.call; 76 | if(args.error!==undefined){ 77 | args.error(cd); 78 | } 79 | //cordova.fireDocumentEvent("disconnected",cd); 80 | break; 81 | case "failure": 82 | delete cd.call; 83 | if(args.onConnectionLost!==undefined){ 84 | args.onConnectionLost(cd); 85 | } 86 | //cordova.fireDocumentEvent("failure",cd); 87 | break; 88 | case "onPublish": 89 | delete cd.call; 90 | var payload = isBinaryPayload ? base64.toArrayBuffer(cd.payload) : cd.payload; 91 | if(args.onPublish!==undefined){ 92 | args.onPublish(cd.topic,payload); 93 | } 94 | if(router!==null){ 95 | if (args.routerConfig!==undefined) { 96 | if (args.routerConfig.publishMethod!==undefined) { 97 | router[args.routerConfig.publishMethod](cd.topic,payload); 98 | } 99 | 100 | } else { 101 | router.emit(cd.topic,payload); 102 | } 103 | 104 | } 105 | //cordova.fireDocumentEvent(cd.topic,cd); 106 | break; 107 | default: 108 | console.log(cd); 109 | break; 110 | } 111 | }, function(e){ 112 | console.error(e); 113 | }, "CordovaMqTTPlugin", "connect", [url,args.clientId,(args.keepAlive === undefined ? 60000 : args.keepAlive),iscls,args.connectionTimeout||30,args.username, args.password,args.willTopicConfig.topic,args.willTopicConfig.payload,args.willTopicConfig.qos||0,(args.willTopicConfig.retain === undefined ? true : args.willTopicConfig.retain),args.version||"3.1.1",isBinaryPayload,args.willTopicConfig.payload instanceof ArrayBuffer]); 114 | } else { 115 | 116 | if (args.url.split("tcp://").length > 1) { 117 | client = new Paho.MQTT.Client(args.url.split("tcp://")[1], Number(args.wsPort ? args.wsPort : args.port), args.urlPath||"/ws", args.clientId); 118 | } 119 | // if (args.url.split("local://").length > 1) { 120 | // client = new Paho.MQTT.Client(args.url.split("local://")[1], Number(args.wsPort), args.urlPath||"/ws", args.clientId); 121 | // } 122 | client.onConnectionLost = function (cd) { 123 | client = null; 124 | if(args.error!==undefined){ 125 | args.error(cd); 126 | } 127 | }; 128 | client.onMessageArrived = function (payload) { 129 | var preparedPayload = isBinaryPayload ? payload.payloadBytes : payload.payloadString; 130 | if(args.onPublish!==undefined){ 131 | args.onPublish(payload.destinationName,preparedPayload); 132 | } 133 | if(router!==null){ 134 | if (args.routerConfig!==undefined) { 135 | if (args.routerConfig.publishMethod!==undefined) { 136 | router[args.routerConfig.publishMethod](payload.destinationName,preparedPayload); 137 | } 138 | 139 | } else { 140 | router.emit(payload.destinationName,preparedPayload); 141 | } 142 | 143 | } 144 | }; 145 | var connOpts = {}; 146 | connOpts.userName = args.username||""; 147 | connOpts.password = args.password||""; 148 | connOpts.onSuccess = function (cd) { 149 | if(args.success!==undefined){ 150 | args.success(cd); 151 | } 152 | }; 153 | connOpts.onFailure = function (cd) { 154 | client = null; 155 | if(args.error!==undefined){ 156 | args.error(cd); 157 | } 158 | }; 159 | connOpts.timeout = args.connectionTimeout||30; 160 | connOpts.keepAliveInterval = (args.keepAlive === undefined) ? 60000 : args.keepAlive; 161 | connOpts.cleanSession = iscls; 162 | //connOpts.mqttVersion = args.version||"3.1.1"; 163 | //console.log("will",args.willTopicConfig); 164 | if (args.willTopicConfig.topic !== undefined) { 165 | var willMsg = new Paho.MQTT.Message(args.willTopicConfig.payload); 166 | willMsg.destinationName = args.willTopicConfig.topic; 167 | willMsg.qos = args.willTopicConfig.qos||0; 168 | willMsg.retained = (args.willTopicConfig.retain === undefined) ? true : args.willTopicConfig.retain; 169 | connOpts.willMessage = willMsg; 170 | } 171 | client.connect(connOpts); 172 | } 173 | 174 | } else{ 175 | console.error("Please provide the URL to connect. If entered then please check the URL format. We support only tcp:// & local:// protocols"); 176 | } 177 | 178 | }; 179 | exports.publish = function(args){ 180 | (args.retain===undefined) ? (args.retain=false) : ""; 181 | if(args.topic.length>0){ 182 | if (cordova.platformId === "android") { 183 | exec(function(data){ 184 | //console.log("data",data); 185 | //cordova.fireDocumentEvent(data); 186 | switch(data.call){ 187 | case "success": 188 | delete data.call; 189 | if(args.success !== undefined){ 190 | args.success(data); 191 | } 192 | 193 | break; 194 | case "failure": 195 | delete data.call; 196 | if(args.success !== undefined){ 197 | args.error(data); 198 | } 199 | break; 200 | } 201 | }, function(e){ 202 | if(args.error !== undefined){ 203 | args.error(e); 204 | } 205 | }, "CordovaMqTTPlugin", "publish", [args.topic,args.payload,args.qos||0,args.retain,args.payload instanceof ArrayBuffer]); 206 | } else { 207 | var message = new Paho.MQTT.Message(args.payload); 208 | message.destinationName = args.topic; 209 | message.qos = args.qos; 210 | message.retained = args.retain; 211 | if (client !== null) { 212 | client.send(message); 213 | } 214 | } 215 | 216 | } else{ 217 | console.error("Please provide a topic string in topic argument"); 218 | } 219 | }; 220 | exports.subscribe = function(args){ 221 | (args.retain===undefined) ? args.retain=false : args.retain=true; 222 | if(args.topic.length>0){ 223 | if (cordova.platformId === "android") { 224 | exec(function(data){ 225 | //console.log("data",data); 226 | switch(data.call){ 227 | case "success": 228 | delete data.call; 229 | if (args.success!==undefined) { 230 | args.success(data); 231 | } 232 | break; 233 | case "failure": 234 | delete data.call; 235 | if (args.error!==undefined) { 236 | args.error(data); 237 | } 238 | 239 | break; 240 | } 241 | }, function(e){ 242 | console.error(e); 243 | args.error(e); 244 | }, "CordovaMqTTPlugin", "subscribe", [args.topic,args.qos||0]); 245 | } else { 246 | if (client !== null) { 247 | client.subscribe(args.topic,{ 248 | qos:args.qos||0, 249 | onSuccess:function(cd,data){ 250 | if (args.success!==undefined) { 251 | args.success(data); 252 | } 253 | }, 254 | onFailure:function (cd,data) { 255 | if (args.error!==undefined) { 256 | args.error(data); 257 | } 258 | } 259 | }); 260 | } 261 | } 262 | 263 | } else{ 264 | console.error("Please provide a topic string in topic argument"); 265 | } 266 | 267 | }; 268 | exports.unsubscribe = function(args){ 269 | if(args.topic.length > 0){ 270 | if (cordova.platformId === "android") { 271 | exec(function(data){ 272 | console.log("data",data); 273 | switch(data.call){ 274 | case "success": 275 | delete data.call; 276 | if (args.success!==undefined) { 277 | args.success(data); 278 | } 279 | if (router!==null) { 280 | router.removeListener(args.topic); 281 | } 282 | break; 283 | case "failure": 284 | delete data.call; 285 | if (args.error!==undefined) { 286 | args.error(data); 287 | } 288 | break; 289 | } 290 | }, function(e){ 291 | console.error(e); 292 | args.error(e); 293 | }, "CordovaMqTTPlugin", "unsubscribe", [args.topic]); 294 | } else { 295 | if (client !== null) { 296 | client.unsubscribe(args.topic,{ 297 | timeout:args.timeout||5000, 298 | onSuccess:function(cd,data){ 299 | if (args.success!==undefined) { 300 | args.success(data); 301 | } 302 | }, 303 | onFailure:function (cd,data) { 304 | if (args.error!==undefined) { 305 | args.error(data); 306 | } 307 | } 308 | }); 309 | } 310 | } 311 | 312 | } else{ 313 | console.error("Please provide a topic string in topic argument"); 314 | } 315 | }; 316 | exports.disconnect = function(args){ 317 | if (cordova.platformId === "android") { 318 | exec(function(data){ 319 | console.log("data",data); 320 | switch(data.call){ 321 | case "success": 322 | delete data.call; 323 | if (args.success!==undefined) { 324 | args.success(data); 325 | } 326 | break; 327 | case "failure": 328 | delete data.call; 329 | if (args.error!==undefined) { 330 | args.error(data); 331 | } 332 | break; 333 | } 334 | }, function(e){ 335 | console.error(e); 336 | args.error(e); 337 | }, "CordovaMqTTPlugin", "disconnect", []); 338 | } else { 339 | if (client !== null) { 340 | client.disconnect(); 341 | } 342 | } 343 | }; 344 | exports.router = function() { 345 | if (router!==null) { 346 | return router; 347 | } else { 348 | console.error("Router object seems to be destroyed"); 349 | } 350 | }; 351 | exports.listen = function (topic,cb) { 352 | if (router!==null) { 353 | router.on(topic,cb); 354 | } else { 355 | console.error("Router object seems to be destroyed"); 356 | } 357 | }; 358 | --------------------------------------------------------------------------------