├── README.md ├── examples ├── mqttSwitchBroker │ └── mqttSwitchBroker.ino ├── mqttqostest │ └── mqttqostest.ino ├── mqtttest │ └── mqtttest.ino └── threadtest │ └── testapps.ino ├── library.properties ├── license.txt └── src ├── MQTT.cpp ├── MQTT.h └── MQTT └── MQTT.h /README.md: -------------------------------------------------------------------------------- 1 | # MQTT for Photon, Spark Core 2 | MQTT publish/subscribe library for Photon, Argon, Tracker One...etc version 0.4.32. 3 | 4 | ## Source Code 5 | This lightweight library source code is only 2 files. firmware -> MQTT.cpp, MQTT.h. 6 | 7 | The application can use QoS 0, 1, 2 and the retain flag when publishing a message. 8 | 9 | ## Example 10 | Some sample sketches for Spark Core and Photon included (firmware/examples/). 11 | - mqtttest.ino : simple pub/sub sample. 12 | - mqttqostest.ino : QoS1, QoS2 publish and callback sample. 13 | - mqttSwitchBroker.ino : Example of how to switch to different brokers. 14 | - threadtest.ino : Example of SYSTEM_THREAD(ENABLED). 15 | 16 | ## developer examples 17 | some applications use MQTT with Photon. here are developer's reference examples. 18 | - Spark Core / Photon and CloudMQTT 19 | - MQTT Publish-Subscribe Using Rpi, ESP and Photon 20 | - Particle Photon on Watson IoT 21 | - Connecting IoT devices to the Watson Conversation Car-Dashboard app 22 | - ThingSpeak MQTT API 23 | - How to Connect a Particle Photon to the Losant IoT Platform 24 | - How I Hacked my Humidor with Losant and a Particle Photon 25 | - How to Build a Photon MQTT Logger 26 | - Particle and Ubidots using MQTT 27 | - Using Twilio Sync with MQTT on a Particle Photon 28 | 29 | ## sample source 30 | ``` 31 | #include "application.h" 32 | #include "MQTT.h" 33 | 34 | void callback(char* topic, byte* payload, unsigned int length); 35 | MQTT client("iot.eclipse.org", 1883, callback); 36 | 37 | // recieve message 38 | void callback(char* topic, byte* payload, unsigned int length) { 39 | char p[length + 1]; 40 | memcpy(p, payload, length); 41 | p[length] = NULL; 42 | 43 | if (!strcmp(p, "RED")) 44 | RGB.color(255, 0, 0); 45 | else if (!strcmp(p, "GREEN")) 46 | RGB.color(0, 255, 0); 47 | else if (!strcmp(p, "BLUE")) 48 | RGB.color(0, 0, 255); 49 | else 50 | RGB.color(255, 255, 255); 51 | delay(1000); 52 | } 53 | 54 | 55 | void setup() { 56 | RGB.control(true); 57 | 58 | // connect to the server(unique id by Time.now()) 59 | client.connect("sparkclient_" + String(Time.now())); 60 | 61 | // publish/subscribe 62 | if (client.isConnected()) { 63 | client.publish("outTopic/message","hello world"); 64 | client.subscribe("inTopic/message"); 65 | } 66 | } 67 | 68 | void loop() { 69 | if (client.isConnected()) 70 | client.loop(); 71 | } 72 | ``` 73 | ## FAQ 74 | ### Can't connect/publish/subscribe to the MQTT server? 75 | - Test your MQTT server and port (default 1883) with the mosquitto_pub/sub command. 76 | - Check your network environments. Make sure your MQTT server can reach the Internet through your firewall. 77 | - Verify your subscribe/publish topic name is correct. 78 | - Perhaps device firmware network stack is failed. check your firmware version and bugs. 79 | - If you are using MQTT-TLS, make sure your RooT CA pem file, client key, certifications is valid. 80 | - Several MQTT servers will disconnect the first connection when you use the same user_id. When the application calls the connect method, use a different user_id on every device as connect method's second argument. Using the MAC address as a user_id is suggested. 81 |
 82 |    // device.1
 83 |    client.connect("spark-client", "user_1", "password1");
 84 |    // other devices...
 85 |    client.connect("spark-client", "user_others", "password1");
 86 | 
87 | 88 | ### I want to change MQTT keepalive timeout. 89 | MQTT keepalive timeout is defined "MQTT_DEFAULT_KEEPALIVE 15"(15 sec) in header file. You can change the keepalive timeout in constructor. 90 |
 91 |     MQTT client("server_name", 1883, callback); // default: send keepalive packet to MQTT server every 15sec.
 92 |     MQTT client("server_name", 1883, 256, 30, callback); // keepalive timeout is 30 seconds, default message size also added to be able to access correct constructor 
 93 | 
94 | 95 | ### Want to use over the 255 byte message size. 96 | In this library, the maximum MQTT message size is defined as "MQTT_MAX_PACKET_SIZE 255" in the header file. If you want to use over 255 bytes, use the constructor's last argument. 97 |
 98 |     MQTT client("server_name", 1883, callback);      // default 255 bytes
 99 |     MQTT client("server_name", 1883, 512, callback); // max 512 bytes
100 | 
101 | 102 | ### Can I use on old firmware? 103 | No, use the default latest firmware. I tested this library on the default latest firmware or the latest pre-release version. If you use an old firmware it may not work well and is not supported. 104 | 105 | ### Bug or Problem? 106 | First, check the Particle community site. But if your problem is not resolved, please create an issue with the problem details. 107 | 108 | ### Pull Request 109 | If you have a bug fix or feature, please send a pull request. 110 | Thanks for all developers' pull requests! 111 | 112 | -------------------------------------------------------------------------------- /examples/mqttSwitchBroker/mqttSwitchBroker.ino: -------------------------------------------------------------------------------- 1 | #include "MQTT.h" 2 | 3 | const char *domain1 = "iot.eclipse.org"; 4 | const char *domain2 = "test.mosquitto.org"; 5 | const uint8_t server1[] = {192,168,1,2}; 6 | const uint8_t server2[] = {192,168,1,3}; 7 | 8 | void callback(char* topic, byte* payload, unsigned int length); 9 | 10 | /** 11 | * if want to use IP address, 12 | * const uint8_t[] = { XXX,XXX,XXX,XXX }; 13 | * MQTT client(server, 1883, callback); 14 | * want to use domain name, 15 | * MQTT client("www.sample.com", 1883, callback); 16 | **/ 17 | MQTT client(server1, 1883, callback); 18 | 19 | // recieve message 20 | void callback(char* topic, byte* payload, unsigned int length) { 21 | char p[length + 1]; 22 | memcpy(p, payload, length); 23 | p[length] = NULL; 24 | 25 | if (!strcmp(p, "RED")) 26 | RGB.color(255, 0, 0); 27 | else if (!strcmp(p, "GREEN")) 28 | RGB.color(0, 255, 0); 29 | else if (!strcmp(p, "BLUE")) 30 | RGB.color(0, 0, 255); 31 | else 32 | RGB.color(255, 255, 255); 33 | 34 | delay(1000); 35 | } 36 | 37 | 38 | void setup() { 39 | Serial.begin(); 40 | RGB.control(true); 41 | client.connect("sparkclient"); 42 | if (client.isConnected()) { 43 | client.publish("192392391/message","hello world"); 44 | client.subscribe("192392391/message"); 45 | } 46 | } 47 | 48 | void loop() { 49 | if (client.isConnected()) { 50 | client.loop(); 51 | } 52 | 53 | if (Serial.available() > 0) { 54 | long incomingChar = Serial.parseInt(); 55 | switch (incomingChar) { 56 | case 1: 57 | client.setBroker(domain1, 1883); 58 | break; 59 | case 2: 60 | client.setBroker(domain2, 1883); 61 | break; 62 | case 3: 63 | client.setBroker(server1, 1883); 64 | break; 65 | case 4: 66 | client.setBroker(server2, 1883); 67 | break; 68 | } 69 | client.connect("sparkclient"); 70 | if (client.isConnected()) { 71 | client.publish("192392391/message","hello world"); 72 | client.subscribe("192392391/message"); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /examples/mqttqostest/mqttqostest.ino: -------------------------------------------------------------------------------- 1 | #include "MQTT.h" 2 | 3 | void callback(char* topic, byte* payload, unsigned int length); 4 | 5 | /** 6 | * if want to use IP address, 7 | * const uint8_t server[] = { XXX,XXX,XXX,XXX }; 8 | * MQTT client(server, 1883, callback); 9 | * want to use domain name, 10 | * exp) iot.eclipse.org is Eclipse Open MQTT Broker: https://iot.eclipse.org/getting-started 11 | * MQTT client("mqtt.eclipse.org", 1883, callback); 12 | **/ 13 | MQTT client("server_name", 1883, callback); 14 | 15 | // for QoS2 MQTTPUBREL message. 16 | // this messageid maybe have store list or array structure. 17 | uint16_t qos2messageid = 0; 18 | 19 | // recieve message 20 | void callback(char* topic, byte* payload, unsigned int length) { 21 | char p[length + 1]; 22 | memcpy(p, payload, length); 23 | p[length] = NULL; 24 | 25 | if (!strcmp(p, "RED")) 26 | RGB.color(255, 0, 0); 27 | else if (!strcmp(p, "GREEN")) 28 | RGB.color(0, 255, 0); 29 | else if (!strcmp(p, "BLUE")) 30 | RGB.color(0, 0, 255); 31 | else 32 | RGB.color(255, 255, 255); 33 | delay(1000); 34 | } 35 | 36 | // QOS ack callback. 37 | // if application use QOS1 or QOS2, MQTT server sendback ack message id. 38 | void qoscallback(unsigned int messageid) { 39 | Serial.print("Ack Message Id:"); 40 | Serial.println(messageid); 41 | } 42 | 43 | void setup() { 44 | Serial.begin(9600); 45 | RGB.control(true); 46 | 47 | // connect to the server 48 | client.connect("sparkclient"); 49 | 50 | // add qos callback. If don't add qoscallback, ACK message from MQTT server is ignored. 51 | client.addQosCallback(qoscallback); 52 | 53 | // publish/subscribe 54 | if (client.isConnected()) { 55 | // get the messageid from parameter at 4. 56 | uint16_t messageid; 57 | client.publish("outTopic/message", "hello world QOS1", MQTT::QOS1, &messageid); 58 | Serial.println(messageid); 59 | 60 | // if 4th parameter don't set or NULL, application can not check the message id to the ACK message from MQTT server. 61 | client.publish("outTopic/message", "hello world QOS1(message is NULL)", MQTT::QOS1); 62 | 63 | // QOS=2 64 | client.publish("outTopic/message", "hello world QOS2", MQTT::QOS2, &messageid); 65 | Serial.println(messageid); 66 | 67 | // save QoS2 message id as global parameter. 68 | qos2messageid = messageid; 69 | 70 | // MQTT subscribe endpoint could have the QoS 71 | client.subscribe("inTopic/message", MQTT::QOS2); 72 | } 73 | } 74 | 75 | void loop() { 76 | if (client.isConnected()) 77 | client.loop(); 78 | } 79 | 80 | -------------------------------------------------------------------------------- /examples/mqtttest/mqtttest.ino: -------------------------------------------------------------------------------- 1 | #include "MQTT.h" 2 | 3 | void callback(char* topic, byte* payload, unsigned int length); 4 | 5 | /** 6 | * if want to use IP address, 7 | * const uint8_t[] = { XXX,XXX,XXX,XXX }; 8 | * MQTT client(server, 1883, callback); 9 | * want to use domain name, 10 | * exp) iot.eclipse.org is Eclipse Open MQTT Broker: https://iot.eclipse.org/getting-started 11 | * MQTT client("mqtt.eclipse.org", 1883, callback); 12 | **/ 13 | MQTT client("server_name", 1883, callback); 14 | 15 | // recieve message 16 | void callback(char* topic, byte* payload, unsigned int length) { 17 | char p[length + 1]; 18 | memcpy(p, payload, length); 19 | p[length] = NULL; 20 | 21 | if (!strcmp(p, "RED")) 22 | RGB.color(255, 0, 0); 23 | else if (!strcmp(p, "GREEN")) 24 | RGB.color(0, 255, 0); 25 | else if (!strcmp(p, "BLUE")) 26 | RGB.color(0, 0, 255); 27 | else 28 | RGB.color(255, 255, 255); 29 | delay(1000); 30 | } 31 | 32 | 33 | void setup() { 34 | RGB.control(true); 35 | 36 | // connect to the server 37 | client.connect("sparkclient"); 38 | 39 | // publish/subscribe 40 | if (client.isConnected()) { 41 | client.publish("outTopic/message","hello world"); 42 | client.subscribe("inTopic/message"); 43 | } 44 | } 45 | 46 | void loop() { 47 | if (client.isConnected()) 48 | client.loop(); 49 | } 50 | -------------------------------------------------------------------------------- /examples/threadtest/testapps.ino: -------------------------------------------------------------------------------- 1 | #include "MQTT.h" 2 | 3 | SYSTEM_THREAD(ENABLED); 4 | void callback(char* topic, byte* payload, unsigned int length); 5 | 6 | /** 7 | * if want to use IP address, 8 | * const uint8_t[] = { XXX,XXX,XXX,XXX }; 9 | * MQTT client(server, 1883, callback); 10 | * want to use domain name, 11 | * exp) iot.eclipse.org is Eclipse Open MQTT Broker: https://iot.eclipse.org/getting-started 12 | * MQTT client("mqtt.eclipse.org", 1883, callback, true); 13 | * 4th parameter : bool thread(default false.) 14 | * SYSTEM_THREAD(ENABLED) settings : thread is true. 15 | **/ 16 | MQTT client("sample.com", 1883, callback, true); 17 | 18 | // recieve message 19 | void callback(char* topic, byte* payload, unsigned int length) { 20 | char p[length + 1]; 21 | memcpy(p, payload, length); 22 | p[length] = NULL; 23 | 24 | if (!strcmp(p, "RED")) 25 | RGB.color(255, 0, 0); 26 | else if (!strcmp(p, "GREEN")) 27 | RGB.color(0, 255, 0); 28 | else if (!strcmp(p, "BLUE")) 29 | RGB.color(0, 0, 255); 30 | else 31 | RGB.color(255, 255, 255); 32 | delay(1000); 33 | } 34 | 35 | 36 | void setup() { 37 | WiFi.on(); 38 | WiFi.setCredentials("ssid", "pass"); 39 | WiFi.connect(); 40 | waitUntil(WiFi.ready); 41 | while (WiFi.localIP() == IPAddress()) { 42 | delay(10); 43 | } 44 | 45 | // set LED control 46 | RGB.control(true); 47 | 48 | // connect to the server 49 | client.connect("sparkclient"); 50 | 51 | // publish/subscribe 52 | if (client.isConnected()) { 53 | client.publish("outTopic/message","hello world"); 54 | client.subscribe("inTopic/message"); 55 | } 56 | } 57 | 58 | void loop() { 59 | if (client.isConnected()) 60 | client.loop(); 61 | delay(100); 62 | } 63 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=MQTT 2 | version=0.4.32 3 | license=MIT 4 | author=hirotakaster 5 | url=https://github.com/hirotakaster/MQTT/ 6 | repository=https://github.com/hirotakaster/MQTT.git 7 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Hirotaka Niisato 2 | This software is released under the MIT License. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | Much of the code was inspired by Arduino Nicholas pubsubclient 24 | sample code bearing this copyright. 25 | //--------------------------------------------------------------------------- 26 | // Copyright (c) 2008-2012 Nicholas O'Leary 27 | // 28 | // Permission is hereby granted, free of charge, to any person obtaining 29 | // a copy of this software and associated documentation files (the 30 | // "Software"), to deal in the Software without restriction, including 31 | // without limitation the rights to use, copy, modify, merge, publish, 32 | // distribute, sublicense, and/or sell copies of the Software, and to 33 | // permit persons to whom the Software is furnished to do so, subject to 34 | // the following conditions: 35 | // 36 | // The above copyright notice and this permission notice shall be 37 | // included in all copies or substantial portions of the Software. 38 | // 39 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 40 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 41 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 42 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 43 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 44 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 45 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 46 | //--------------------------------------------------------------------------- 47 | -------------------------------------------------------------------------------- /src/MQTT.cpp: -------------------------------------------------------------------------------- 1 | #include "MQTT.h" 2 | 3 | #define LOGGING 4 | 5 | #define MQTTQOS0_HEADER_MASK (0 << 1) 6 | #define MQTTQOS1_HEADER_MASK (1 << 1) 7 | #define MQTTQOS2_HEADER_MASK (2 << 1) 8 | 9 | #define DUP_FLAG_OFF_MASK (0<<3) 10 | #define DUP_FLAG_ON_MASK (1<<3) 11 | 12 | MQTT::MQTT(const char* domain, uint16_t port, void (*callback)(char*,uint8_t*,unsigned int), 13 | bool thread) { 14 | this->initialize(domain, NULL, port, MQTT_DEFAULT_KEEPALIVE, MQTT_MAX_PACKET_SIZE, callback, thread); 15 | } 16 | 17 | MQTT::MQTT(const char* domain, uint16_t port, int maxpacketsize, void (*callback)(char*,uint8_t*,unsigned int), 18 | bool thread) { 19 | this->initialize(domain, NULL, port, MQTT_DEFAULT_KEEPALIVE, maxpacketsize, callback, thread); 20 | } 21 | 22 | MQTT::MQTT(const uint8_t *ip, uint16_t port, void (*callback)(char*,uint8_t*,unsigned int), 23 | bool thread) { 24 | this->initialize(NULL, ip, port, MQTT_DEFAULT_KEEPALIVE, MQTT_MAX_PACKET_SIZE, callback, thread); 25 | } 26 | 27 | MQTT::MQTT(const uint8_t *ip, uint16_t port, int maxpacketsize, void (*callback)(char*,uint8_t*,unsigned int), 28 | bool thread) { 29 | this->initialize(NULL, ip, port, MQTT_DEFAULT_KEEPALIVE, maxpacketsize, callback, thread); 30 | } 31 | 32 | MQTT::MQTT(const char* domain, uint16_t port, int maxpacketsize, int keepalive, void (*callback)(char*,uint8_t*,unsigned int), 33 | bool thread) { 34 | this->initialize(domain, NULL, port, keepalive, maxpacketsize, callback, thread); 35 | } 36 | 37 | MQTT::MQTT(const uint8_t *ip, uint16_t port, int maxpacketsize, int keepalive, void (*callback)(char*,uint8_t*,unsigned int), 38 | bool thread) { 39 | this->initialize(NULL, ip, port, keepalive, maxpacketsize, callback, thread); 40 | } 41 | 42 | MQTT::~MQTT() { 43 | if (isConnected()) { 44 | disconnect(); 45 | } 46 | 47 | if (buffer != NULL) 48 | delete[] buffer; 49 | } 50 | 51 | void MQTT::initialize(const char* domain, const uint8_t *ip, uint16_t port, int keepalive, int maxpacketsize, 52 | void (*callback)(char*,uint8_t*,unsigned int), bool thread) { 53 | if (thread) { 54 | this->thread = true; 55 | os_mutex_create(&mutex_lock); 56 | } 57 | this->callback = callback; 58 | this->qoscallback = NULL; 59 | if (ip != NULL) 60 | this->ip = ip; 61 | if (domain != NULL) 62 | this->domain = domain; 63 | this->port = port; 64 | this->keepalive = keepalive; 65 | 66 | // if maxpacketsize is over MQTT_MAX_PACKET_SIZE. 67 | this->maxpacketsize = (maxpacketsize <= MQTT_MAX_PACKET_SIZE ? MQTT_MAX_PACKET_SIZE : maxpacketsize); 68 | if (buffer != NULL) 69 | delete[] buffer; 70 | buffer = new uint8_t[this->maxpacketsize]; 71 | } 72 | 73 | void MQTT::setBroker(const char* domain, uint16_t port) { 74 | if(isConnected()) { 75 | disconnect(); 76 | } 77 | this->domain = domain; 78 | this->ip = NULL; 79 | this->port = port; 80 | } 81 | 82 | void MQTT::setBroker(const uint8_t *ip, uint16_t port) { 83 | if(isConnected()) { 84 | disconnect(); 85 | } 86 | this->domain = ""; 87 | this->ip = ip; 88 | this->port = port; 89 | } 90 | 91 | 92 | void MQTT::addQosCallback(void (*qoscallback)(unsigned int)) { 93 | this->qoscallback = qoscallback; 94 | } 95 | 96 | 97 | bool MQTT::connect(const char *id) { 98 | return connect(id, NULL, NULL, 0, QOS0, 0, 0, true); 99 | } 100 | 101 | bool MQTT::connect(const char *id, const char *user, const char *pass) { 102 | return connect(id, user, pass, 0, QOS0, 0, 0, true); 103 | } 104 | 105 | bool MQTT::connect(const char *id, const char *user, const char *pass, const char* willTopic, EMQTT_QOS willQos, uint8_t willRetain, const char* willMessage, bool cleanSession, MQTT_VERSION version) { 106 | if (!isConnected()) { 107 | MutexLocker lock(this); 108 | int result = 0; 109 | if (ip == NULL) 110 | result = _client.connect(this->domain.c_str(), this->port); 111 | else 112 | result = _client.connect(this->ip, this->port); 113 | 114 | if (result) { 115 | nextMsgId = 1; 116 | uint16_t length = 5; 117 | 118 | if (version == MQTT_V311) { 119 | const uint8_t MQTT_HEADER_V311[] = {0x00,0x04,'M','Q','T','T',MQTT_V311}; 120 | memcpy(buffer + length, MQTT_HEADER_V311, sizeof(MQTT_HEADER_V311)); 121 | length+=sizeof(MQTT_HEADER_V311); 122 | } else { 123 | const uint8_t MQTT_HEADER_V31[] = {0x00,0x06,'M','Q','I','s','d','p', MQTT_V31}; 124 | memcpy(buffer + length, MQTT_HEADER_V31, sizeof(MQTT_HEADER_V31)); 125 | length+=sizeof(MQTT_HEADER_V31); 126 | } 127 | 128 | uint8_t v = 0; 129 | if (willTopic) { 130 | v = 0x06|(willQos<<3)|(willRetain<<5); 131 | } else { 132 | v = 0x02; 133 | } 134 | 135 | if (!cleanSession) { 136 | v = v&0xfd; 137 | } 138 | 139 | if(user != NULL) { 140 | v = v|0x80; 141 | 142 | if(pass != NULL) { 143 | v = v|(0x80>>1); 144 | } 145 | } 146 | 147 | buffer[length++] = v; 148 | 149 | buffer[length++] = ((this->keepalive) >> 8); 150 | buffer[length++] = ((this->keepalive) & 0xFF); 151 | length = writeString(id, buffer, length); 152 | if (willTopic) { 153 | length = writeString(willTopic, buffer, length); 154 | length = writeString(willMessage, buffer, length); 155 | } 156 | 157 | if(user != NULL) { 158 | length = writeString(user,buffer,length); 159 | if(pass != NULL) { 160 | length = writeString(pass,buffer,length); 161 | } 162 | } 163 | 164 | write(MQTTCONNECT, buffer, length-5); 165 | lastInActivity = lastOutActivity = millis(); 166 | 167 | while (!_client.available()) { 168 | unsigned long t = millis(); 169 | if (t-lastInActivity > this->keepalive*1000UL) { 170 | _client.stop(); 171 | return false; 172 | } 173 | } 174 | uint8_t llen; 175 | uint16_t len = readPacket(&llen); 176 | 177 | if (len == 4) { 178 | if (buffer[3] == CONN_ACCEPT) { 179 | lastInActivity = millis(); 180 | pingOutstanding = false; 181 | debug_print(" Connect success\n"); 182 | return true; 183 | } else { 184 | // check EMQTT_CONNACK_RESPONSE code. 185 | debug_print(" Connect fail. code = [%d]\n", buffer[3]); 186 | } 187 | } 188 | } 189 | _client.stop(); 190 | } 191 | return false; 192 | } 193 | 194 | uint8_t MQTT::readByte() { 195 | while(!_client.available()) {} 196 | return _client.read(); 197 | } 198 | 199 | uint16_t MQTT::readPacket(uint8_t* lengthLength) { 200 | uint16_t len = 0; 201 | buffer[len++] = readByte(); 202 | bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH; 203 | uint32_t multiplier = 1; 204 | uint16_t length = 0; 205 | uint8_t digit = 0; 206 | uint16_t skip = 0; 207 | uint8_t start = 0; 208 | 209 | do { 210 | digit = readByte(); 211 | buffer[len++] = digit; 212 | length += (digit & 127) * multiplier; 213 | multiplier *= 128; 214 | } while ((digit & 128) != 0); 215 | *lengthLength = len-1; 216 | 217 | if (isPublish) { 218 | // Read in topic length to calculate bytes to skip over for Stream writing 219 | buffer[len++] = readByte(); 220 | buffer[len++] = readByte(); 221 | skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2]; 222 | start = 2; 223 | if (buffer[0] & MQTTQOS1_HEADER_MASK) { 224 | // skip message id 225 | skip += 2; 226 | } 227 | } 228 | 229 | for (uint16_t i = start;imaxpacketsize) { 232 | buffer[len] = digit; 233 | } 234 | len++; 235 | } 236 | 237 | if (len > this->maxpacketsize) { 238 | len = 0; // This will cause the packet to be ignored. 239 | } 240 | 241 | return len; 242 | } 243 | 244 | bool MQTT::loop() { 245 | if (isConnected()) { 246 | MutexLocker lock(this); 247 | 248 | unsigned long t = millis(); 249 | if ((t - lastInActivity > this->keepalive*1000UL) || (t - lastOutActivity > this->keepalive*1000UL)) { 250 | if (pingOutstanding) { 251 | _client.stop(); 252 | return false; 253 | } else { 254 | buffer[0] = MQTTPINGREQ; 255 | buffer[1] = 0; 256 | _client.write(buffer,2); 257 | lastOutActivity = t; 258 | lastInActivity = t; 259 | pingOutstanding = true; 260 | } 261 | } 262 | 263 | if (_client.available()) { 264 | uint8_t llen; 265 | uint16_t len = readPacket(&llen); 266 | uint16_t msgId = 0; 267 | uint8_t *payload; 268 | if (len > 0) { 269 | lastInActivity = t; 270 | uint8_t type = buffer[0]&0xF0; 271 | if (type == MQTTPUBLISH) { 272 | if (callback) { 273 | uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; // topic length 274 | char topic[tl+1]; 275 | for (uint16_t i=0;i0 280 | if ((buffer[0]&0x06) == MQTTQOS1_HEADER_MASK) { // QoS=1 281 | msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1]; 282 | payload = buffer+llen+3+tl+2; 283 | callback(topic,payload,len-llen-3-tl-2); 284 | 285 | buffer[0] = MQTTPUBACK; // respond with PUBACK 286 | buffer[1] = 2; 287 | buffer[2] = (msgId >> 8); 288 | buffer[3] = (msgId & 0xFF); 289 | _client.write(buffer,4); 290 | lastOutActivity = t; 291 | } else if ((buffer[0] & 0x06) == MQTTQOS2_HEADER_MASK) { // QoS=2 292 | msgId = (buffer[llen + 3 + tl] << 8) + buffer[llen + 3 + tl + 1]; 293 | payload = buffer + llen + 3 + tl + 2; 294 | callback(topic, payload, len - llen - 3 - tl - 2); 295 | 296 | buffer[0] = MQTTPUBREC; // respond with PUBREC 297 | buffer[1] = 2; 298 | buffer[2] = (msgId >> 8); 299 | buffer[3] = (msgId & 0xFF); 300 | _client.write(buffer, 4); 301 | lastOutActivity = t; 302 | } else { 303 | payload = buffer+llen+3+tl; 304 | callback(topic,payload,len-llen-3-tl); 305 | } 306 | } 307 | } else if (type == MQTTPUBREC) { 308 | // check for the situation that QoS2 receive PUBREC, should return PUBREL 309 | msgId = (buffer[2] << 8) + buffer[3]; 310 | this->publishRelease(msgId); 311 | } else if (type == MQTTPUBACK) { 312 | if (qoscallback) { 313 | // this case QOS==1 314 | if (len == 4 && (buffer[0]&0x06) == MQTTQOS0_HEADER_MASK) { 315 | msgId = (buffer[2]<<8)+buffer[3]; 316 | this->qoscallback(msgId); 317 | } 318 | } 319 | } else if (type == MQTTPUBREL) { 320 | msgId = (buffer[2] << 8) + buffer[3]; 321 | this->publishComplete(msgId); 322 | } else if (type == MQTTPUBCOMP) { 323 | if (qoscallback) { 324 | // msgId only present for QOS==0 325 | if (len == 4 && (buffer[0]&0x06) == MQTTQOS0_HEADER_MASK) { 326 | msgId = (buffer[2]<<8)+buffer[3]; 327 | this->qoscallback(msgId); 328 | } 329 | } 330 | } else if (type == MQTTSUBACK) { 331 | // if something... 332 | } else if (type == MQTTPINGREQ) { 333 | buffer[0] = MQTTPINGRESP; 334 | buffer[1] = 0; 335 | _client.write(buffer,2); 336 | } else if (type == MQTTPINGRESP) { 337 | pingOutstanding = false; 338 | } 339 | } 340 | } 341 | return true; 342 | } 343 | return false; 344 | } 345 | 346 | bool MQTT::publish(const char* topic, const char* payload) { 347 | return publish(topic, (uint8_t*)payload, strlen(payload), false, QOS0, NULL); 348 | } 349 | 350 | bool MQTT::publish(const char* topic, const char* payload, bool retain) { 351 | return publish(topic, (uint8_t*)payload, strlen(payload), retain, QOS0, NULL); 352 | } 353 | 354 | bool MQTT::publish(const char * topic, const char* payload, EMQTT_QOS qos, bool dup, uint16_t *messageid) { 355 | return publish(topic, (uint8_t*)payload, strlen(payload), false, qos, dup, messageid); 356 | } 357 | 358 | bool MQTT::publish(const char * topic, const char* payload, EMQTT_QOS qos, uint16_t *messageid) { 359 | return publish(topic, (uint8_t*)payload, strlen(payload), false, qos, messageid); 360 | } 361 | 362 | bool MQTT::publish(const char* topic, const uint8_t* payload, unsigned int plength) { 363 | return publish(topic, payload, plength, false, QOS0, NULL); 364 | } 365 | 366 | bool MQTT::publish(const char* topic, const uint8_t* payload, unsigned int plength, EMQTT_QOS qos, bool dup, uint16_t *messageid) { 367 | return publish(topic, payload, plength, false, qos, dup, messageid); 368 | } 369 | 370 | bool MQTT::publish(const char* topic, const uint8_t* payload, unsigned int plength, EMQTT_QOS qos, uint16_t *messageid) { 371 | return publish(topic, payload, plength, false, qos, messageid); 372 | } 373 | 374 | bool MQTT::publish(const char* topic, const uint8_t* payload, unsigned int plength, bool retain) { 375 | return publish(topic, payload, plength, retain, QOS0, NULL); 376 | } 377 | 378 | bool MQTT::publish(const char* topic, const uint8_t* payload, unsigned int plength, bool retain, EMQTT_QOS qos, uint16_t *messageid) { 379 | return publish(topic, payload, plength, retain, qos, false, messageid); 380 | } 381 | 382 | bool MQTT::publish(const char* topic, const uint8_t* payload, unsigned int plength, bool retain, EMQTT_QOS qos, bool dup, uint16_t *messageid) { 383 | if (isConnected()) { 384 | MutexLocker lock(this); 385 | // Leave room in the buffer for header and variable length field 386 | uint16_t length = 5; 387 | memset(buffer, 0, this->maxpacketsize); 388 | 389 | length = writeString(topic, buffer, length); 390 | 391 | if (qos == QOS2 || qos == QOS1) { 392 | nextMsgId += 1; 393 | buffer[length++] = (nextMsgId >> 8); 394 | buffer[length++] = (nextMsgId & 0xFF); 395 | if (messageid != NULL) 396 | *messageid = nextMsgId++; 397 | } 398 | 399 | for (uint16_t i=0; i < plength && length < this->maxpacketsize; i++) { 400 | buffer[length++] = payload[i]; 401 | } 402 | 403 | uint8_t header = MQTTPUBLISH; 404 | if (retain) { 405 | header |= 1; 406 | } 407 | 408 | if (dup) { 409 | header |= DUP_FLAG_ON_MASK; 410 | } 411 | 412 | if (qos == QOS2) 413 | header |= MQTTQOS2_HEADER_MASK; 414 | else if (qos == QOS1) 415 | header |= MQTTQOS1_HEADER_MASK; 416 | else 417 | header |= MQTTQOS0_HEADER_MASK; 418 | 419 | return write(header, buffer, length-5); 420 | } 421 | return false; 422 | } 423 | 424 | bool MQTT::publishRelease(uint16_t messageid) { 425 | if (isConnected()) { 426 | MutexLocker lock(this); 427 | uint16_t length = 0; 428 | // reserved bits in MQTT v3.1.1 429 | buffer[length++] = MQTTPUBREL | MQTTQOS1_HEADER_MASK; 430 | buffer[length++] = 2; 431 | buffer[length++] = (messageid >> 8); 432 | buffer[length++] = (messageid & 0xFF); 433 | return _client.write(buffer, length); 434 | } 435 | return false; 436 | } 437 | 438 | bool MQTT::publishComplete(uint16_t messageid) { 439 | if (isConnected()) { 440 | MutexLocker lock(this); 441 | uint16_t length = 0; 442 | // reserved bits in MQTT v3.1.1 443 | buffer[length++] = MQTTPUBCOMP | MQTTQOS1_HEADER_MASK; 444 | buffer[length++] = 2; 445 | buffer[length++] = (messageid >> 8); 446 | buffer[length++] = (messageid & 0xFF); 447 | return _client.write(buffer, length); 448 | } 449 | return false; 450 | } 451 | 452 | bool MQTT::write(uint8_t header, uint8_t* buf, uint16_t length) { 453 | uint8_t lenBuf[4]; 454 | uint8_t llen = 0; 455 | uint8_t digit; 456 | uint8_t pos = 0; 457 | uint16_t rc; 458 | uint16_t len = length; 459 | do { 460 | digit = len % 128; 461 | len = len / 128; 462 | if (len > 0) { 463 | digit |= 0x80; 464 | } 465 | lenBuf[pos++] = digit; 466 | llen++; 467 | } while(len > 0); 468 | 469 | buf[4-llen] = header; 470 | for (int i = 0; i < llen; i++) { 471 | buf[5-llen+i] = lenBuf[i]; 472 | } 473 | rc = _client.write(buf+(4-llen), length+1+llen); 474 | 475 | lastOutActivity = millis(); 476 | return (rc == 1+llen+length); 477 | } 478 | 479 | bool MQTT::subscribe(const char* topic) { 480 | return subscribe(topic, QOS0); 481 | } 482 | 483 | bool MQTT::subscribe(const char* topic, EMQTT_QOS qos) { 484 | 485 | if (isConnected()) { 486 | // Leave room in the buffer for header and variable length field 487 | MutexLocker lock(this); 488 | uint16_t length = 5; 489 | nextMsgId++; 490 | if (nextMsgId == 0) { 491 | nextMsgId = 1; 492 | } 493 | buffer[length++] = (nextMsgId >> 8); 494 | buffer[length++] = (nextMsgId & 0xFF); 495 | length = writeString(topic, buffer,length); 496 | buffer[length++] = qos; 497 | return write(MQTTSUBSCRIBE | MQTTQOS1_HEADER_MASK,buffer,length-5); 498 | } 499 | return false; 500 | } 501 | 502 | bool MQTT::unsubscribe(const char* topic) { 503 | if (isConnected()) { 504 | MutexLocker lock(this); 505 | uint16_t length = 5; 506 | nextMsgId++; 507 | if (nextMsgId == 0) { 508 | nextMsgId = 1; 509 | } 510 | buffer[length++] = (nextMsgId >> 8); 511 | buffer[length++] = (nextMsgId & 0xFF); 512 | length = writeString(topic, buffer,length); 513 | return write(MQTTUNSUBSCRIBE | MQTTQOS1_HEADER_MASK,buffer,length-5); 514 | } 515 | return false; 516 | } 517 | 518 | void MQTT::disconnect() { 519 | MutexLocker lock(this); 520 | buffer[0] = MQTTDISCONNECT; 521 | buffer[1] = 0; 522 | _client.write(buffer,2); 523 | _client.stop(); 524 | lastInActivity = lastOutActivity = millis(); 525 | } 526 | 527 | uint16_t MQTT::writeString(const char* string, uint8_t* buf, uint16_t pos) { 528 | const char* idp = string; 529 | uint16_t i = 0; 530 | pos += 2; 531 | while (*idp && pos < this->maxpacketsize) { 532 | buf[pos++] = *idp++; 533 | i++; 534 | } 535 | buf[pos-i-2] = (i >> 8); 536 | buf[pos-i-1] = (i & 0xFF); 537 | return pos; 538 | } 539 | 540 | 541 | bool MQTT::isConnected() { 542 | bool rc = (int)_client.connected(); 543 | if (!rc) _client.stop(); 544 | return rc; 545 | } 546 | 547 | void MQTT::clear() { 548 | _client.stop(); 549 | lastInActivity = lastOutActivity = millis(); 550 | } 551 | -------------------------------------------------------------------------------- /src/MQTT.h: -------------------------------------------------------------------------------- 1 | /* 2 | MQTT library for Particle Core, Photon, Arduino 3 | This software is released under the MIT License. 4 | Copyright (c) 2014 Hirotaka Niisato 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | Much of the code was inspired by Arduino Nicholas pubsubclient 22 | sample code bearing this copyright. 23 | 24 | //--------------------------------------------------------------------------- 25 | // Copyright (c) 2008-2012 Nicholas O'Leary 26 | // 27 | // Permission is hereby granted, free of charge, to any person obtaining 28 | // a copy of this software and associated documentation files (the 29 | // "Software"), to deal in the Software without restriction, including 30 | // without limitation the rights to use, copy, modify, merge, publish, 31 | // distribute, sublicense, and/or sell copies of the Software, and to 32 | // permit persons to whom the Software is furnished to do so, subject to 33 | // the following conditions: 34 | // 35 | // The above copyright notice and this permission notice shall be 36 | // included in all copies or substantial portions of the Software. 37 | // 38 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 39 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 40 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 41 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 42 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 43 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 44 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 45 | //--------------------------------------------------------------------------- 46 | 47 | bug fixed and features pull requests 48 | * add publish(char*, char*, bool retain) #77 49 | * Updating readme.md #75 50 | * Fix bugs #74 51 | * Added setBroker method to update domain or ip and port. #52 52 | * Added keep alive setting #49 53 | * Added support for clean session flag #47 54 | * Fixed a buffer overflow / bad allocation size #38 55 | * Topics should not start with '/' #37 56 | * Completed path for Build IDE compatibility #23 57 | * QOS given as enum type - refer github issue 12 #15 58 | * retained is now a system keyword, fixes compiler issue #9 59 | * replace boolean with bool and include application.h #4 60 | * Proper include path for MQTT.h #1 61 | */ 62 | 63 | #ifndef __MQTT_H_ 64 | #define __MQTT_H_ 65 | 66 | #include "application.h" 67 | #include "spark_wiring_string.h" 68 | #include "spark_wiring_tcpclient.h" 69 | #include "spark_wiring_usbserial.h" 70 | 71 | // MQTT_MAX_PACKET_SIZE : Maximum packet size 72 | // this size is total of [MQTT Header(Max:5byte) + Topic Name Length + Topic Name + Message ID(QoS1|2) + Payload] 73 | #define MQTT_MAX_PACKET_SIZE 255 74 | 75 | // MQTT_KEEPALIVE : keepAlive interval in Seconds 76 | #define MQTT_DEFAULT_KEEPALIVE 15 77 | 78 | #define MQTTPROTOCOLVERSION 3 79 | #define MQTTCONNECT 1 << 4 // Client request to connect to Server 80 | #define MQTTCONNACK 2 << 4 // Connect Acknowledgment 81 | #define MQTTPUBLISH 3 << 4 // Publish message 82 | #define MQTTPUBACK 4 << 4 // Publish Acknowledgment 83 | #define MQTTPUBREC 5 << 4 // Publish Received (assured delivery part 1) 84 | #define MQTTPUBREL 6 << 4 // Publish Release (assured delivery part 2) 85 | #define MQTTPUBCOMP 7 << 4 // Publish Complete (assured delivery part 3) 86 | #define MQTTSUBSCRIBE 8 << 4 // Client Subscribe request 87 | #define MQTTSUBACK 9 << 4 // Subscribe Acknowledgment 88 | #define MQTTUNSUBSCRIBE 10 << 4 // Client Unsubscribe request 89 | #define MQTTUNSUBACK 11 << 4 // Unsubscribe Acknowledgment 90 | #define MQTTPINGREQ 12 << 4 // PING Request 91 | #define MQTTPINGRESP 13 << 4 // PING Response 92 | #define MQTTDISCONNECT 14 << 4 // Client is Disconnecting 93 | #define MQTTReserved 15 << 4 // Reserved 94 | 95 | 96 | // for debugging. 97 | // #define DEBUG_MQTT_SERIAL_OUTPUT 98 | #if defined(DEBUG_MQTT_SERIAL_OUTPUT) 99 | #define debug_print(fmt, ...) Serial.printf("[DEBUG] MQTT " fmt, ##__VA_ARGS__) 100 | #else /* !DEBUG_MQTT_SERIAL_OUTPUT */ 101 | #define debug_print(fmt, ...) ((void)0) 102 | #endif /* DEBUG_MQTT_SERIAL_OUTPUT */ 103 | 104 | 105 | class MQTT { 106 | /** types */ 107 | public: 108 | typedef enum { 109 | QOS0 = 0, 110 | QOS1 = 1, 111 | QOS2 = 2, 112 | } EMQTT_QOS; 113 | 114 | typedef enum{ 115 | MQTT_V31 = 3, 116 | MQTT_V311 = 4 117 | } MQTT_VERSION; 118 | 119 | typedef enum { 120 | CONN_ACCEPT = 0, 121 | CONN_UNACCEPTABLE_PROCOTOL = 1, 122 | CONN_ID_REJECT = 2, 123 | CONN_SERVER_UNAVAILALE = 3, 124 | CONN_BAD_USER_PASSWORD = 4, 125 | CONN_NOT_AUTHORIZED = 5 126 | } EMQTT_CONNACK_RESPONSE; 127 | 128 | private: 129 | TCPClient _client; 130 | uint8_t *buffer = NULL; 131 | uint16_t nextMsgId; 132 | unsigned long lastOutActivity; 133 | unsigned long lastInActivity; 134 | bool pingOutstanding; 135 | void (*callback)(char*,uint8_t*,unsigned int); 136 | void (*qoscallback)(unsigned int); 137 | uint16_t readPacket(uint8_t*); 138 | uint8_t readByte(); 139 | bool write(uint8_t header, uint8_t* buf, uint16_t length); 140 | uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos); 141 | String domain; 142 | const uint8_t *ip = NULL; 143 | uint16_t port; 144 | int keepalive; 145 | uint16_t maxpacketsize; 146 | os_mutex_t mutex_lock; 147 | bool thread = false; 148 | 149 | void initialize(const char* domain, const uint8_t *ip, uint16_t port, int keepalive, int maxpacketsize, 150 | void (*callback)(char*,uint8_t*,unsigned int), bool thread = false); 151 | bool publishRelease(uint16_t messageid); 152 | bool publishComplete(uint16_t messageid); 153 | 154 | class MutexLocker { 155 | MQTT * mqtt; 156 | public: 157 | MutexLocker(MQTT *mqtt) { 158 | #if defined(SPARK) 159 | #if defined(PLATFORM_ID) 160 | #if (PLATFORM_ID == 0) 161 | #else 162 | this->mqtt = mqtt; 163 | if (mqtt->thread) 164 | os_mutex_lock(mqtt->mutex_lock); 165 | #endif 166 | #endif 167 | #endif 168 | } 169 | ~MutexLocker() { 170 | #if defined(SPARK) 171 | #if defined(PLATFORM_ID) 172 | #if (PLATFORM_ID == 0) 173 | #else 174 | if (mqtt->thread) 175 | os_mutex_unlock(mqtt->mutex_lock); 176 | #endif 177 | #endif 178 | #endif 179 | } 180 | }; 181 | public: 182 | 183 | MQTT(){}; 184 | 185 | MQTT(const char* domain, uint16_t port, void (*callback)(char*,uint8_t*,unsigned int), bool thread = false); 186 | MQTT(const uint8_t *ip, uint16_t port, void (*callback)(char*,uint8_t*,unsigned int), bool thread = false); 187 | MQTT(const char* domain, uint16_t port, int maxpacketsize, void (*callback)(char*,uint8_t*,unsigned int), bool thread = false); 188 | MQTT(const uint8_t *ip, uint16_t port, int maxpacketsize, void (*callback)(char*,uint8_t*,unsigned int), bool thread = false); 189 | MQTT(const char* domain, uint16_t port, int maxpacketsize, int keepalive, void (*callback)(char*,uint8_t*,unsigned int), bool thread = false); 190 | MQTT(const uint8_t *ip, uint16_t port, int maxpacketsize, int keepalive, void (*callback)(char*,uint8_t*,unsigned int), bool thread = false); 191 | 192 | ~MQTT(); 193 | 194 | void setBroker(const char* domain, uint16_t port); 195 | void setBroker(const uint8_t *ip, uint16_t port); 196 | 197 | bool connect(const char *id); 198 | bool connect(const char *id, const char *user, const char *pass); 199 | bool connect(const char *id, const char *user, const char *pass, const char* willTopic, EMQTT_QOS willQos, uint8_t willRetain, const char* willMessage, bool cleanSession, MQTT_VERSION version = MQTT_V311); 200 | void disconnect(); 201 | void clear(); 202 | 203 | bool publish(const char *topic, const char* payload); 204 | bool publish(const char *topic, const char* payload, bool retain); 205 | bool publish(const char *topic, const char* payload, EMQTT_QOS qos, uint16_t *messageid = NULL); 206 | bool publish(const char *topic, const char* payload, EMQTT_QOS qos, bool dup, uint16_t *messageid = NULL); 207 | bool publish(const char *topic, const uint8_t *pyaload, unsigned int plength); 208 | bool publish(const char *topic, const uint8_t *payload, unsigned int plength, EMQTT_QOS qos, uint16_t *messageid = NULL); 209 | bool publish(const char *topic, const uint8_t *payload, unsigned int plength, EMQTT_QOS qos, bool dup, uint16_t *messageid = NULL); 210 | bool publish(const char *topic, const uint8_t *payload, unsigned int plength, bool retain); 211 | bool publish(const char *topic, const uint8_t *payload, unsigned int plength, bool retain, EMQTT_QOS qos, uint16_t *messageid = NULL); 212 | bool publish(const char *topic, const uint8_t *payload, unsigned int plength, bool retain, EMQTT_QOS qos, bool dup, uint16_t *messageid); 213 | void addQosCallback(void (*qoscallback)(unsigned int)); 214 | 215 | bool subscribe(const char *topic); 216 | bool subscribe(const char *topic, EMQTT_QOS); 217 | bool unsubscribe(const char *topic); 218 | bool loop(); 219 | bool isConnected(); 220 | }; 221 | 222 | #endif // __MQTT_H_ 223 | -------------------------------------------------------------------------------- /src/MQTT/MQTT.h: -------------------------------------------------------------------------------- 1 | #include "../MQTT.h" --------------------------------------------------------------------------------