Adafruit_IO_Arduino/AdafruitIO.cpp
2016-08-03 12:16:32 -04:00

184 lines
4.3 KiB
C++

#include "AdafruitIO.h"
AdafruitIO::AdafruitIO(){}
void AdafruitIO::connect(const char *user, const char *key)
{
_username = user;
_key = key;
_init();
}
void AdafruitIO::connect(const __FlashStringHelper *user, const __FlashStringHelper *key)
{
_username = (const char*)user;
_key = (const char*)key;
_init();
}
AdafruitIO_Feed* AdafruitIO::feed(const char* name)
{
return new AdafruitIO_Feed(this, name);
}
AdafruitIO_Feed* AdafruitIO::feed(const __FlashStringHelper *name)
{
return new AdafruitIO_Feed(this, name);
}
void AdafruitIO::_init()
{
// we have never pinged, so set last ping to now
_last_ping = millis();
// call child class connect
_connect();
// dynamically allocate memory for err topic
_err_topic = (char *)malloc(sizeof(char) * (strlen(_username) + strlen(AIO_ERROR_TOPIC) + 1));
if(_err_topic) {
// build error topic
strcpy(_err_topic, _username);
strcat(_err_topic, AIO_ERROR_TOPIC);
// setup error sub
_subscriptions[0] = new Adafruit_MQTT_Subscribe(_mqtt, _err_topic);
_mqtt->subscribe(_subscriptions[0]);
} else {
// malloc failed
_err_topic = 0;
}
// dynamically allocate memory for throttle topic
_throttle_topic = (char *)malloc(sizeof(char) * (strlen(_username) + strlen(AIO_THROTTLE_TOPIC) + 1));
if(_throttle_topic) {
// build throttle topic
strcpy(_throttle_topic, _username);
strcat(_throttle_topic, AIO_THROTTLE_TOPIC);
// setup throttle sub
_subscriptions[1] = new Adafruit_MQTT_Subscribe(_mqtt, _throttle_topic);
_mqtt->subscribe(_subscriptions[1]);
} else {
// malloc failed
_throttle_topic = 0;
}
}
void AdafruitIO::setErrorHandler(SubscribeCallbackBufferType cb)
{
_subscriptions[0]->setCallback(cb);
_subscriptions[1]->setCallback(cb);
}
const __FlashStringHelper* AdafruitIO::statusText()
{
switch(_status) {
// CONNECTING
case AIO_IDLE: return F("Idle. Waiting for connect to be called...");
case AIO_NET_DISCONNECTED: return F("Network disconnected.");
case AIO_DISCONNECTED: return F("Disconnected from Adafruit IO.");
// FAILURE
case AIO_NET_CONNECT_FAILED: return F("Network connection failed.");
case AIO_CONNECT_FAILED: return F("Adafruit IO connection failed.");
case AIO_FINGERPRINT_INVALID: return F("Adafruit IO SSL fingerprint verification failed.");
case AIO_AUTH_FAILED: return F("Adafruit IO authentication failed.");
// SUCCESS
case AIO_NET_CONNECTED: return F("Network connected.");
case AIO_CONNECTED: return F("Adafruit IO connected.");
case AIO_CONNECTED_INSECURE: return F("Adafruit IO connected. **THIS CONNECTION IS INSECURE** SSL/TLS not supported for this platform.");
case AIO_FINGERPRINT_UNSUPPORTED: return F("Adafruit IO connected over SSL/TLS. Fingerprint verification unsupported.");
case AIO_FINGERPRINT_VALID: return F("Adafruit IO connected over SSL/TLS. Fingerprint valid.");
default: return F("Unknown status code");
}
}
void AdafruitIO::run()
{
// loop until we have a connection
while(mqttStatus() != AIO_CONNECTED){}
_mqtt->processPackets(1000);
// ping to keep connection alive if needed
if(millis() > (_last_ping + AIO_PING_INTERVAL)) {
_mqtt->ping();
_last_ping = millis();
}
}
aio_status_t AdafruitIO::status()
{
aio_status_t net_status = networkStatus();
// if we aren't connected, return network status
if(net_status != AIO_NET_CONNECTED) {
_status = net_status;
return _status;
}
// check mqtt status and return
_status = mqttStatus();
return _status;
}
aio_status_t AdafruitIO::mqttStatus()
{
// if the connection failed,
// return so we don't hammer IO
if(_status == AIO_CONNECT_FAILED)
return _status;
if(_mqtt->connected())
return AIO_CONNECTED;
switch(_mqtt->connect(_username, _key)) {
case 0:
return AIO_CONNECTED;
case 1: // invalid mqtt protocol
case 2: // client id rejected
case 4: // malformed user/pass
case 5: // unauthorized
case 7: // banned
case -1: // general failure
return AIO_CONNECT_FAILED;
case 3: // mqtt service unavailable
case 6: // throttled
// delay to prevent fast reconnects
delay(AIO_THROTTLE_RECONNECT_INTERVAL);
return AIO_DISCONNECTED;
default:
return AIO_DISCONNECTED;
}
}