Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A way to set the timestamp inside a json object? #91

Closed
mbariola opened this issue Aug 7, 2020 · 19 comments
Closed

A way to set the timestamp inside a json object? #91

mbariola opened this issue Aug 7, 2020 · 19 comments
Labels
help wanted Extra attention is needed question Further information is requested

Comments

@mbariola
Copy link

mbariola commented Aug 7, 2020

Hi there @mobizt

I need to save a moderately complex JSON object, which has an array of integers, some integers, and some strings. By following your examples, I am able to set a JSON object and commit it in one go.

This JSON object also has a timestamp, but I was not able to set it in the json object to commit. Only to do it in 2 steps: first the object without the timestamp, then fetching the object key and save the timestamp in it by giving a path within the object I just created.

Is there a way to do it in just one step?

to clarify I need to save something like this at /clients/config/[clientName]/current and would like it to happen in one go

configOptions: [int, int, int.......... int],
configVersion int,
name: string,
CreatedAt: Timestamp

Many thanks

@mbariola mbariola added help wanted Extra attention is needed question Further information is requested labels Aug 7, 2020
@mobizt
Copy link
Owner

mobizt commented Aug 7, 2020

Please share the code that you create the JSON object with timestamp.

@mobizt mobizt closed this as completed Aug 8, 2020
@mobizt
Copy link
Owner

mobizt commented Aug 9, 2020

No more feedback?

@mbariola
Copy link
Author

mbariola commented Aug 9, 2020 via email

@mbariola
Copy link
Author

mbariola commented Aug 10, 2020

Hi @mobizt , thanks for waiting

here is the code. It does not compile (error on the timestamp line) ... as you have seen, I have tried to do it with a FirebaseData too, no luck. probably it's something trivial but I have difficulty understanding the separation of concerns between FirebaseJson objects and FirebaseData ones.

Ideally, I would like to create in memory the JSON object, then push it to a /...../clientID/readings path which will contain N (an array) of the objects I am building

FirebaseData firebaseData; // Firebase Object
FirebaseJsonArray readingsJsonArray;
FirebaseJson testObj;
      ....


                    /* code */
                    // build the obj to send
                    Firebase.setTimestamp(firebaseData, "/datetime");
                    for(int i = 0; i< numSteps; i++)
                    {
                      readingsJsonArray.add(stepStatus[i]);
                    }
                    testObj.set("/readings", readingsJsonArray);
                    //Firebase.set(firebaseData, "/readings", readingsJsonArray);
                    testObj.setTimestamp("/readingDateTime");
                    //Firebase.setTimestamp(firebaseData, "/readingDateTime" );
                    testObj.set("/gloveID", "DemoGloveID");
                    //Firebase.set(firebaseData, "/gloveID", "DemoGloveID" );
                    Firebase.push(firebaseData, readingsSavePath, testObj);
                    readingsJsonArray.clear();
                    testObj.clear();

@mobizt
Copy link
Owner

mobizt commented Aug 10, 2020

That is because you use the wrong syntax.

The setTimestamp function is not available (not existed) for FirebaseJson object.

The data types i.e. bool, int, float, double, string, JSON object and JSON array object are supported with set and add function of FirebaseJson and FirebaseJsonArray.

The FirebaseJson is the JSON object (class) that used for JSON data manipulation (create, edit and parsing)
and FirebaseJsonArray is the array object (class) which can creat, edit and then add to the JSON object (FirebaseJson).

The FirebaseJsonData (similar to FirebaseData object) is the class object that holds the parsing result when you want to get or extract the value from specific key in the FirebaseJson object.

The Firebase.setTimestamp function is for Firebase class only. This timestamp value was hidden from Firebase web console but you can read its double value (UNIX timestamp value of milliseconds) from specific node with the FirebasegetDouble function as seen in Timestamp.ino example.

To check all supported function please see this.

If you want to set the timestamp to the JSON object, you just use

testObj.set("/readingDateTime", xxxxxxxxxxxx);

Where as xxxxxxxxxxxx is the integer number of timestamp which you need to assign or get it from the system time of the device (NTP server or RTC chip).

This is total difference from Firebase.setTimestamp which you don't need to provide the timestamp value to the function, Firebase will be set it for you automatically at the server side.

@mbariola
Copy link
Author

mbariola commented Aug 10, 2020

Hi @mobizt ,

