diff --git a/examples/ESP32-basic/ESP32-basic.ino b/examples/ESP32-basic/ESP32-basic.ino new file mode 100644 index 0000000..76ff5ba --- /dev/null +++ b/examples/ESP32-basic/ESP32-basic.ino @@ -0,0 +1,49 @@ +#include +#include + +ThingESP32 thing("username", "project_name", "credentials"); + +int LED = 2; + +void setup() +{ + Serial.begin(115200); + + pinMode(LED, OUTPUT); + + thing.SetWiFi("wifi_ssid", "wifi_password"); + + thing.initDevice(); + +} + + + +String HandleResponse(String query) +{ + + if (query == "led on") { + digitalWrite(LED, 1); + return "Done: LED Turned ON"; + } + + else if (query == "led off") { + digitalWrite(LED, 0); + return "Done: LED Turned OFF"; + } + + else if (query == "led status") + return digitalRead(LED) ? "LED is ON" : "LED is OFF"; + + + else return "Your query was invalid.."; + +} + + + + +void loop() +{ + thing.Handle(); +} \ No newline at end of file diff --git a/examples/ESP32-send-message/ESP32-send-message.ino b/examples/ESP32-send-message/ESP32-send-message.ino new file mode 100644 index 0000000..f4abcbe --- /dev/null +++ b/examples/ESP32-send-message/ESP32-send-message.ino @@ -0,0 +1,55 @@ +#include +#include + +ThingESP32 thing("username", "project_name", "credentials"); + +int LED = 2; + +unsigned long previousMillis = 0; +const long INTERVAL = 6000; + +void setup() +{ + Serial.begin(115200); + + pinMode(LED, OUTPUT); + + thing.SetWiFi("wifi_ssid", "wifi_password"); + + thing.initDevice(); +} + +String HandleResponse(String query) +{ + + if (query == "led on") + { + digitalWrite(LED, 1); + return "Done: LED Turned ON"; + } + + else if (query == "led off") + { + digitalWrite(LED, 0); + return "Done: LED Turned OFF"; + } + + else if (query == "led status") + return digitalRead(LED) ? "LED is ON" : "LED is OFF"; + + else + return "Your query was invalid.."; +} + +void loop() +{ + + // if (millis() - previousMillis >= INTERVAL) + // { + // previousMillis = millis(); + // String msg = digitalRead(LED) ? "LED is ON" : "LED is OFF"; + // thing.sendMsg("PHONE_NUMBER", msg); + // } + + thing.Handle(); +} \ No newline at end of file diff --git a/examples/ThingESP-example/ThingESP-example.ino b/examples/ESP8266-basic/ESP8266-basic.ino similarity index 68% rename from examples/ThingESP-example/ThingESP-example.ino rename to examples/ESP8266-basic/ESP8266-basic.ino index 2535d32..dfbac4f 100644 --- a/examples/ThingESP-example/ThingESP-example.ino +++ b/examples/ESP8266-basic/ESP8266-basic.ino @@ -1,7 +1,7 @@ #include -#include +#include -WH_ESP8266 DeviceClient; +ThingESP8266 thing("username", "project_name", "credentials"); int LED = LED_BUILTIN; @@ -10,13 +10,10 @@ void setup() Serial.begin(115200); pinMode(LED, OUTPUT); - digitalWrite(LED, 1); - DeviceClient.SetDevice("username", "project_name", "credentials"); + thing.SetWiFi("wifi_ssid", "wifi_password"); - DeviceClient.SetWiFi("ssid", "pass"); - - DeviceClient.initDevice(); + thing.initDevice(); } @@ -48,7 +45,5 @@ String HandleResponse(String query) void loop() { - - DeviceClient.Handle(); - + thing.Handle(); } \ No newline at end of file diff --git a/examples/ESP8266-send-message/ESP8266-send-message.ino b/examples/ESP8266-send-message/ESP8266-send-message.ino new file mode 100644 index 0000000..f5809a5 --- /dev/null +++ b/examples/ESP8266-send-message/ESP8266-send-message.ino @@ -0,0 +1,54 @@ +#include +#include + +ThingESP8266 thing("username", "project_name", "credentials"); + +int LED = LED_BUILTIN; + +unsigned long previousMillis = 0; +const long INTERVAL = 6000; + +void setup() +{ + Serial.begin(115200); + + pinMode(LED, OUTPUT); + + thing.SetWiFi("wifi_ssid", "wifi_password"); + + thing.initDevice(); +} + +String HandleResponse(String query) +{ + + if (query == "led on") + { + digitalWrite(LED, 0); + return "Done: LED Turned ON"; + } + + else if (query == "led off") + { + digitalWrite(LED, 1); + return "Done: LED Turned OFF"; + } + + else if (query == "led status") + return digitalRead(LED) ? "LED is OFF" : "LED is ON"; + + else + return "Your query was invalid.."; +} + +void loop() +{ + // if (millis() - previousMillis >= INTERVAL) + // { + // previousMillis = millis(); + // String msg = digitalRead(LED) ? "LED is OFF" : "LED is ON"; + // thing.sendMsg("PHONE_NUMBER", msg); + // } + + thing.Handle(); +} \ No newline at end of file diff --git a/keywords.txt b/keywords.txt index 3a806e8..387729c 100644 --- a/keywords.txt +++ b/keywords.txt @@ -3,23 +3,23 @@ ####################################### ####################################### -# Datatypes (KEYWORD1) Classes +# Datatypes (KEYWORD1) ####################################### -WH_ESP8266 KEYWORD1 +ThingESP32 KEYWORD1 +ThingESP8266 KEYWORD1 ####################################### -# Datatypes (KEYWORD2) Methods +# Methods and Functions (KEYWORD2) ####################################### -DeviceClient KEYWORD2 +SetWiFi KEYWORD2 +initDevice KEYWORD2 +setCallback KEYWORD2 +Handle KEYWORD2 +sendMsg KEYWORD2 +###################################### +# Constants (LITERAL1) ####################################### -# Datatypes (KEYWORD3) Setup & Loop -####################################### - -SetDevice KEYWORD3 -SetWiFi KEYWORD3 -initDevice KEYWORD3 -Handle KEYWORD3 -HandleResponse KEYWORD3 \ No newline at end of file +HandleResponse LITERAL1 diff --git a/library.properties b/library.properties index eccd682..30f9e4c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ThingESP -version=1.0.0 +version=1.3.0 author=SiddheshNan maintainer=SiddheshNan sentence=Arduino library for the ThingsESP Platform. diff --git a/src/PubSubClient/PubSubClient.cpp b/src/PubSubClient/PubSubClient.cpp index 9658c4a..2b48d2b 100644 --- a/src/PubSubClient/PubSubClient.cpp +++ b/src/PubSubClient/PubSubClient.cpp @@ -1,4 +1,5 @@ /* + PubSubClient.cpp - A simple client for MQTT. Nick O'Leary http://knolleary.net @@ -12,12 +13,20 @@ PubSubClient::PubSubClient() { this->_client = NULL; this->stream = NULL; setCallback(NULL); + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(Client& client) { this->_state = MQTT_DISCONNECTED; setClient(client); this->stream = NULL; + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) { @@ -25,12 +34,20 @@ PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) { setServer(addr, port); setClient(client); this->stream = NULL; + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream) { this->_state = MQTT_DISCONNECTED; setServer(addr,port); setClient(client); setStream(stream); + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { this->_state = MQTT_DISCONNECTED; @@ -38,6 +55,10 @@ PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATUR setCallback(callback); setClient(client); this->stream = NULL; + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { this->_state = MQTT_DISCONNECTED; @@ -45,6 +66,10 @@ PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATUR setCallback(callback); setClient(client); setStream(stream); + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) { @@ -52,12 +77,20 @@ PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) { setServer(ip, port); setClient(client); this->stream = NULL; + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client, Stream& stream) { this->_state = MQTT_DISCONNECTED; setServer(ip,port); setClient(client); setStream(stream); + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { this->_state = MQTT_DISCONNECTED; @@ -65,6 +98,10 @@ PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, setCallback(callback); setClient(client); this->stream = NULL; + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { this->_state = MQTT_DISCONNECTED; @@ -72,6 +109,10 @@ PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, setCallback(callback); setClient(client); setStream(stream); + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) { @@ -79,12 +120,20 @@ PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) { setServer(domain,port); setClient(client); this->stream = NULL; + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client, Stream& stream) { this->_state = MQTT_DISCONNECTED; setServer(domain,port); setClient(client); setStream(stream); + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { this->_state = MQTT_DISCONNECTED; @@ -92,6 +141,10 @@ PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGN setCallback(callback); setClient(client); this->stream = NULL; + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { this->_state = MQTT_DISCONNECTED; @@ -99,33 +152,51 @@ PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGN setCallback(callback); setClient(client); setStream(stream); + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); +} + +PubSubClient::~PubSubClient() { + free(this->buffer); } boolean PubSubClient::connect(const char *id) { - return connect(id,NULL,NULL,0,0,0,0); + return connect(id,NULL,NULL,0,0,0,0,1); } boolean PubSubClient::connect(const char *id, const char *user, const char *pass) { - return connect(id,user,pass,0,0,0,0); + return connect(id,user,pass,0,0,0,0,1); } boolean PubSubClient::connect(const char *id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) { - return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage); + return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage,1); } boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) { + return connect(id,user,pass,willTopic,willQos,willRetain,willMessage,1); +} + +boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage, boolean cleanSession) { if (!connected()) { int result = 0; - if (domain != NULL) { - result = _client->connect(this->domain, this->port); + + if(_client->connected()) { + result = 1; } else { - result = _client->connect(this->ip, this->port); + if (domain != NULL) { + result = _client->connect(this->domain, this->port); + } else { + result = _client->connect(this->ip, this->port); + } } + if (result == 1) { nextMsgId = 1; // Leave room in the buffer for header and variable length field - uint16_t length = 5; + uint16_t length = MQTT_MAX_HEADER_SIZE; unsigned int j; #if MQTT_VERSION == MQTT_VERSION_3_1 @@ -136,14 +207,17 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass #define MQTT_HEADER_VERSION_LENGTH 7 #endif for (j = 0;jbuffer[length++] = d[j]; } uint8_t v; if (willTopic) { - v = 0x06|(willQos<<3)|(willRetain<<5); + v = 0x04|(willQos<<3)|(willRetain<<5); } else { - v = 0x02; + v = 0x00; + } + if (cleanSession) { + v = v|0x02; } if(user != NULL) { @@ -153,38 +227,43 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass v = v|(0x80>>1); } } + this->buffer[length++] = v; - buffer[length++] = v; + this->buffer[length++] = ((this->keepAlive) >> 8); + this->buffer[length++] = ((this->keepAlive) & 0xFF); - buffer[length++] = ((MQTT_KEEPALIVE) >> 8); - buffer[length++] = ((MQTT_KEEPALIVE) & 0xFF); - length = writeString(id,buffer,length); + CHECK_STRING_LENGTH(length,id) + length = writeString(id,this->buffer,length); if (willTopic) { - length = writeString(willTopic,buffer,length); - length = writeString(willMessage,buffer,length); + CHECK_STRING_LENGTH(length,willTopic) + length = writeString(willTopic,this->buffer,length); + CHECK_STRING_LENGTH(length,willMessage) + length = writeString(willMessage,this->buffer,length); } if(user != NULL) { - length = writeString(user,buffer,length); + CHECK_STRING_LENGTH(length,user) + length = writeString(user,this->buffer,length); if(pass != NULL) { - length = writeString(pass,buffer,length); + CHECK_STRING_LENGTH(length,pass) + length = writeString(pass,this->buffer,length); } } - write(MQTTCONNECT,buffer,length-5); + write(MQTTCONNECT,this->buffer,length-MQTT_MAX_HEADER_SIZE); lastInActivity = lastOutActivity = millis(); while (!_client->available()) { unsigned long t = millis(); - if (t-lastInActivity >= ((int32_t) MQTT_SOCKET_TIMEOUT*1000UL)) { + if (t-lastInActivity >= ((int32_t) this->socketTimeout*1000UL)) { _state = MQTT_CONNECTION_TIMEOUT; _client->stop(); return false; } } uint8_t llen; - uint16_t len = readPacket(&llen); + uint32_t len = readPacket(&llen); if (len == 4) { if (buffer[3] == 0) { @@ -209,8 +288,9 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass boolean PubSubClient::readByte(uint8_t * result) { uint32_t previousMillis = millis(); while(!_client->available()) { + yield(); uint32_t currentMillis = millis(); - if(currentMillis - previousMillis >= ((int32_t) MQTT_SOCKET_TIMEOUT * 1000)){ + if(currentMillis - previousMillis >= ((int32_t) this->socketTimeout * 1000)){ return false; } } @@ -229,68 +309,76 @@ boolean PubSubClient::readByte(uint8_t * result, uint16_t * index){ return false; } -uint16_t PubSubClient::readPacket(uint8_t* lengthLength) { +uint32_t PubSubClient::readPacket(uint8_t* lengthLength) { uint16_t len = 0; - if(!readByte(buffer, &len)) return 0; - bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH; + if(!readByte(this->buffer, &len)) return 0; + bool isPublish = (this->buffer[0]&0xF0) == MQTTPUBLISH; uint32_t multiplier = 1; - uint16_t length = 0; + uint32_t length = 0; uint8_t digit = 0; uint16_t skip = 0; - uint8_t start = 0; + uint32_t start = 0; do { + if (len == 5) { + // Invalid remaining length encoding - kill the connection + _state = MQTT_DISCONNECTED; + _client->stop(); + return 0; + } if(!readByte(&digit)) return 0; - buffer[len++] = digit; + this->buffer[len++] = digit; length += (digit & 127) * multiplier; - multiplier *= 128; + multiplier <<=7; //multiplier *= 128 } while ((digit & 128) != 0); *lengthLength = len-1; if (isPublish) { // Read in topic length to calculate bytes to skip over for Stream writing - if(!readByte(buffer, &len)) return 0; - if(!readByte(buffer, &len)) return 0; - skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2]; + if(!readByte(this->buffer, &len)) return 0; + if(!readByte(this->buffer, &len)) return 0; + skip = (this->buffer[*lengthLength+1]<<8)+this->buffer[*lengthLength+2]; start = 2; - if (buffer[0]&MQTTQOS1) { + if (this->buffer[0]&MQTTQOS1) { // skip message id skip += 2; } } + uint32_t idx = len; - for (uint16_t i = start;istream) { - if (isPublish && len-*lengthLength-2>skip) { + if (isPublish && idx-*lengthLength-2>skip) { this->stream->write(digit); } } - if (len < MQTT_MAX_PACKET_SIZE) { - buffer[len] = digit; + + if (len < this->bufferSize) { + this->buffer[len] = digit; + len++; } - len++; + idx++; } - if (!this->stream && len > MQTT_MAX_PACKET_SIZE) { + if (!this->stream && idx > this->bufferSize) { len = 0; // This will cause the packet to be ignored. } - return len; } boolean PubSubClient::loop() { if (connected()) { unsigned long t = millis(); - if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) { + if ((t - lastInActivity > this->keepAlive*1000UL) || (t - lastOutActivity > this->keepAlive*1000UL)) { if (pingOutstanding) { this->_state = MQTT_CONNECTION_TIMEOUT; _client->stop(); return false; } else { - buffer[0] = MQTTPINGREQ; - buffer[1] = 0; - _client->write(buffer,2); + this->buffer[0] = MQTTPINGREQ; + this->buffer[1] = 0; + _client->write(this->buffer,2); lastOutActivity = t; lastInActivity = t; pingOutstanding = true; @@ -303,40 +391,41 @@ boolean PubSubClient::loop() { uint8_t *payload; if (len > 0) { lastInActivity = t; - uint8_t type = buffer[0]&0xF0; + uint8_t type = this->buffer[0]&0xF0; if (type == MQTTPUBLISH) { if (callback) { - uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; - char topic[tl+1]; - for (uint16_t i=0;ibuffer[llen+1]<<8)+this->buffer[llen+2]; /* topic length in bytes */ + memmove(this->buffer+llen+2,this->buffer+llen+3,tl); /* move topic inside buffer 1 byte to front */ + this->buffer[llen+2+tl] = 0; /* end the topic as a 'C' string with \x00 */ + char *topic = (char*) this->buffer+llen+2; // msgId only present for QOS>0 - if ((buffer[0]&0x06) == MQTTQOS1) { - msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1]; - payload = buffer+llen+3+tl+2; + if ((this->buffer[0]&0x06) == MQTTQOS1) { + msgId = (this->buffer[llen+3+tl]<<8)+this->buffer[llen+3+tl+1]; + payload = this->buffer+llen+3+tl+2; callback(topic,payload,len-llen-3-tl-2); - buffer[0] = MQTTPUBACK; - buffer[1] = 2; - buffer[2] = (msgId >> 8); - buffer[3] = (msgId & 0xFF); - _client->write(buffer,4); + this->buffer[0] = MQTTPUBACK; + this->buffer[1] = 2; + this->buffer[2] = (msgId >> 8); + this->buffer[3] = (msgId & 0xFF); + _client->write(this->buffer,4); lastOutActivity = t; } else { - payload = buffer+llen+3+tl; + payload = this->buffer+llen+3+tl; callback(topic,payload,len-llen-3-tl); } } } else if (type == MQTTPINGREQ) { - buffer[0] = MQTTPINGRESP; - buffer[1] = 0; - _client->write(buffer,2); + this->buffer[0] = MQTTPINGRESP; + this->buffer[1] = 0; + _client->write(this->buffer,2); } else if (type == MQTTPINGRESP) { pingOutstanding = false; } + } else if (!connected()) { + // readPacket has closed the connection + return false; } } return true; @@ -345,11 +434,11 @@ boolean PubSubClient::loop() { } boolean PubSubClient::publish(const char* topic, const char* payload) { - return publish(topic,(const uint8_t*)payload,strlen(payload),false); + return publish(topic,(const uint8_t*)payload, payload ? strnlen(payload, this->bufferSize) : 0,false); } boolean PubSubClient::publish(const char* topic, const char* payload, boolean retained) { - return publish(topic,(const uint8_t*)payload,strlen(payload),retained); + return publish(topic,(const uint8_t*)payload, payload ? strnlen(payload, this->bufferSize) : 0,retained); } boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength) { @@ -358,26 +447,34 @@ boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigne boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) { if (connected()) { - if (MQTT_MAX_PACKET_SIZE < 5 + 2+strlen(topic) + plength) { + if (this->bufferSize < MQTT_MAX_HEADER_SIZE + 2+strnlen(topic, this->bufferSize) + plength) { // Too long return false; } // Leave room in the buffer for header and variable length field - uint16_t length = 5; - length = writeString(topic,buffer,length); + uint16_t length = MQTT_MAX_HEADER_SIZE; + length = writeString(topic,this->buffer,length); + + // Add payload uint16_t i; for (i=0;ibuffer[length++] = payload[i]; } + + // Write the header uint8_t header = MQTTPUBLISH; if (retained) { header |= 1; } - return write(header,buffer,length-5); + return write(header,this->buffer,length-MQTT_MAX_HEADER_SIZE); } return false; } +boolean PubSubClient::publish_P(const char* topic, const char* payload, boolean retained) { + return publish_P(topic, (const uint8_t*)payload, payload ? strnlen(payload, this->bufferSize) : 0, retained); +} + boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) { uint8_t llen = 0; uint8_t digit; @@ -387,32 +484,33 @@ boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsig unsigned int i; uint8_t header; unsigned int len; + int expectedLength; if (!connected()) { return false; } - tlen = strlen(topic); + tlen = strnlen(topic, this->bufferSize); header = MQTTPUBLISH; if (retained) { header |= 1; } - buffer[pos++] = header; + this->buffer[pos++] = header; len = plength + 2 + tlen; do { - digit = len % 128; - len = len / 128; + digit = len & 127; //digit = len %128 + len >>= 7; //len = len / 128 if (len > 0) { digit |= 0x80; } - buffer[pos++] = digit; + this->buffer[pos++] = digit; llen++; } while(len>0); - pos = writeString(topic,buffer,pos); + pos = writeString(topic,this->buffer,pos); - rc += _client->write(buffer,pos); + rc += _client->write(this->buffer,pos); for (i=0;iwrite((char)pgm_read_byte_near(payload + i)); @@ -420,19 +518,52 @@ boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsig lastOutActivity = millis(); - return rc == tlen + 4 + plength; + expectedLength = 1 + llen + 2 + tlen + plength; + + return (rc == expectedLength); } -boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) { +boolean PubSubClient::beginPublish(const char* topic, unsigned int plength, boolean retained) { + if (connected()) { + // Send the header and variable length field + uint16_t length = MQTT_MAX_HEADER_SIZE; + length = writeString(topic,this->buffer,length); + uint8_t header = MQTTPUBLISH; + if (retained) { + header |= 1; + } + size_t hlen = buildHeader(header, this->buffer, plength+length-MQTT_MAX_HEADER_SIZE); + uint16_t rc = _client->write(this->buffer+(MQTT_MAX_HEADER_SIZE-hlen),length-(MQTT_MAX_HEADER_SIZE-hlen)); + lastOutActivity = millis(); + return (rc == (length-(MQTT_MAX_HEADER_SIZE-hlen))); + } + return false; +} + +int PubSubClient::endPublish() { + return 1; +} + +size_t PubSubClient::write(uint8_t data) { + lastOutActivity = millis(); + return _client->write(data); +} + +size_t PubSubClient::write(const uint8_t *buffer, size_t size) { + lastOutActivity = millis(); + return _client->write(buffer,size); +} + +size_t PubSubClient::buildHeader(uint8_t header, uint8_t* buf, uint16_t length) { uint8_t lenBuf[4]; uint8_t llen = 0; uint8_t digit; uint8_t pos = 0; - uint16_t rc; uint16_t len = length; do { - digit = len % 128; - len = len / 128; + + digit = len & 127; //digit = len %128 + len >>= 7; //len = len / 128 if (len > 0) { digit |= 0x80; } @@ -442,12 +573,18 @@ boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) { buf[4-llen] = header; for (int i=0;i 0) && result) { @@ -459,9 +596,9 @@ boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) { } return result; #else - rc = _client->write(buf+(4-llen),length+1+llen); + rc = _client->write(buf+(MQTT_MAX_HEADER_SIZE-hlen),length+hlen); lastOutActivity = millis(); - return (rc == 1+llen+length); + return (rc == hlen+length); #endif } @@ -470,53 +607,62 @@ boolean PubSubClient::subscribe(const char* topic) { } boolean PubSubClient::subscribe(const char* topic, uint8_t qos) { - if (qos < 0 || qos > 1) { + size_t topicLength = strnlen(topic, this->bufferSize); + if (topic == 0) { return false; } - if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { + if (qos > 1) { + return false; + } + if (this->bufferSize < 9 + topicLength) { // Too long return false; } if (connected()) { // Leave room in the buffer for header and variable length field - uint16_t length = 5; + uint16_t length = MQTT_MAX_HEADER_SIZE; nextMsgId++; if (nextMsgId == 0) { nextMsgId = 1; } - buffer[length++] = (nextMsgId >> 8); - buffer[length++] = (nextMsgId & 0xFF); - length = writeString((char*)topic, buffer,length); - buffer[length++] = qos; - return write(MQTTSUBSCRIBE|MQTTQOS1,buffer,length-5); + this->buffer[length++] = (nextMsgId >> 8); + this->buffer[length++] = (nextMsgId & 0xFF); + length = writeString((char*)topic, this->buffer,length); + this->buffer[length++] = qos; + return write(MQTTSUBSCRIBE|MQTTQOS1,this->buffer,length-MQTT_MAX_HEADER_SIZE); } return false; } boolean PubSubClient::unsubscribe(const char* topic) { - if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { + size_t topicLength = strnlen(topic, this->bufferSize); + if (topic == 0) { + return false; + } + if (this->bufferSize < 9 + topicLength) { // Too long return false; } if (connected()) { - uint16_t length = 5; + uint16_t length = MQTT_MAX_HEADER_SIZE; nextMsgId++; if (nextMsgId == 0) { nextMsgId = 1; } - buffer[length++] = (nextMsgId >> 8); - buffer[length++] = (nextMsgId & 0xFF); - length = writeString(topic, buffer,length); - return write(MQTTUNSUBSCRIBE|MQTTQOS1,buffer,length-5); + this->buffer[length++] = (nextMsgId >> 8); + this->buffer[length++] = (nextMsgId & 0xFF); + length = writeString(topic, this->buffer,length); + return write(MQTTUNSUBSCRIBE|MQTTQOS1,this->buffer,length-MQTT_MAX_HEADER_SIZE); } return false; } void PubSubClient::disconnect() { - buffer[0] = MQTTDISCONNECT; - buffer[1] = 0; - _client->write(buffer,2); + this->buffer[0] = MQTTDISCONNECT; + this->buffer[1] = 0; + _client->write(this->buffer,2); _state = MQTT_DISCONNECTED; + _client->flush(); _client->stop(); lastInActivity = lastOutActivity = millis(); } @@ -547,6 +693,8 @@ boolean PubSubClient::connected() { _client->flush(); _client->stop(); } + } else { + return this->_state == MQTT_CONNECTED; } } return rc; @@ -588,3 +736,34 @@ PubSubClient& PubSubClient::setStream(Stream& stream){ int PubSubClient::state() { return this->_state; } + +boolean PubSubClient::setBufferSize(uint16_t size) { + if (size == 0) { + // Cannot set it back to 0 + return false; + } + if (this->bufferSize == 0) { + this->buffer = (uint8_t*)malloc(size); + } else { + uint8_t* newBuffer = (uint8_t*)realloc(this->buffer, size); + if (newBuffer != NULL) { + this->buffer = newBuffer; + } else { + return false; + } + } + this->bufferSize = size; + return (this->buffer != NULL); +} + +uint16_t PubSubClient::getBufferSize() { + return this->bufferSize; +} +PubSubClient& PubSubClient::setKeepAlive(uint16_t keepAlive) { + this->keepAlive = keepAlive; + return *this; +} +PubSubClient& PubSubClient::setSocketTimeout(uint16_t timeout) { + this->socketTimeout = timeout; + return *this; +} diff --git a/src/PubSubClient/PubSubClient.h b/src/PubSubClient/PubSubClient.h index 2d1b1f6..0a950ac 100644 --- a/src/PubSubClient/PubSubClient.h +++ b/src/PubSubClient/PubSubClient.h @@ -21,17 +21,17 @@ #define MQTT_VERSION MQTT_VERSION_3_1_1 #endif -// MQTT_MAX_PACKET_SIZE : Maximum packet size +// MQTT_MAX_PACKET_SIZE : Maximum packet size. Override with setBufferSize(). #ifndef MQTT_MAX_PACKET_SIZE -#define MQTT_MAX_PACKET_SIZE 512 +#define MQTT_MAX_PACKET_SIZE 1024 #endif -// MQTT_KEEPALIVE : keepAlive interval in Seconds +// MQTT_KEEPALIVE : keepAlive interval in Seconds. Override with setKeepAlive() #ifndef MQTT_KEEPALIVE #define MQTT_KEEPALIVE 15 #endif -// MQTT_SOCKET_TIMEOUT: socket timeout interval in Seconds +// MQTT_SOCKET_TIMEOUT: socket timeout interval in Seconds. Override with setSocketTimeout() #ifndef MQTT_SOCKET_TIMEOUT #define MQTT_SOCKET_TIMEOUT 15 #endif @@ -73,27 +73,40 @@ #define MQTTQOS1 (1 << 1) #define MQTTQOS2 (2 << 1) -#ifdef ESP8266 +// Maximum size of fixed header and variable length size header +#define MQTT_MAX_HEADER_SIZE 5 + +#if defined(ESP8266) || defined(ESP32) #include #define MQTT_CALLBACK_SIGNATURE std::function callback #else #define MQTT_CALLBACK_SIGNATURE void (*callback)(char*, uint8_t*, unsigned int) #endif -class PubSubClient { +#define CHECK_STRING_LENGTH(l,s) if (l+2+strnlen(s, this->bufferSize) > this->bufferSize) {_client->stop();return false;} + +class PubSubClient : public Print { private: Client* _client; - uint8_t buffer[MQTT_MAX_PACKET_SIZE]; + uint8_t* buffer; + uint16_t bufferSize; + uint16_t keepAlive; + uint16_t socketTimeout; uint16_t nextMsgId; unsigned long lastOutActivity; unsigned long lastInActivity; bool pingOutstanding; MQTT_CALLBACK_SIGNATURE; - uint16_t readPacket(uint8_t*); + uint32_t readPacket(uint8_t*); boolean readByte(uint8_t * result); boolean readByte(uint8_t * result, uint16_t * index); boolean write(uint8_t header, uint8_t* buf, uint16_t length); uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos); + // Build up the header ready to send + // Returns the size of the header + // Note: the header is built at the end of the first MQTT_MAX_HEADER_SIZE bytes, so will start + // (MQTT_MAX_HEADER_SIZE - ) bytes into the buffer + size_t buildHeader(uint8_t header, uint8_t* buf, uint16_t length); IPAddress ip; const char* domain; uint16_t port; @@ -115,29 +128,56 @@ class PubSubClient { PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); + ~PubSubClient(); + PubSubClient& setServer(IPAddress ip, uint16_t port); PubSubClient& setServer(uint8_t * ip, uint16_t port); PubSubClient& setServer(const char * domain, uint16_t port); PubSubClient& setCallback(MQTT_CALLBACK_SIGNATURE); PubSubClient& setClient(Client& client); PubSubClient& setStream(Stream& stream); + PubSubClient& setKeepAlive(uint16_t keepAlive); + PubSubClient& setSocketTimeout(uint16_t timeout); + + boolean setBufferSize(uint16_t size); + uint16_t getBufferSize(); boolean connect(const char* id); boolean connect(const char* id, const char* user, const char* pass); boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); + boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage, boolean cleanSession); void disconnect(); boolean publish(const char* topic, const char* payload); boolean publish(const char* topic, const char* payload, boolean retained); boolean publish(const char* topic, const uint8_t * payload, unsigned int plength); boolean publish(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained); + boolean publish_P(const char* topic, const char* payload, boolean retained); boolean publish_P(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained); + // Start to publish a message. + // This API: + // beginPublish(...) + // one or more calls to write(...) + // endPublish() + // Allows for arbitrarily large payloads to be sent without them having to be copied into + // a new buffer and held in memory at one time + // Returns 1 if the message was started successfully, 0 if there was an error + boolean beginPublish(const char* topic, unsigned int plength, boolean retained); + // Finish off this publish message (started with beginPublish) + // Returns 1 if the packet was sent successfully, 0 if there was an error + int endPublish(); + // Write a single byte of payload (only to be used with beginPublish/endPublish) + virtual size_t write(uint8_t); + // Write size bytes from buffer into the payload (only to be used with beginPublish/endPublish) + // Returns the number of bytes written + virtual size_t write(const uint8_t *buffer, size_t size); boolean subscribe(const char* topic); boolean subscribe(const char* topic, uint8_t qos); boolean unsubscribe(const char* topic); boolean loop(); boolean connected(); int state(); + }; diff --git a/src/ThingESP.h b/src/ThingESP.h new file mode 100644 index 0000000..b274bb9 --- /dev/null +++ b/src/ThingESP.h @@ -0,0 +1,19 @@ +#define MQTT_MAX_PACKET_SIZE 1024 +#include "./ThingESPClient.cpp" + +#if defined(ESP8266) + class ThingESP8266 : public thing_esp::ThingESPClient { + public: + ThingESP8266(const char* _username, const char* _projectName, const char* _credentials) : ThingESPClient(_username, _projectName, _credentials) + {} + }; +#elif defined(ESP32) + class ThingESP32 : public thing_esp::ThingESPClient { + public: + ThingESP32(const char* _username, const char* _projectName, const char* _credentials) : ThingESPClient(_username, _projectName, _credentials) + {} + }; +#endif + + + diff --git a/src/ThingESPClient.cpp b/src/ThingESPClient.cpp new file mode 100644 index 0000000..ee0ec45 --- /dev/null +++ b/src/ThingESPClient.cpp @@ -0,0 +1,129 @@ +#pragma once + +#if defined(ESP8266) + #include +#elif defined(ESP32) + #include +#endif + +#ifndef _DISABLE_TLS_ + #include +#endif + +#include +#include + +#include "PubSubClient/PubSubClient.h" +#include "ArduinoJson.h" + +#include "thingesp/Logger.cpp" +#include "thingesp/Device.cpp" +#include "thingesp/RateLimiter.cpp" +#include "thingesp/Message.cpp" + +namespace thing_esp { + class ThingESPClient : public DeviceData, public Message { + public: + ThingESPClient(const char *_username, const char *_projectName, const char *_credentials) : client(espClient) { + + #if !defined(_DISABLE_TLS_) && !defined(ESP32) + espClient.setInsecure(); + delay(2); + #endif + + username = _username; + projectName = _projectName; + credentials = _credentials; + + this->genMetaData(); + }; + + void initDevice() { + if (wifi_configured) { + + LOG_VALUE("WiFi", "Connecting to: ", ssid) + + WiFi.begin(ssid, ssid_password); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + } + + LOG("WiFi", "Connected successfully"); + LOG_VALUE("WiFi", "IP address: ", WiFi.localIP()); + + + } + + randomSeed(micros()); + + client.setServer(MQTT_SERVER, MQTT_PORT); + client.setCallback([this](char *topic, byte *payload, unsigned int length) { + callback(topic, payload, length); + }); + } + + void Handle() { + if (!client.connected()) { + while (!client.connected()) { + LOG("SOCKET", "Attempting connection to ThingESP") + + if (client.connect(outName.c_str(), outName.c_str(), credentials)) { + LOG("SOCKET", "Connected to ThingESP successfully") + client.subscribe(c_topic); + publishMSG(get_rate_limits_msg()); + } else { + LOG_VALUE("SOCKET", "Error connecting to ThingESP! Error code: ", client.state()); + if (client.state() == 5) { + LOG("SOCKET", "Please check your username, project name or credentials! "); + } + LOG("SOCKET", "Trying again in 10 seconds.."); + delay(10000); + } + } + } + client.loop(); + } + + + protected: + + /* + * the callback function + */ + String (*callbackFunction)(String) override; + + + /* + * the WiFi Client + */ + #if !defined(_DISABLE_TLS_) && !defined(ESP32) + WiFiClientSecure espClient; + #else + WiFiClient espClient; + #endif + + + /* + * PubSubClient for MQTT + */ + PubSubClient client; + + + void publishMSG(const char *_msg) override { + client.publish(c_topic, _msg); + } + + void callback(char *topic, byte *payload, unsigned int length) { + String msg; + + for (int i = 0; i < length; i++) + msg.concat((char) payload[i]); + + this->onMessage(msg); + } + + + }; + +} \ No newline at end of file diff --git a/src/thingesp/Device.cpp b/src/thingesp/Device.cpp new file mode 100644 index 0000000..90e9501 --- /dev/null +++ b/src/thingesp/Device.cpp @@ -0,0 +1,75 @@ +#pragma once + +#include +#include +#include + +#include "../PubSubClient/PubSubClient.h" + + +namespace thing_esp { + class DeviceData { + public: + + /* + * Set WiFi SSID and Password + */ + void SetWiFi(const char *_ssid, const char *_ssid_password) { + wifi_configured = true; + ssid = _ssid; + ssid_password = _ssid_password; + } + + + /* + * Generate DeviceName and Topic Name(s) + */ + void genMetaData() { + this->outName = projectName + "@" + username; + this->topic = projectName + "/" + username; + this->c_topic = topic.c_str(); + } + + String projectName; + const char *username; + const char *credentials; + + String outName; + String topic; + const char* c_topic; + + const char *ssid; + const char *ssid_password; + + bool wifi_configured = false; + + + /* + * Check if TLS Disabled or not + */ + #if !defined(_MQTT_PORT_) + + #if !defined(_DISABLE_TLS_) && !defined(ESP32) + unsigned int MQTT_PORT = 1899; // tls port + #else + unsigned int MQTT_PORT = 1893; // non-tls port + #endif + + #else + unsigned int MQTT_PORT = _MQTT_PORT_; + #endif + + + + /* + * ThingESP server DNS + */ + #ifndef _THINGESP_SERVER_ + const char *MQTT_SERVER = "thingesp.siddhesh.me"; + #else + const char *MQTT_SERVER = _THINGESP_SERVER_; + #endif + + + }; +} \ No newline at end of file diff --git a/src/thingesp/Logger.cpp b/src/thingesp/Logger.cpp new file mode 100644 index 0000000..4bb3449 --- /dev/null +++ b/src/thingesp/Logger.cpp @@ -0,0 +1,11 @@ +#pragma once + +#ifndef _LOG_DISABLE_ + #define LOG(type, text) Serial.print("["); Serial.print(F(type)); Serial.print("] "); Serial.println(F(text)); + #define LOG_VALUE(type, text, value) Serial.print("["); Serial.print(F(type)); Serial.print("] "); Serial.print(F(text)); Serial.println(value); + #define LOG_WITHOUT_F(type, text) Serial.print("["); Serial.print(type); Serial.print("] "); Serial.println(text); +#else + #define LOG(type, text) void(); + #define LOG_VALUE(type, text, value) void(); + #define LOG_WITHOUT_F(type, text) void(); +#endif \ No newline at end of file diff --git a/src/thingesp/Message.cpp b/src/thingesp/Message.cpp new file mode 100644 index 0000000..88a5a96 --- /dev/null +++ b/src/thingesp/Message.cpp @@ -0,0 +1,111 @@ +#pragma once + +#include "../ArduinoJson.h" +#include "./RateLimiter.cpp" +#include "./Logger.cpp" + +#if defined(__GNUC__) || defined(__GNUG__) || defined(__clang__) + String HandleResponse(String query) __attribute__((weak)); +#else + String HandleResponse(String query); +#endif + +namespace thing_esp { + class Message : public RateLimiter { + public: + void sendMsg(String number, String msg) { + if (!is_device_calls_enabled()) { + LOG("ERR", + "Device-calls have not been enabled! Please go to ThingESP console and enable them from project settings."); + return; + } + + if (is_rate_limited()) { + LOG_VALUE("ERR", "This device-call have been rate limited! for (seconds): ", get_rate_limit()); + LOG("ERR", + "to reduce the rate-limiting, email me with your username and your project use-case."); + return; + } + + DynamicJsonDocument data_out(1024); + data_out["action"] = "device_call"; + data_out["to_number"] = number; + data_out["msg"] = msg; + sendResponse(data_out); + } + + void setCallback(String(*callback_func)(String)) { + this->callbackFunction = callback_func; + } + + + protected: + void onMessage(String &data) { + + DynamicJsonDocument data_in(1024); + DynamicJsonDocument data_out(1024); + deserializeJson(data_in, data); + + String incoming_action = data_in["action"]; + + if (incoming_action == "query") { + + if (!HandleResponse && !callbackFunction){ + LOG("MSG", "Error! No callback was set! Please set HandleResponse or setCallback!"); + return; + } + + data_out["msg_id"] = (const char *) data_in["msg_id"]; + data_out["action"] = "returned_api_response"; + String query = (const char *) data_in["query"]; + + #ifndef _DISABLE_LOWER_CASE_ + query.toLowerCase(); + #endif + + LOG_VALUE("MSG", "Query: ", query); + String resp = !!HandleResponse ? HandleResponse(query) : this->callbackFunction(query); + LOG_VALUE("MSG", "Response: ", resp); + data_out["returned_api_response"] = resp; + sendResponse(data_out); + + + } else if (incoming_action == "rate_limits_info") { + + unsigned int delay = (unsigned int) data_in["delay"]; + bool calls_enabled = (bool) data_in["calls_enabled"]; + + LOG_VALUE("INFO", "Device calls: ", calls_enabled ? "enabled" : "disabled"); + LOG_VALUE("INFO", "Got rate-limits (sec): ", delay / 1000); + + set_rate_limit(delay); + set_device_calls_status(calls_enabled); + + } else if (incoming_action == "server_msg") { + + String incoming_msg = (const char *) data_in["msg"]; + LOG_WITHOUT_F("MSG", incoming_msg); + + } + }; + + + void sendResponse(DynamicJsonDocument &json_doc) { + String out_str; + serializeJson(json_doc, out_str); + publishMSG(out_str.c_str()); + } + + + /* + * Overwritten in the client + */ + + String (*callbackFunction)(String); + + virtual void publishMSG(const char *msg) {}; + + + }; + +} \ No newline at end of file diff --git a/src/thingesp/RateLimiter.cpp b/src/thingesp/RateLimiter.cpp new file mode 100644 index 0000000..3ad6783 --- /dev/null +++ b/src/thingesp/RateLimiter.cpp @@ -0,0 +1,57 @@ +#pragma once + +#include +#include + +#include "../ArduinoJson.h" +#include "./Logger.cpp" + +namespace thing_esp { + class RateLimiter { + protected: + + bool is_rate_limited() { + unsigned int current_millis = millis(); + if (current_millis - last_called_millis >= RATE_LIMIT) { + last_called_millis = current_millis; + return false; + } else { + LOG("INFO", "You are getting Rate Limited!") + return true; + } + } + + void set_rate_limit(unsigned int _limit) { + RATE_LIMIT = _limit; + } + + const char *get_rate_limits_msg() { + +// DynamicJsonDocument data_out(1024); +// data_out["action"] = "get_rate_limits"; +// String out_msg; +// serializeJson(data_out, out_msg); +// return out_msg.c_str(); + + return "{\"action\": \"get_rate_limits\"}"; + } + + bool is_device_calls_enabled() { + return device_calls_enabled; + } + + void set_device_calls_status(bool is_enabled) { + device_calls_enabled = is_enabled; + } + + unsigned int get_rate_limit() { + return RATE_LIMIT / 1000; + } + + + private: + bool device_calls_enabled = false; + unsigned int last_called_millis = 0; + unsigned int RATE_LIMIT = 0; + }; +} \ No newline at end of file diff --git a/src/whesp8266.cpp b/src/whesp8266.cpp deleted file mode 100644 index ee030bb..0000000 --- a/src/whesp8266.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#if defined(ESP8266) -#include -#else -#include -#endif -#include "PubSubClient/PubSubClient.h" -#include "ArduinoJson.h" -//#include -//WiFiClient espClient; -//PubSubClient client(espClient); - -String HandleResponse(String query); - -class WH_ESP8266 -{ -public: - WH_ESP8266() - { - WiFiClient espClient; - PubSubClient client(espClient); - this->client = client; - }; - - void SetDevice(String username, String deviceName, String password) - { - this->Username = username; - this->DeviceName = deviceName; - this->Password = password; - } - void SetWiFi(const char *ssID, const char *ssID_password) - { - this->ssid = ssID; - this->ssid_password = ssID_password; - } - - void logic(String data) - { - DynamicJsonDocument data_in(1024); - DynamicJsonDocument data_out(1024); - deserializeJson(data_in, data); - - if (data_in["action"] == "query") - { - data_out["msg_id"] = data_in["msg_id"]; - data_out["action"] = "returned_api_response"; - String query = data_in["query"]; - query.toLowerCase(); - data_out["returned_api_response"] = HandleResponse(query); - String outdata; - serializeJson(data_out, outdata); - publishMSG(outdata.c_str()); - } - }; - - void sendMsg(String number, String msg) - { - DynamicJsonDocument data_out(1024); - data_out["action"] = "device_call"; - data_out["to_number"] = number; - data_out["msg"] = msg; - String outdata; - serializeJson(data_out, outdata); - publishMSG(outdata.c_str()); - } - - void initDevice() - { - // this->client = client; - this->topic = this->DeviceName + "/" + this->Username; - this->outname = this->DeviceName + "@" + this->Username; - - this->char_DeviceName = this->DeviceName.c_str(); - this->char_Password = this->Password.c_str(); - this->char_outname = this->outname.c_str(); - this->char_topic = this->topic.c_str(); - this->initiated = true; - - this->setupIT(); - } - - void Handle() - { - if (!client.connected()) - { - while (!client.connected()) - { - Serial.print("Attempting connection..."); - if (client.connect(this->char_outname, this->char_outname, this->char_Password)) - { - Serial.println("connected"); - client.subscribe(this->char_topic); - } - else - { - Serial.print("failed, rc="); - Serial.print(this->client.state()); - Serial.println(" try again in 5 seconds"); - delay(5000); - } - } - } - this->client.loop(); - } - - void publishMSG(const char *info) - { - client.publish(this->char_topic, info); - } - - void SetHost(const char *host) - { - this->mqttServer = host; - } - -private: - String Username; - String DeviceName; - String Password; - - bool initiated = false; - - const char *ssid; - const char *ssid_password; - - const char *mqttServer = "thingesp.siddhesh.me"; - int mqttPort = 1883; - - String topic; - String outname; - const char *char_DeviceName; - const char *char_Password; - const char *char_outname; - const char *char_topic; - - PubSubClient client; - - void callback(char *topic, byte *payload, unsigned int length) - { - String srr; - Serial.println(); - Serial.print("Message arrived ["); - Serial.print(topic); - Serial.print("] "); - Serial.println(); - for (int i = 0; i < length; i++) - { - Serial.print((char)payload[i]); - srr.concat((char)payload[i]); - } - this->logic(srr); - } - - void setupIT() - { - - Serial.println(); - Serial.print("Connecting to "); - Serial.println(ssid); - - WiFi.begin(ssid, ssid_password); - - while (WiFi.status() != WL_CONNECTED) - { - delay(500); - Serial.print("."); - } - - randomSeed(micros()); - - Serial.println(""); - Serial.println("WiFi connected"); - Serial.println("IP address: "); - Serial.println(WiFi.localIP()); - - this->client.setServer(this->mqttServer, this->mqttPort); - this->client.setCallback([this](char *topic, byte *payload, unsigned int length) { - this->callback(topic, payload, length); - }); - } -}; diff --git a/src/whesp8266.h b/src/whesp8266.h deleted file mode 100644 index 7b0ff3d..0000000 --- a/src/whesp8266.h +++ /dev/null @@ -1 +0,0 @@ -#include "whesp8266.cpp" \ No newline at end of file