I know this has been posted in the past I can’t find a clean example on how to do this. Would anyone be willing to share their code on how to store variable data with timestamp when offline and public then publish the data to the Particle cloud when online.
Ok here is what I have so far but please take it easy on me I’m trying to waste anyone’s time. The code verifies OK but does not save or return the data correctly. Any guidance really appreciated!
// This #include statement was automatically added by the Particle IDE.
#include <Ubidots.h>
// Distributed with a free-will license.
// Use it any way you want, profit or free, provided it fits in the licenses of its associated works.
// TMP112
// This code is designed to work with the TMP112_I2CS I2C Mini Module available from ControlEverything.com.
// https://www.controleverything.com/content/Temperature?sku=TMP112_I2CS#tabs-0-product_tabset-2
#include <application.h>
#include <spark_wiring_i2c.h>
// TMP112 I2C address is 0x48(72)
#define Addr 0x48
SYSTEM_THREAD(ENABLED);
double cTemp = 0.0, fTemp = 0.0;
const char* WEBHOOK_NAME = "Ubidots";
Ubidots ubidots("webhook", UBI_PARTICLE);
int address = 0; //EEPROM address counter
void printTemp();
void clearEEPROM();
unsigned long timestamp_seconds = Time.now();
struct MyObject {
char name[13];
double field1;
char field2[4];
unsigned long field3;
};
void setup()
{
Serial.begin();
pinMode(PWR, INPUT);
pinMode(CHG, INPUT);
// Set variable
Particle.variable("i2cdevice", "TMP112");
Particle.variable("cTemp", cTemp);
Particle.variable("fTemp", fTemp);
// Initialise I2C communication as MASTER
Wire.begin();
// Initialise Serial communication, set baud rate = 9600
Serial.begin(9600);
// Start I2C Transmission
Wire.beginTransmission(Addr);
// Select configuration register
Wire.write(0x01);
// Continuous conversion, comparator mode, 12-bit resolution
Wire.write(0x60);
Wire.write(0xA0);
// Stop I2C Transmission
Wire.endTransmission();
delay(300);
}
void loop()
{
delay(15000);
unsigned int data[2];
// Start I2C Transmission
Wire.beginTransmission(Addr);
// Select temperature data register
Wire.write(0x00);
// Stop I2C Transmission
Wire.endTransmission();
delay(300);
// Request 2 bytes of data
Wire.requestFrom(Addr, 2);
// Read 2 bytes of data
// temp msb, temp lsb
if(Wire.available() == 2)
{
data[0] = Wire.read();
data[1] = Wire.read();
}
// Convert the data to 12-bits
int temp = ((data[0] * 256) + (data[1])) / 16;
if(temp > 2048)
{
temp -= 4096;
}
cTemp = temp * 0.0625;
fTemp = cTemp * 1.8 + 32;
if(Particle.connected()==true) {
// Output data to dashboard
ubidots.add("Temperature", fTemp, NULL, timestamp_seconds); // Change for your variable name
bool bufferSent = false;
bufferSent = ubidots.send(WEBHOOK_NAME, PUBLIC);
printTemp();
clearEEPROM();
}
if(Particle.connected()==false) {
MyObject myObj = {"Temperature", fTemp, NULL, timestamp_seconds };
EEPROM.put(address, myObj); //write value to current address counter address
address++; //increment address counter
if(address == EEPROM.length()) //check if address counter has reached the end of EEPROM
{
address = 0; //if yes: reset address counter
}
}
}
void clearEEPROM()
{
for (int i = 0 ; i < EEPROM.length() ; i++) {
if(EEPROM.read(i) != 0) //skip already "empty" addresses
{
EEPROM.write(i, 0); //write 0 to address i
Particle.publish("DataCleared");
}
}
address = 0; //reset address counter
}
void printTemp()
{
for (int i = 0 ; i < EEPROM.length() ; i++) {
uint8_t value = EEPROM.read(i);
if(value != 0) //skip "empty" addresses
{
MyObject myObj;
EEPROM.get(i, myObj); //read EEPROM data at address i
ubidots.add(myObj.name, myObj.field1, myObj.field2, myObj.field3 );
bool bufferSent = false;
bufferSent = ubidots.send(WEBHOOK_NAME, PUBLIC);
Particle.publish("DataRetrieved");
}
}
}
What is your specific question or what does your code not do the way you expect it?
But I found a few things you may want to (re)consider.
You are using timestamp_seconds but only set it once, hence all your data objects will get the same time stamp. You need to refresh the value each time you collect/store new data.
You are only incrementing address by 1, but your data structure is longer than one byte, hence each new EEPROM.put() will corrupt the previously stored object(s).
Since your project seems to run permanently, you could use a normal array of MyObject fields - or if you want your data to survive a reset even opt for a retained array instead of EEPROM based instances of “volatile” data.
BTW, since you are always storing the same name with the actual data you are wasting almost half the memory on non-information. The name is only needed for publishing to ubidots and you have that hardcoded in all cases when creating a new set of data so the worth of that field is zero but uses a big portion of your data.
The other point is that it shouldn’t be necessary to always call ubidots.send() after each ubidots.add() call. AFAIK the add() function queues multiple entries and one final send() call should push them all out.