Timestamp with each action

Hey all,

I’m new to the spark community and have been poking around various tutorials and projects to get acquainted with the time function. Seems like aside from calling the built in RTC, I can just use time.hour(); and whatnot to call time that has been synced with the cloud.
While this seems like an incredibly straightforward idea, I’ve been having some trouble with figuring out how to timestamp certain actions. For example, the code I have right now counts every button presses and can report it to me via the cloud, but I can’t figure out how I can store the timestamp for each button press and have that displayed. Thought about using both time and milis, but not sure what the best way is to go about it.

Any help would be awesome! I’m excited to start my sparkcore projects, and this would help tremendously.

1 Like

@jkkim93, creating a timestamp for each event will mean you need to store the event and time. I am not sure how you “count every button press and report it via the cloud”. To maintain a record of EVERY button push with its timestamp, you would need to maintain a structure of event/time and the Core may not be the best place depending on the amount of data generated. You could publish each event with the timestamp or send it to a database on a server or a data collecting service (eg xliverly).

For the timestamp part, you can use millis() if you want differential time, ie. the time from the LAST button pressed. This is the simplest way to go though the differential needs to be an unsigned long (4 bytes) per entry. For absolute time, you can use the RTC library Time.GetUnixTime() function which returns the time in Unix Time format. The returned value is again an unsigned long.

@bko may have some great insights here :smile:

2 Likes

Hi @jkkim93

Every response you get from the cloud when reading a variable or receiving an event is already timestamped by the cloud. So one simple way would be to publish all the button presses as events. As long you don’t go over the rate limit of a burst of 4 and an average of one per second, that should work.

For an event:

event: Temperature
data: {"data":"90.725000","ttl":"60","published_at":"2014-06-18T13:40:25.449Z","coreid":"<<device id here>>"}

The “published_at” field is the time the event reached the cloud server, down to the millisecond.

As @peekay123 said, you can store the 32-bit Unix time stamp value on the core and send that with your data as well. This is just a count of seconds since Jan 1, 1970 so the difference between successive stored values would be the time seconds between button presses.

It would help us provide a better answer if we knew how many buttons per second and how accurately you need to time resolution.

Do you need more resolution than one per second?

2 Likes

Hi @bko Thanks for your input (I’ve been reading all your tutorials too!)
If I were to get the difference in time between two successive button presses, would I store the published_at into two separate variables and subtract the values (can you even do that or have to convert it into int format)?

Thanks to @peekay123 for starting the discussion!!!

1 Like

If you want to easily get the difference in seconds, you can subtract the new Time.GetUnixTime() from the stored timestamp.

Example (ignoring time zone offsets):
Let’s say I pressed the button at 2014-06-18 11:55:44 AM. The Unix time from Time.GetUnixTime() would be 1403106944. Then, I pressed the button again at 2014-06-18 11:59:06 which is 1403107146. If I subtract the old time from the new time (1403107146 - 1403106944), I come out with 202, which is the number of seconds elapsed between the button presses.

Hopefully, that’s a little bit clearer than mud!

Hi @jkkim93

If you go with the Spark.publish() way, then you will be doing the time differences on the web page side of things, not on the core. There is a Javascript Date object that can parse the time stamps for you and convert them to the Unix number-of-milliseconds format so they are easy to subtract. I have some code I could share if you go that way.

Either on the core or on the web page will work great!

@bko the parsing for easier subtraction would be something I’d be interested in looking into for my mini timestamp project to get the time differences between each consecutive stroke. If you could help me on that, that would be greatly appreciated!

And @wgbartley thanks for clearing some things up- it’s not so muddy now, and I appreciate your tutorials and example codes you have up as well!

Hi @jkkim93

The key is to use the parsed JSON in the event and make a new Javascript Date object. That object has a method getTime() that returns the number of milliseconds since Jan 1, 1970 which you can subtract.

Here’s some code to play with. Put this in an HTML file and launch it in your browser with the “file:///” type URL. Then enter your access token and a popular event like “Uptime” and click connect. You should see a table built from all the unique cores broadcasting that event, with the last column giving the difference between the success published events.

In your application you will want to change this for your cores and buttons, but I hope you will get started from this!

