From a971ed4a2cac1469a3be096faae41d9687df8c99 Mon Sep 17 00:00:00 2001 From: Nicholas O'Leary Date: Thu, 13 Sep 2012 22:35:48 +0100 Subject: [PATCH] Allow any instance of Client to be passed in. Added new example for publishing in callback. --- PubSubClient/CHANGES.txt | 7 ++ PubSubClient/PubSubClient.cpp | 73 ++++++++++--------- PubSubClient/PubSubClient.h | 12 +-- .../{mqtt_auth.pde => mqtt_auth.ino} | 8 +- .../{mqtt_basic.pde => mqtt_basic.ino} | 3 +- .../mqtt_publish_in_callback.ino | 51 +++++++++++++ 6 files changed, 109 insertions(+), 45 deletions(-) rename PubSubClient/examples/mqtt_auth/{mqtt_auth.pde => mqtt_auth.ino} (78%) rename PubSubClient/examples/mqtt_basic/{mqtt_basic.pde => mqtt_basic.ino} (89%) create mode 100644 PubSubClient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino diff --git a/PubSubClient/CHANGES.txt b/PubSubClient/CHANGES.txt index a53536e..a68abbf 100755 --- a/PubSubClient/CHANGES.txt +++ b/PubSubClient/CHANGES.txt @@ -1,3 +1,10 @@ +1.9 + * API change: All constructors now require an instance of Client + to be passed in. + * Fixed example to match 1.8 api changes - dpslwk + * Added username/password support - WilHall + * Added publish_P - publishes messages from PROGMEM - jobytaffey + 1.8 * KeepAlive interval is configurable in PubSubClient.h * Maximum packet size is configurable in PubSubClient.h diff --git a/PubSubClient/PubSubClient.cpp b/PubSubClient/PubSubClient.cpp index 16c16d0..9a2c976 100755 --- a/PubSubClient/PubSubClient.cpp +++ b/PubSubClient/PubSubClient.cpp @@ -5,19 +5,21 @@ */ #include "PubSubClient.h" -#include #include -PubSubClient::PubSubClient() : _client() { +PubSubClient::PubSubClient(Client& client) { + this->_client = &client; } -PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, void (*callback)(char*,uint8_t*,unsigned int)) : _client() { +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, void (*callback)(char*,uint8_t*,unsigned int), Client& client) { + this->_client = &client; this->callback = callback; this->ip = ip; this->port = port; } -PubSubClient::PubSubClient(char* domain, uint16_t port, void (*callback)(char*,uint8_t*,unsigned int)) : _client() { +PubSubClient::PubSubClient(char* domain, uint16_t port, void (*callback)(char*,uint8_t*,unsigned int), Client& client) { + this->_client = &client; this->callback = callback; this->domain = domain; this->port = port; @@ -41,9 +43,9 @@ boolean PubSubClient::connect(char *id, char *user, char *pass, char* willTopic, int result = 0; if (domain != NULL) { - result = _client.connect(this->domain, this->port); + result = _client->connect(this->domain, this->port); } else { - result = _client.connect(this->ip, this->port); + result = _client->connect(this->ip, this->port); } if (result) { @@ -90,10 +92,10 @@ boolean PubSubClient::connect(char *id, char *user, char *pass, char* willTopic, write(MQTTCONNECT,buffer,length); lastOutActivity = millis(); lastInActivity = millis(); - while (!_client.available()) { + while (!_client->available()) { unsigned long t= millis(); if (t-lastInActivity > MQTT_KEEPALIVE*1000) { - _client.stop(); + _client->stop(); return false; } } @@ -105,14 +107,14 @@ boolean PubSubClient::connect(char *id, char *user, char *pass, char* willTopic, return true; } } - _client.stop(); + _client->stop(); } return false; } uint8_t PubSubClient::readByte() { - while(!_client.available()) {} - return _client.read(); + while(!_client->available()) {} + return _client->read(); } uint16_t PubSubClient::readPacket() { @@ -146,17 +148,17 @@ boolean PubSubClient::loop() { unsigned long t = millis(); if ((t - lastInActivity > MQTT_KEEPALIVE*1000) || (t - lastOutActivity > MQTT_KEEPALIVE*1000)) { if (pingOutstanding) { - _client.stop(); + _client->stop(); return false; } else { - _client.write(MQTTPINGREQ); - _client.write((uint8_t)0); + _client->write(MQTTPINGREQ); + _client->write((uint8_t)0); lastOutActivity = t; lastInActivity = t; pingOutstanding = true; } } - if (_client.available()) { + if (_client->available()) { uint16_t len = readPacket(); if (len > 0) { lastInActivity = t; @@ -174,8 +176,8 @@ boolean PubSubClient::loop() { callback(topic,payload,len-4-tl); } } else if (type == MQTTPINGREQ) { - _client.write(MQTTPINGRESP); - _client.write((uint8_t)0); + _client->write(MQTTPINGRESP); + _client->write((uint8_t)0); } else if (type == MQTTPINGRESP) { pingOutstanding = false; } @@ -221,14 +223,16 @@ boolean PubSubClient::publish_P(char* topic, uint8_t* PROGMEM payload, unsigned uint8_t header; unsigned int len; - if (!connected()) + if (!connected()) { return false; + } tlen = strlen(topic); header = MQTTPUBLISH; - if (retained) + if (retained) { header |= 1; + } len = plength + 2 + tlen; do { @@ -241,17 +245,18 @@ boolean PubSubClient::publish_P(char* topic, uint8_t* PROGMEM payload, unsigned llen++; } while(len>0); - rc += _client.write(&header, 1); - rc += _client.write(lenBuf, llen); + rc += _client->write(&header, 1); + rc += _client->write(lenBuf, llen); lenBuf[0] = tlen >> 8; // MSB lenBuf[1] = tlen & 0xFF; // LSB - rc += _client.write(lenBuf, 2); - rc += _client.write((uint8_t *)topic, tlen); + rc += _client->write(lenBuf, 2); + rc += _client->write((uint8_t *)topic, tlen); - for (i=0;iwrite((char)pgm_read_byte_near(payload + i)); + } lastOutActivity = millis(); return rc == len + 1 + plength; @@ -274,9 +279,9 @@ boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) { llen++; } while(len>0); - rc = _client.write(header); - rc += _client.write(lenBuf,llen); - rc += _client.write(buf,length); + rc = _client->write(header); + rc += _client->write(lenBuf,llen); + rc += _client->write(buf,length); lastOutActivity = millis(); return (rc == 1+llen+length); } @@ -299,9 +304,9 @@ boolean PubSubClient::subscribe(char* topic) { } void PubSubClient::disconnect() { - _client.write(MQTTDISCONNECT); - _client.write((uint8_t)0); - _client.stop(); + _client->write(MQTTDISCONNECT); + _client->write((uint8_t)0); + _client->stop(); lastInActivity = millis(); lastOutActivity = millis(); } @@ -321,10 +326,8 @@ uint16_t PubSubClient::writeString(char* string, uint8_t* buf, uint16_t pos) { boolean PubSubClient::connected() { - int rc = (int)_client.connected(); - if (!rc) _client.stop(); + int rc = (int)_client->connected(); + if (!rc) _client->stop(); return rc; } - - diff --git a/PubSubClient/PubSubClient.h b/PubSubClient/PubSubClient.h index ea33074..93d631a 100755 --- a/PubSubClient/PubSubClient.h +++ b/PubSubClient/PubSubClient.h @@ -7,8 +7,8 @@ #ifndef PubSubClient_h #define PubSubClient_h -#include "Ethernet.h" -#include "EthernetClient.h" +#include +#include "Client.h" // MQTT_MAX_PACKET_SIZE : Maximum packet size #define MQTT_MAX_PACKET_SIZE 128 @@ -39,7 +39,7 @@ class PubSubClient { private: - EthernetClient _client; + Client* _client; uint8_t buffer[MQTT_MAX_PACKET_SIZE]; uint16_t nextMsgId; unsigned long lastOutActivity; @@ -54,9 +54,9 @@ private: char* domain; uint16_t port; public: - PubSubClient(); - PubSubClient(uint8_t *, uint16_t, void(*)(char*,uint8_t*,unsigned int)); - PubSubClient(char*, uint16_t, void(*)(char*,uint8_t*,unsigned int)); + PubSubClient(Client& client); + PubSubClient(uint8_t *, uint16_t, void(*)(char*,uint8_t*,unsigned int),Client& client); + PubSubClient(char*, uint16_t, void(*)(char*,uint8_t*,unsigned int),Client& client); boolean connect(char *); boolean connect(char *, char *, char *); boolean connect(char *, char *, uint8_t, uint8_t, char *); diff --git a/PubSubClient/examples/mqtt_auth/mqtt_auth.pde b/PubSubClient/examples/mqtt_auth/mqtt_auth.ino similarity index 78% rename from PubSubClient/examples/mqtt_auth/mqtt_auth.pde rename to PubSubClient/examples/mqtt_auth/mqtt_auth.ino index bfc73ef..c8a519a 100755 --- a/PubSubClient/examples/mqtt_auth/mqtt_auth.pde +++ b/PubSubClient/examples/mqtt_auth/mqtt_auth.ino @@ -1,7 +1,8 @@ /* - Basic MQTT example + Basic MQTT example with Authentication - - connects to an MQTT server + - connects to an MQTT server, providing username + and password - publishes "hello world" to the topic "outTopic" - subscribes to the topic "inTopic" */ @@ -19,7 +20,8 @@ void callback(char* topic, byte* payload, unsigned int length) { // handle message arrived } -PubSubClient client(server, 1883, callback); +EthernetClient ethClient; +PubSubClient client(server, 1883, callback, ethClient); void setup() { diff --git a/PubSubClient/examples/mqtt_basic/mqtt_basic.pde b/PubSubClient/examples/mqtt_basic/mqtt_basic.ino similarity index 89% rename from PubSubClient/examples/mqtt_basic/mqtt_basic.pde rename to PubSubClient/examples/mqtt_basic/mqtt_basic.ino index 359a267..72276cd 100755 --- a/PubSubClient/examples/mqtt_basic/mqtt_basic.pde +++ b/PubSubClient/examples/mqtt_basic/mqtt_basic.ino @@ -19,7 +19,8 @@ void callback(char* topic, byte* payload, unsigned int length) { // handle message arrived } -PubSubClient client(server, 1883, callback); +EthernetClient ethClient; +PubSubClient client(server, 1883, callback, ethClient); void setup() { diff --git a/PubSubClient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino b/PubSubClient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino new file mode 100644 index 0000000..278149a --- /dev/null +++ b/PubSubClient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino @@ -0,0 +1,51 @@ +/* + Publishing in the callback + + - connects to an MQTT server + - subscribes to the topic "inTopic" + - when a message is received, republishes it to "outTopic" + + This example shows how to publish messages within the + callback function. The callback function header needs to + be declared before the PubSubClient constructor and the + actual callback defined afterwards. + This ensures the client reference in the callback function + is valid. + +*/ + +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +byte server[] = { 172, 16, 0, 2 }; +byte ip[] = { 172, 16, 0, 100 }; + +// Callback function header +void callback(char* topic, byte* payload, unsigned int length); + +EthernetClient ethClient; +PubSubClient client(server, 1883, callback, ethClient); + +// Callback function +void callback(char* topic, byte* payload, unsigned int length) { + client.publish("outTopic", payload, length); +} + +void setup() +{ + + Ethernet.begin(mac, ip); + if (client.connect("arduinoClient")) { + client.publish("outTopic","hello world"); + client.subscribe("inTopic"); + } +} + +void loop() +{ + client.loop(); +} +