I understand a little bit better, and that I had a confusion between client set timestamp and firebase set timestamp. So, what I want to achieve, is to create an array of JSON objects. each of the objects is made like this:

  • readingDateTime: a timestamp given by Firebase (I understand that it is created but hidden by firebase. how should I do if I want it to be visible and explicit?)
  • readings: an array of int values
  • deviceID: a string identifying the device
    .... I would like to create this object in memory then add it in one go to a list (or array) of similar JSON objects at firebase path /clients/clientname/readings

So, I seem to understand that

  1. I need to copy my normal int array into a FirebaseJsonArray, then add this array to a .... FirebaseJson? (i.e. testObj)

  2. Add other key/values pairs to this FirebaseJson object. Is it correct to say that at this moment, the object has not been saved to Firebase and all paths are relative to the object itself?

  3. push this object in the firebase path (i.e. save to firebase) where the list of readings is. I am not sure at this point what syntax is best to use.
    3.1) If I want to have an explicitly set timestamp from Firebase, how should I specify it while building the object befoee pushing it to firebase?

Thanks

@mbariola
Copy link
Author

mbariola commented Aug 10, 2020

ok, this is the current version of the code.....

                    for(int i = 0; i< numSteps; i++)
                    {
                      readingsJsonArray.add((int)stepStatus[i]);
                    }
                    testObj.set("/readings", readingsJsonArray);
                    testObj.set("/sockID", "DemoSockID");
                    // TODO:  /readingDateTime needs to be set by Firebase server
                    Firebase.push(firebaseData, readingsSavePath, testObj);
                    readingsJsonArray.clear(); // will this deallocate the memory / best way to avoid leaks / fragmentation?
                    testObj.clear();

It works. And I also saw that I can construct the object in memory and push it in one go with Firebase.push.

But I still need to set the readingsDateTime key/value with the Firebase server value . This bit I do not know how to do in a short way.

@mobizt
Copy link
Owner

mobizt commented Aug 11, 2020

You can't set the server value in to any json data.

You need to make a single request for set server value timestamp.

Please read the Firebase REST API document.

@mbariola
Copy link
Author

mbariola commented Aug 11, 2020 via email

@mobizt
Copy link
Owner

mobizt commented Aug 11, 2020

Yes.

@mbariola
Copy link
Author

mbariola commented Aug 11, 2020 via email

@mbariola
Copy link
Author

mbariola commented Aug 11, 2020 via email

@mobizt
Copy link
Owner

mobizt commented Aug 11, 2020

For server timestamp, the pay load for the request sent to server must be {".sv":"timestamp"} which should not mixed by any user data.

@mbariola
Copy link
Author

mbariola commented Aug 11, 2020 via email

@mobizt
Copy link
Owner

mobizt commented Aug 11, 2020

No, I only explain what the server timestamp payload (data that being send to server) should be.

When you call the Firebasse.setTimestamp function, the library sent this JSON {".sv":"timestamp"} to Firebase server.
This kind of JSON payload is treated like a command not a user data.

@mbariola
Copy link
Author

mbariola commented Aug 11, 2020

Hi @mobizt , yes that I understood, but had problems to find out how to make sure to pass that special value at the time of object creation.

So I experimented a little with what you said, and found a way. I don't know if it's the most elegant one, but it works and it does all with just one call to firebase


FirebaseJson testObj;

                    for(int i = 0; i< numSteps; i++)
                    {
                      readingsJsonArray.add((int)stepStatus[i]);
                    }
                    testObj.set("/readings", readingsJsonArray);
                    testObj.set("/shirtID", "DemoShirtID");
                    testObj.set("/readingDateTime/.sv", "timestamp");
                    Firebase.push(firebaseData, readingsSavePath, testObj) || Serial.println(firebaseData.errorReason());
                    readingsJsonArray.clear();
                    testObj.clear();
                  

Thanks for your input, it nudged me in the right direction. Cheers!

@mobizt
Copy link
Owner

mobizt commented Aug 11, 2020

You can trust the device time as you can get the time from NTP server that give you the same and accurate timestamp for every client device.

The millisecond timestamp is only the second timestamp multiplied by 1000.

Some Time library provides more precision timestamp from NTP server with the request/response time delay compensation.

@mbariola
Copy link
Author

Unfortunately I am developing a battery powered device and thus it is most of the time in super low power mode and offline. it comes online only to send data in bursts, then goes offline again. Any extra call shortens battery life. But I found a way that works (see comment above)! thanks for the info

@ksb86
Copy link

ksb86 commented Dec 23, 2020

@mbariola Thanks for posting, I had the same question. Your implementation worked for me too. Using the '.set' with a path instead of the '.add' method on the json object is the trick. Also, thanks @mobizt for this library, works great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants