Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
282 lines (220 sloc) 6.55 KB
//
// Adafruit invests time and resources providing this open source code.
// Please support Adafruit and open source hardware by purchasing
// products from Adafruit!
//
// Copyright (c) 2015-2016 Adafruit Industries
// Authors: Tony DiCola, Todd Treece, Adam Bachman
// Licensed under the MIT license.
//
// All text above must be included in any redistribution.
//
#include "AdafruitIO_Feed.h"
#include "AdafruitIO.h"
AdafruitIO_Feed::AdafruitIO_Feed(AdafruitIO *io, const char *n):AdafruitIO_MQTT()
{
_io = io;
name = n;
owner = _io->_username;
_init();
}
AdafruitIO_Feed::AdafruitIO_Feed(AdafruitIO *io, const char *n, const char *un):AdafruitIO_MQTT()
{
_io = io;
name = n;
owner = un;
_init();
}
AdafruitIO_Feed::~AdafruitIO_Feed()
{
if(_sub)
delete _sub;
if(_pub)
delete _pub;
if(_get_pub)
delete _get_pub;
if(data)
delete data;
if(_topic)
free(_topic);
if (_get_topic)
free(_get_topic);
if(_feed_url)
free(_feed_url);
if(_create_url)
free(_create_url);
}
void AdafruitIO_Feed::onMessage(AdafruitIODataCallbackType cb)
{
_dataCallback = cb;
}
bool AdafruitIO_Feed::save(char *value, double lat, double lon, double ele)
{
data->setValue(value, lat, lon, ele);
return _pub->publish(data->toCSV());
}
bool AdafruitIO_Feed::save(bool value, double lat, double lon, double ele)
{
data->setValue(value, lat, lon, ele);
return _pub->publish(data->toCSV());
}
bool AdafruitIO_Feed::save(String value, double lat, double lon, double ele)
{
data->setValue(value, lat, lon, ele);
return _pub->publish(data->toCSV());
}
bool AdafruitIO_Feed::save(int value, double lat, double lon, double ele)
{
data->setValue(value, lat, lon, ele);
return _pub->publish(data->toCSV());
}
bool AdafruitIO_Feed::save(unsigned int value, double lat, double lon, double ele)
{
data->setValue(value, lat, lon, ele);
return _pub->publish(data->toCSV());
}
bool AdafruitIO_Feed::save(long value, double lat, double lon, double ele)
{
data->setValue(value, lat, lon, ele);
return _pub->publish(data->toCSV());
}
bool AdafruitIO_Feed::save(unsigned long value, double lat, double lon, double ele)
{
data->setValue(value, lat, lon, ele);
return _pub->publish(data->toCSV());
}
bool AdafruitIO_Feed::save(float value, double lat, double lon, double ele, int precision)
{
data->setValue(value, lat, lon, ele, precision);
return _pub->publish(data->toCSV());
}
bool AdafruitIO_Feed::save(double value, double lat, double lon, double ele, int precision)
{
data->setValue(value, lat, lon, ele, precision);
return _pub->publish(data->toCSV());
}
bool AdafruitIO_Feed::get()
{
return _get_pub->publish("\0");
}
bool AdafruitIO_Feed::exists()
{
_io->_http->beginRequest();
_io->_http->get(_feed_url);
_io->_http->sendHeader("X-AIO-Key", _io->_key);
_io->_http->endRequest();
int status = _io->_http->responseStatusCode();
_io->_http->responseBody(); // needs to be read even if not used
return status == 200;
}
bool AdafruitIO_Feed::create()
{
String body = "name=";
body += name;
_io->_http->beginRequest();
_io->_http->post(_create_url);
_io->_http->sendHeader("Content-Type", "application/x-www-form-urlencoded");
_io->_http->sendHeader("Content-Length", body.length());
_io->_http->sendHeader("X-AIO-Key", _io->_key);
// the following call to endRequest
// should be replaced by beginBody once the
// Arduino HTTP Client Library is updated
// _io->_http->beginBody();
_io->_http->endRequest();
_io->_http->print(body);
_io->_http->endRequest();
int status = _io->_http->responseStatusCode();
_io->_http->responseBody(); // needs to be read even if not used
return status == 201;
}
AdafruitIO_Data* AdafruitIO_Feed::lastValue()
{
// 15 extra for api path, 12 for /data/retain, 1 for null
String url = "/api/v2/";
url += owner;
url += "/feeds/";
url += name;
url += "/data/retain";
AIO_DEBUG_PRINT("lastValue get ");
AIO_DEBUG_PRINTLN(url);
_io->_http->beginRequest();
_io->_http->get(url.c_str());
_io->_http->sendHeader("X-AIO-Key", _io->_key);
_io->_http->endRequest();
int status = _io->_http->responseStatusCode();
String body = _io->_http->responseBody();
if (status >= 200 && status <= 299) {
if (body.length() > 0) {
return new AdafruitIO_Data(this, body.c_str());
}
return NULL;
} else {
AIO_ERROR_PRINT("error retrieving lastValue, status: ");
AIO_ERROR_PRINTLN(status);
AIO_ERROR_PRINT("response body: ");
AIO_ERROR_PRINTLN(_io->_http->responseBody());
return NULL;
}
}
void AdafruitIO_Feed::setLocation(double lat, double lon, double ele)
{
data->setLocation(lat, lon, ele);
}
void AdafruitIO_Feed::subCallback(char *val, uint16_t len)
{
data->setCSV(val);
// call callback with data
if(_dataCallback)
_dataCallback(data);
}
void AdafruitIO_Feed::_init()
{
_sub = 0;
_pub = 0;
_get_pub = 0;
_dataCallback = 0;
// dynamically allocate memory for mqtt topic and REST URLs
_topic = (char *) malloc(sizeof(char) * (strlen(owner) + strlen(name) + 8)); // 8 extra chars for /f/, /csv & null termination
_get_topic = (char *) malloc(sizeof(char) * (strlen(owner) + strlen(name) + 12)); // 12 extra chars for /f/, /csv/get & null termination
_feed_url = (char *) malloc(sizeof(char) * (strlen(owner) + strlen(name) + 16)); // 16 extra for api path & null term
_create_url = (char *) malloc(sizeof(char) * (strlen(owner) + 15)); // 15 extra for api path & null term
// init feed data
data = new AdafruitIO_Data(this);
if(_topic && _create_url && _feed_url) {
// build topic string
strcpy(_topic, owner);
strcat(_topic, "/f/");
strcat(_topic, name);
strcat(_topic, "/csv");
// build feed url string
strcpy(_feed_url, "/api/v2/");
strcat(_feed_url, owner);
strcat(_feed_url, "/feeds/");
strcat(_feed_url, name);
// build create url string
strcpy(_create_url, "/api/v2/");
strcat(_create_url, owner);
strcat(_create_url, "/feeds");
// build /get topic string
strcpy(_get_topic, owner);
strcat(_get_topic, "/f/");
strcat(_get_topic, name);
strcat(_get_topic, "/csv/get");
// setup subscription
_sub = new Adafruit_MQTT_Subscribe(_io->_mqtt, _topic);
_pub = new Adafruit_MQTT_Publish(_io->_mqtt, _topic);
_get_pub = new Adafruit_MQTT_Publish(_io->_mqtt, _get_topic);
_io->_mqtt->subscribe(_sub);
_sub->setCallback(this, &AdafruitIO_MQTT::subCallback);
} else {
// malloc failed
_topic = 0;
_get_topic = 0;
_create_url = 0;
_feed_url = 0;
_sub = 0;
_pub = 0;
_get_pub = 0;
data = 0;
}
}