<!DOCTYPE HTML>
<html>
<body>
    <P>Event name:<input type="text" name="eventNameBox" id="evText" >
    <br><br>
    <P>Access Token:<input type="password" size="40" name="accessToken" id="accText" >
    <br><br>
    <table id="dataTable" width="500px" border="2">
      <tr>
    <td> Core ID </td>
    <td> Data </td>    
        <td> Timestamp </td>
    <td> milliseconds difference </td>
      </tr>
    </table>
    <br><br>
    <button id="connectbutton" onclick="start()">Connect</button>
 
    <script type="text/javascript">

    function start(objButton) {
        document.getElementById("connectbutton").innerHTML = "Running";
        var eventName = document.getElementById('evText').value;
        var accessToken = document.getElementById('accText').value;

    var requestURL = "https://api.spark.io/v1/events/?access_token=" + accessToken;

        var eventSource = new EventSource(requestURL);

        eventSource.addEventListener('open', function(e) {
            console.log("Opened!"); },false);
         
        eventSource.addEventListener('error', function(e) {
            console.log("Errored!"); },false);
         
        eventSource.addEventListener(eventName, function(e) {
            var parsedData = JSON.parse(e.data);
            var nowTime = new Date(parsedData.published_at);
        var dt = document.getElementById("dataTable");
            var rows = dt.rows.length;
        var foundIt = false;
        for(var i=0;i<rows;i++) {
          var rowN = dt.rows[i];
          if (false==foundIt  && rowN.cells[0].innerHTML==parsedData.coreid) {
        foundIt = true;
                var lastTime = new Date(rowN.cells[2].innerHTML);
        rowN.cells[1].innerHTML = parsedData.data;
        rowN.cells[2].innerHTML = parsedData.published_at;
                rowN.cells[3].innerHTML = nowTime.getTime() - lastTime.getTime();
          }
        }
        if (false == foundIt) {
          var newRow = dt.insertRow(rows);
              var cell1 = newRow.insertCell(0);
              var cell2 = newRow.insertCell(1);
              var cell3 = newRow.insertCell(2);  
              var cell4 = newRow.insertCell(3);         
          cell1.innerHTML = parsedData.coreid;
          cell2.innerHTML = parsedData.data;
          cell3.innerHTML = parsedData.published_at;
              cell4.innerHTML = 0;
        }

        }, false);
    }
    </script>
</body>
</html>
3 Likes

A good reference that I always use is W3Schools.com. The documentation is simple and easy to follow. They also have great examples that you can play around with. I’ve been doing web development for 15+ years (nearly half my life!), but I still reference their documentation frequently.

1 Like

Hi @jkkim93

Good question–this example will work any event you publish, you just put in the event name you are using in your core firmware to match.

For testing, try the event name “Uptime” which is a popular one based on the tutorials I wrote. You should see several come up–give it 60 seconds or so.

1 Like

Thanks @bko,
I see that the time is working on the html side, but if I wanted to transfer the number of button presses from the board (I have it stored as a int on the code) to the html to display it… any tips? Seems like a fairly simple variable callback that I keep tripping over. Right now I have what I want on the coding side all stored into ints that I’m just having trouble displaying/calling them back out on the html screen.

@bko, all the help you've been giving is awesome.
That being said, thought I should clarify more what I'm trying to do.
So on the coding side, I have the core counting button presses and storing it, and my goal was to timestamp the presses, get time differences between consecutive presses, and display it on the html output. The html side help you've give me is extremely helpful, and I'm still toying around with reading the presses into the code there.

const int strokeButton = 1;
const int blitz = 7;

int strokeCount = 0;
int stroke = 0;
int lastButtonState = 0;

void setup() {
pinMode(strokeButton, INPUT);
pinMode(blitz, OUTPUT);

Serial.begin(9600);
}

void loop() {

stroke = digitalRead(strokeButton);
if (strokeCount <= 10) {
if(stroke != lastButtonState) {
if(stroke == HIGH) {
strokeCount++;
digitalWrite(blitz, HIGH);

}
else {
  digitalWrite(blitz, LOW);
  Serial.print("you have taken ");
  Serial.print(strokeCount);
  Serial.println(" strokes");
}

}
lastButtonState = stroke;
}
else {
digitalWrite(blitz, HIGH);
delay(100);
}
}

I just hit a wall trying to incorporate my variables into your code (I get them separately but in connecting the two I'm having some trouble) wondering if you could help!!!! @bko

My html code just added a couple of lines to your's (I'm still not quite done wrapping my head around what exactly JSON reads and what I can call from the parsed data to get the variables I want)

Event name:

<table id="dataTable" width="500px" border="2">
  <tr>
<td> Core ID </td>
<td> Data </td>    
<td> Timestamp </td>
<td> milliseconds difference </td>
<td> number of presses </td>
<td> duration</td>
  </tr>
</table>
<br><br>
<button id="connectbutton" onclick="start()">Connect</button>
<script type="text/javascript">
function start(objButton) {
    document.getElementById("connectbutton").innerHTML = "Running";
    var eventName = document.getElementById('evText').value;
    var accessToken = "xxxxx";
var requestURL = "https://api.spark.io/v1/events/?access_token=" + accessToken;
    var eventSource = new EventSource(requestURL);
    eventSource.addEventListener('open', function(e) {
        console.log("Opened!"); },false);
    eventSource.addEventListener('error', function(e) {
        console.log("Errored!"); },false);
    eventSource.addEventListener(eventName, function(e) {
        var parsedData = JSON.parse(e.data);
        var nowTime = new Date(parsedData.published_at);
        var dt = document.getElementById("dataTable");
        var rows = dt.rows.length;
        var foundIt = false;
    for(var i=0;i<rows;i++) {
      var rowN = dt.rows[i];
      if (false==foundIt  && rowN.cells[0].innerHTML==parsedData.coreid) {
    foundIt = true;
            var lastTime = new Date(rowN.cells[2].innerHTML);
    rowN.cells[1].innerHTML = parsedData.data;
    rowN.cells[2].innerHTML = parsedData.published_at;
    rowN.cells[3].innerHTML = parsedData.result;
            rowN.cells[3].innerHTML = nowTime.getTime() - lastTime.getTime();
      }
    }
    if (false == foundIt) {
      var newRow = dt.insertRow(rows);
          var cell1 = newRow.insertCell(0);
          var cell2 = newRow.insertCell(1);
          var cell3 = newRow.insertCell(2);  
          var cell4 = newRow.insertCell(3);         
      cell1.innerHTML = parsedData.coreid;
      cell2.innerHTML = parsedData.data;
      cell3.innerHTML = parsedData.published_at;
      cell4.innerHTML = parasedData.result;
    }
    }, false);
}
</script>

From this, I'm trying to read from my spark code

const int strokeButton = 1;
const int blitz = 7;
unsigned int currentHour;
unsigned int currentMin;
unsigned int currentSec;
unsigned long lastTime = 0UL;
char publishString[40];

int strokeCount = 0;
int stroke = 0;
int lastButtonState = 0;

void setup() {
pinMode(strokeButton, INPUT);
pinMode(blitz, OUTPUT);

Serial.begin(9600);

Spark.variable("strokecount", &publishString, STRING);
}

void loop() {

stroke = digitalRead(strokeButton);
if (strokeCount <= 10) {
if(stroke != lastButtonState) {
if(stroke == HIGH) {
strokeCount++;
digitalWrite(blitz, HIGH);

}
else {
  digitalWrite(blitz, LOW);
  Serial.print("you have taken ");
  Serial.print(strokeCount);
  Serial.println(" strokes");
}

}
lastButtonState = stroke;
}
else {
digitalWrite(blitz, HIGH);
delay(1000);
strokeCount = 0;
}
sprintf(publishString, "%u", strokeCount);
Spark.publish("strokeCount", publishString);
}

The passing of publishString isn't quite working out and I think it largely has to do with the fact that I'm not calling the right things or parsing the right things in- any help would be tremendously appreciated!!! (reaching the point of frustration here haha......)

Which browser are you using? If you’re using Chrome or FireFox, you can add some debug code to your JavaScript to see if you’re getting what you think you should be getting. Try adding a console.log(e); just under your eventSource.addEventListener(....

eventSource.addEventListener(eventName, function(e) {
	console.log(e);

This will show you the full data published to the Spark.publish() stream that you’re monitoring. If all looks good using console.log(e), you can delete that line and then try doing console.log(parsedData); just under the line that starts with var parsedData = ....

If you’re on Windows, you can press Ctrl+Shift+J to bring up the JavaScript developer console. In Chrome, you can go to Tools → JavaScript console. In Firefox, you can go to Web Developer → Browser Console. I don’t know about other browsers off the top of my head.

After all that, update your resume and add web development as one of your qualifications. :wink:

2 Likes

The event name needs to match what you put into the Spark.publish() command, in your case, "strokeCount", so change the line above to:

var eventName = "strokeCount";

I looked at the public event stream for a while but I didn't see any strokeCount events go by.

1 Like

I’m wondering if parsedData.results and parsedData.data is different. In debugging, I made a html output to read just the variable strokecount and that works fine- but having trouble putting that into the table code. I think the problem is with my parsing. Is there a way to know what exactly JSON is parsing out? specifically in this case, data vs results.
And for calling event functions, is there a different there between calling the function (and getting it from spark.publish) vs reading off a variable besides one on call and one updating regularly?
(asking the basics here bc updating the eventname to strokeCount still isn’t giving me an output, so I thought it was syntax problems)

Thank you so much!!!

quick Q: when I try getting the time difference on the code side (not using html), I'm having trouble getting the code to compile... Thanks for your help!!!!!!!

error: 'class TimeClass' has no member named 'GetUnixTime'

@jkkim93, the correct function is Get_UnixTime() :wink:

1 Like

If you use the console.log(...) example I posted above, it will print out the JSON object that is (mostly) human friendly.

There are a bunch of technical differences, but I think in your particular use case, the only difference is on-demand updates versus regular update intervals.