Reputation: 773
I want to use an array to store temperature readings from an Arduino on a Firestore database. My (probably terrible) way of thinking it out so far is to read the document, do my array operations on the Arduino, and send the whole array back to Firestore. I don't know how to write to Firestore via REST at all so I haven't implemented it yet. Here is my code:
void writeTemp(String url, int temperature) {
// writeTemp() appends the given temperature to an array. temperature[0]
// holds the oldest temperature while temperature[9] holds the first.
// When a new temperature is put in, the last one is taken out.
HTTPClient http;
http.begin(url);
int httpCode = http.GET();
// Gets the current temperature array from the provided URL.
String payload = http.getString();
Serial.println(httpCode); // Prints HTTP response code.
// Calculates the size of the JSON buffer. This is big enough for 11
// temperature values that are all 3 digits so as long as you're not using
// this on the Sun you're probably fine.
const size_t capacity = JSON_ARRAY_SIZE(11) + 14 * JSON_OBJECT_SIZE(1) +
JSON_OBJECT_SIZE(4) + 440;
DynamicJsonDocument doc(capacity); // Makes the JSON document
DeserializationError err = deserializeJson(doc, payload);
// Prints out the deserialization error if an error occurred
if (err) {
Serial.print("JSON DESERIALIZE ERROR: ");
Serial.println(err.c_str());
}
// Sets up the array from the JSON
JsonArray temperatureArray =
doc["fields"]["Temperature"]["arrayValue"]["values"];
// Creates a new array object to store the new temperature
JsonObject newTemp = temperatureArray.createNestedObject();
// Puts the new temperature in the new array object. For some reason,
// Firestore stores numbers as strings so the temperature is converted into
// a string.
newTemp["integerValue"] = String(temperature);
// Removes the first (oldest) array object.
temperatureArray.remove(0);
// Removes irrelevant data that we got from the Firestore request
doc.remove("name");
doc.remove("createTime");
doc.remove("updateTime");
String newJson;
serializeJson(doc, newJson);
Serial.println(newJson);
}
How would I send this new JSON back to Firestore? Am I even doing this right? I've heard of transactions, which sounds like the theoretically better way to do what I'm trying to do but I can't find any guides or readable documentation on how to do it. My database is in test mode right now so no need to worry about authentication.
Upvotes: 0
Views: 802
Reputation: 83068
The documentation for the Firestore REST API is here.
To create a document, you need to issue a POST Request to an URL with the following format:
https://firestore.googleapis.com/v1/{parent=projects/*/databases/*/documents/**}/{collectionId}
With an instance of a Document
in the Request body.
To be more concrete, below is an example in a simple HTML page (using the Axios library to issue the HTTP Request). This code will create a new document in the collection1
Firestore collection.
Just save this file on your local disk, adapt the value of <yourprojectID>
and opens this page in a browser, directly from your local disk.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<script>
var firebaseProjectId = '<yourprojectID>';
var collectionId = 'collection1';
var url =
'https://firestore.googleapis.com/v1/projects/' +
firebaseProjectId +
'/databases/(default)/documents/' +
collectionId;
var writeObj = {
fields: {
name: {
stringValue: 'theName'
},
initialBudget: {
doubleValue: 1200
}
}
};
axios.post(url, writeObj).catch(function(error) {
console.log(error);
});
</script>
</body>
</html>
In order to update an Array in an existing document, you have to use a FieldTransform
with appendMissingElements
elements.
Excerpt of this doc on appendMissingElements
elements:
appendMissingElements
: Append the given elements in order if they are not already present in the current field value. If the field is not an array, or if the field does not yet exist, it is first set to the empty array.
You will find below an example of FieldTransform
value containing appendMissingElements
elements.
{
"transform": {
"document": "projects/" + firebaseProjectId + "/databases/(default)/documents/....,
"fieldTransforms": [
{
"setToServerValue": "REQUEST_TIME",
"fieldPath": "lastUpdate"
},
{
"appendMissingElements": {
"values": [
{
"stringValue": "...."
}
]
},
"fieldPath": "fieldName"
}
]
}
}
UPDATE FOLLOWING YOUR COMMENT
The following should work (tested positively):
var collectionId = 'SensorData';
var url =
'https://firestore.googleapis.com/v1/projects/' +
firebaseProjectId +
'/databases/(default)/documents:commit';
var writeObj = {
writes: {
transform: {
document:
'projects/' +
firebaseProjectId +
'/databases/(default)/documents/' +
collectionId +
'/Temperature',
fieldTransforms: [
{
setToServerValue: 'REQUEST_TIME',
fieldPath: 'lastUpdate'
},
{
appendMissingElements: {
values: [
{
integerValue: 25
}
]
},
fieldPath: 'Temperature'
}
]
}
}
};
Upvotes: 3