implement API upload
This commit is contained in:
parent
e3581f3088
commit
8ef77fcc97
7 changed files with 81 additions and 68 deletions
27
api.h
27
api.h
|
@ -1,30 +1,39 @@
|
|||
#pragma once
|
||||
#include <WiFiClientSecure.h>
|
||||
#include "config.h"
|
||||
#include "streampipe.h"
|
||||
|
||||
class OsemApi {
|
||||
protected:
|
||||
WiFiClientSecure client;
|
||||
|
||||
public:
|
||||
bool postMeasurement(String m, String sensorID) {
|
||||
bool postMeasurement(String measurement, String sensorID) {
|
||||
//telnet.print("Connecting to API.. ");
|
||||
if (!client.connect(API_ENDPOINT, 443)) {
|
||||
//telnet.println("connection failed");
|
||||
//Serial.println("connection failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!client.verify(API_FINGERPRINT, API_ENDPOINT)) {
|
||||
Serial.println("certificate doesn't match");
|
||||
//Serial.println("certificate doesn't match");
|
||||
return false;
|
||||
}
|
||||
|
||||
String url = "/boxes/" + String(ID_BOX) + "/" + sensorID;
|
||||
// TODO: add actual measurement to post
|
||||
client.print(String("POST ") + url + " HTTP/1.1\r\n" +
|
||||
"Host: " + API_ENDPOINT + "\r\n" +
|
||||
"User-Agent: mobile-sensebox-esp8266\r\n" +
|
||||
"Connection: close\r\n\r\n");
|
||||
client << String("POST ") << "/boxes/" << ID_BOX << "/" << sensorID << " HTTP/1.1" << EOL;
|
||||
client << "Host: " << API_ENDPOINT << EOL;
|
||||
client << "X-APIKey: " << API_KEY << EOL;
|
||||
client << "Content-Type: application/json" << EOL;
|
||||
client << "Connection: close" << EOL;
|
||||
client << "Content-Length: " << measurement.length() << EOL << EOL;
|
||||
client << measurement;
|
||||
|
||||
// read response
|
||||
while (client.connected()) {
|
||||
String line = client.readStringUntil('\n');
|
||||
if (line == "\r") break;
|
||||
}
|
||||
Serial << "API-Server response: " << client.readString() << EOL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
27
config.h
27
config.h
|
@ -1,19 +1,22 @@
|
|||
/* WiFi (ESP8266) */
|
||||
#pragma once
|
||||
|
||||
static const char* WIFI_SSID = "Elmo";
|
||||
static const char* WIFI_PASS = "FreiBier123";
|
||||
/* WiFi (ESP8266) */
|
||||
|
||||
|
||||
#define WIFI_SSID "Penaten"
|
||||
#define WIFI_PASS "XXXXXX"
|
||||
|
||||
/* GPS reciever (uBloc NEO-7M) */
|
||||
static const int GPS_RX_PIN = 4;
|
||||
static const int GPS_TX_PIN = 3;
|
||||
static const int GPS_BAUD = 9600;
|
||||
static const int GPS_INTERVAL = 1000; // update interval of the gps device
|
||||
#define GPS_RX_PIN 4
|
||||
#define GPS_TX_PIN 3
|
||||
#define GPS_BAUD 9600
|
||||
#define GPS_INTERVAL 1000 // update interval of the gps device
|
||||
|
||||
/* API (openSenseMap) */
|
||||
static const char* API_ENDPOINT = "api.opensensemap.org";
|
||||
#define API_ENDPOINT "api.osem.vo1d.space"
|
||||
// SHA1 of the API SSL cert
|
||||
static const char* API_FINGERPRINT = "0F B0 0C E0 FD 18 C2 0B 07 1C 21 AB A0 FF EF CC 09 62 57 A9";
|
||||
static const char* API_KEY = "...";
|
||||
static const char* ID_BOX = "57308b2c566b8d3c11114a9f";
|
||||
static const char* ID_SENSOR_WIFI = "...";
|
||||
#define API_FINGERPRINT "A2 38 74 C7 B0 71 07 D4 2A 1C A5 6D 0D 05 3E 0A 90 68 A5 CB"
|
||||
#define API_KEY_LENGTH 24
|
||||
#define API_KEY "XXXXXXXXXXX"
|
||||
#define ID_BOX "57c7f3291421551100bf13c8"
|
||||
#define ID_SENSOR_WIFI "57c7f3291421551100bf13ca"
|
||||
|
|
8
gps.h
8
gps.h
|
@ -3,6 +3,8 @@
|
|||
#include <Time.h>
|
||||
#include "config.h"
|
||||
|
||||
// TODO: refactor updateXXX members to be protected and called by getXXX ?
|
||||
|
||||
class Gps {
|
||||
protected:
|
||||
TinyGPSPlus gps;
|
||||
|
@ -59,8 +61,12 @@ class Gps {
|
|||
return true;
|
||||
}
|
||||
|
||||
TinyGPSLocation& getLocation() {
|
||||
return gps.location;
|
||||
}
|
||||
|
||||
/**
|
||||
* return an iso8266 formatted datestring with the current time
|
||||
* return an iso8601 formatted datestring with the current time
|
||||
*/
|
||||
static char* getISODate() {
|
||||
// TODO: check why we need to allocate that much storage for a 20 character string for Serial printing??
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "TelnetPrint.h"
|
||||
|
||||
#define DEBUG_OUT Serial
|
||||
//#define DEBUG_OUT telnet
|
||||
|
||||
//TelnetPrint telnet = TelnetPrint();
|
||||
Storage storage = Storage();
|
||||
|
@ -23,15 +24,15 @@ void printState(WifiState wifiState) {
|
|||
DEBUG_OUT.println(wifiState.numUnencrypted);
|
||||
|
||||
DEBUG_OUT.print("lat: ");
|
||||
//DEBUG_OUT.print(gps.location.lat(), 6);
|
||||
//DEBUG_OUT.print(gps.getLocation().lat(), 6);
|
||||
DEBUG_OUT.print(" lng: ");
|
||||
//DEBUG_OUT.println(gps.location.lng(), 6);
|
||||
//DEBUG_OUT.println(gps.getLocation().lng(), 6);
|
||||
|
||||
DEBUG_OUT.println(gps.getISODate());
|
||||
DEBUG_OUT.println("");
|
||||
}
|
||||
|
||||
bool storeMeasurement(float lat, float lng, float value, char* timeStamp, char* sensorID) {
|
||||
bool storeMeasurement(float lat, float lng, float value, const char* timeStamp, const char* sensorID) {
|
||||
Measurement m;
|
||||
m.lat = lat;
|
||||
m.lng = lng;
|
||||
|
@ -51,7 +52,7 @@ void setup() {
|
|||
//gps.begin();
|
||||
wifi.begin();
|
||||
|
||||
//connectWifi(WIFI_SSID, WIFI_PASS);
|
||||
wifi.connect(WIFI_SSID, WIFI_PASS);
|
||||
|
||||
//delay(5000); // DEBUG oportunity to connect to network logger
|
||||
|
||||
|
@ -76,7 +77,7 @@ void setup() {
|
|||
void loop() {
|
||||
//pollGPS();
|
||||
//DEBUG_OUT.pollClients();
|
||||
WifiState wifiState = wifi.scanWifi(WIFI_SSID);
|
||||
WifiState wifiState = wifi.scan(WIFI_SSID);
|
||||
char* dateString = gps.getISODate();
|
||||
|
||||
// TODO: take other measurements (average them?)
|
||||
|
@ -86,7 +87,7 @@ void loop() {
|
|||
*/
|
||||
|
||||
// write measurements to file
|
||||
if (storeMeasurement(51.2, 7.89, wifiState.numNetworks, dateString, "12341234123412341234123412341234")) {
|
||||
if (storeMeasurement(51.25345345, 7.89, wifiState.numNetworks, "2016-08-31T00:03:10Z", ID_SENSOR_WIFI)) {
|
||||
DEBUG_OUT.print("measurement stored! storage size: ");
|
||||
} else {
|
||||
DEBUG_OUT.print("measurement store failed! storage size: ");
|
||||
|
@ -94,17 +95,14 @@ void loop() {
|
|||
DEBUG_OUT.println(storage.size());
|
||||
|
||||
// TODO: connect to wifi, if available & not connected yet
|
||||
// then upload local data, remove from storage
|
||||
|
||||
// DEBUG: recall all previous measurements
|
||||
// then upload local data, remove from storage
|
||||
while (storage.size()) {
|
||||
String measure = storage.pop();
|
||||
//api.postMeasurement(measure.substring(0, 31), measure.substring(32));
|
||||
DEBUG_OUT.println("popped a measurement: ");
|
||||
DEBUG_OUT.println(measure.substring(0, 31)); // size of sensorID
|
||||
DEBUG_OUT.println(measure.substring(32)); // skip the newline char
|
||||
api.postMeasurement(measure.substring(API_KEY_LENGTH + 1), measure.substring(0, API_KEY_LENGTH));
|
||||
}
|
||||
|
||||
printState(wifiState);
|
||||
delay(5000);
|
||||
}
|
||||
|
||||
|
|
49
storage.h
49
storage.h
|
@ -2,45 +2,36 @@
|
|||
|
||||
#include <FS.h>
|
||||
#include <ESP8266TrueRandom.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include "api.h"
|
||||
#include "config.h"
|
||||
#include "streampipe.h"
|
||||
|
||||
#define MEASUREMENT_JSON_SIZE (JSON_OBJECT_SIZE(5))
|
||||
#define MEASUREMENT_JSON_SIZE (JSON_OBJECT_SIZE(4)) // 4 properties (sensorID is excluded)
|
||||
|
||||
struct Measurement {
|
||||
char timeStamp[20];
|
||||
float lat;
|
||||
float lng;
|
||||
float value;
|
||||
char sensorID[32];
|
||||
char sensorID[API_KEY_LENGTH];
|
||||
};
|
||||
|
||||
class Storage {
|
||||
protected:
|
||||
// not needed, as we post the data as json string?
|
||||
/*Measurement deserializeMeasurement(char* s) {
|
||||
Measurement m;
|
||||
StaticJsonBuffer<MEASUREMENT_JSON_SIZE> jsonBuffer;
|
||||
JsonObject& root = jsonBuffer.parseObject(s);
|
||||
m.timeStamp = (const char[sizeof Measurement.timeStamp])jsonBuffer.strdup(root["date"]);
|
||||
m.lat = root["lat"];
|
||||
m.lng = root["lng"];
|
||||
m.value = root["value"];
|
||||
m.sensorID = root["sensorId"];
|
||||
return m;
|
||||
}*/
|
||||
void serializeMeasurement(Measurement& m, Print& f) {
|
||||
// prepend the sensor ID to the json
|
||||
f << m.sensorID << EOL;
|
||||
|
||||
bool serializeMeasurement(Measurement& m, Print& f) {
|
||||
f.println(m.sensorID);
|
||||
StaticJsonBuffer<MEASUREMENT_JSON_SIZE> jsonBuffer;
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
// TODO: replace temporary data model
|
||||
root["createdAt"] = m.timeStamp;
|
||||
root["lat"] = m.lat;
|
||||
root["lng"] = m.lng;
|
||||
root["value"] = m.value;
|
||||
root.printTo(f);
|
||||
return root.success();
|
||||
// convert floats to strings
|
||||
char val[10], lat[10], lng[10];
|
||||
dtostrf(m.value, 5, 6, val);
|
||||
dtostrf(m.lat, 5, 6, lat);
|
||||
dtostrf(m.lng, 5, 6, lng);
|
||||
|
||||
f << "{\"value\":" << val
|
||||
<< ",\"createdAt\":\"" << m.timeStamp
|
||||
<< "\",\"lat\":" << lat
|
||||
<< ",\"lng\":" << lng
|
||||
<< "}" << EOL;
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -60,9 +51,9 @@ class Storage {
|
|||
String fileName = directory + ESP8266TrueRandom.uuidToString(uuid).substring(26);
|
||||
|
||||
if (File f = SPIFFS.open(fileName, "w") ) {
|
||||
bool success = serializeMeasurement(m, f);
|
||||
serializeMeasurement(m, f);
|
||||
f.close();
|
||||
return success;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
6
streampipe.h
Normal file
6
streampipe.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
// add classic C stream pipe operator to arduino C
|
||||
|
||||
#pragma once
|
||||
#define EOL "\r\n"
|
||||
|
||||
template<class T> inline Print &operator <<(Print &obj, T arg) { obj.print(arg); return obj; }
|
4
wifi.h
4
wifi.h
|
@ -14,7 +14,7 @@ class Wifi {
|
|||
WiFi.mode(WIFI_STA);
|
||||
}
|
||||
|
||||
WifiState scanWifi(String homeSSID) {
|
||||
WifiState scan(String homeSSID) {
|
||||
// TODO: filter duplicate SSIDs!
|
||||
WifiState state;
|
||||
state.homeAvailable = false;
|
||||
|
@ -32,7 +32,7 @@ class Wifi {
|
|||
return state;
|
||||
}
|
||||
|
||||
bool connectWifi(const char* ssid, const char* pass) {
|
||||
bool connect(const char* ssid, const char* pass) {
|
||||
static const unsigned int timeout = 10000; // abort after 10 secs
|
||||
unsigned long start = millis();
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue