HTTP Data Node: URL params and payload parsing SOLVED

#1

Hi all,
I’m using Workflow to fetch data from Google Calendar. The API specify OAuth authentication but before to go into this part I’m playing a little with other easy part like “event requests”. Google API specify that this can be done by placing an GET request like this example:

https://www.googleapis.com/calendar/v3/calendars/agarciaibct%40gmail.com/events?orderBy=startTime&singleEvents=true&timeMin=2016-06-05T00%3A00%3A00-02%3A00

Here you can see that some url parts and params like mail and “timeMin” will change over time, specially “timeMin”. So, how can I handle this param as a template ?, The idea is to automate this parameter to build request with the current date and a previous calculated time for each timed request.

The second question is about processing the typical payload coming from these kinds of requests:

{
  "kind": "calendar#events",
  "etag": "\"1465123213122000\"",
  "summary": "Mi Sala",
  "description": "Espacio para eventos académicos con aforo para 235 personas.",
  "updated": "2016-06-05T19:56:35.852Z",
  "timeZone": "Europe/Madrid",
  "accessRole": "owner",
  "defaultReminders": [
    {
      "method": "popup",
      "minutes": 10
    }
  ],
  "items": [
    {
      "kind": "calendar#event",
      "etag": "\"2930310513466000\"",
      "id": "lk2vfsvexxxxxxmb5v0us",
      "status": "confirmed",
      "htmlLink": "https://www.google.com/calendar/event?eid=bGsyxxxxRAbQ",
      "created": "2016-06-05T11:32:39.000Z",
      "updated": "2016-06-05T19:34:16.733Z",
      "summary": "LOSANT Test1",
      "creator": {
        "email": "agarciaibct@gmail.com",
        "displayName": "Andrés García",
        "self": true
      },
      "organizer": {
        "email": "agarciaibct@gmail.com",
        "displayName": "Andrés García",
        "self": true
      },
      "start": {
        "dateTime": "2016-06-05T19:00:00+02:00"
      },
      "end": {
        "dateTime": "2016-06-05T20:00:00+02:00"
      },
      "iCalUID": "lk2vxx0us@google.com",
      "sequence": 1,
      "reminders": {
        "useDefault": true
      }
    },
    {
      "kind": "calendar#event",
      "etag": "\"2930313191240000\"",
      "id": "nuxxxnpk",
      "status": "confirmed",
      "htmlLink": "https://www.google.com/calendar/event?eid=bnVoNTxxxxxxRAbQ",
      "created": "2016-06-05T19:34:31.000Z",
      "updated": "2016-06-05T19:56:35.620Z",
      "summary": "LOSANT Test2",
      "creator": {
        "email": "agarciaibct@gmail.com",
        "displayName": "Andrés García",
        "self": true
      },
      "organizer": {
        "email": "agarciaibct@gmail.com",
        "displayName": "Andrés García",
        "self": true
      },
      "start": {
        "dateTime": "2016-06-05T22:00:00+02:00"
      },
      "end": {
        "dateTime": "2016-06-05T23:00:00+02:00"
      },
      "iCalUID": "nuhxcsnpk@google.com",
      "sequence": 0,
      "reminders": {
        "useDefault": true
      }
    }
  ]
}

Here we can see two events, I mean two items[ ]. This payloads have an undetermined number of items[n] so in order to build an STATE for a device, it will be something like {{Events.body.items[n].summary}} for Summary on each event. So again, How can I handle this issue and store the “n” events ? … probably I can write some function logic base on javascript to parse all the payload??

thanks in advance for your suggestions.

#2

The URI field does support template values, so you would replace your GET URI with something like this:

...&timeMin={{ timeMin }}

timeMin would then have to be on your payload. I’m not sure how you’re calculating timeMin, but an easy approach would be to use a function node before the HTTP node. In the function node you would then set payload.timeMin to your desired value.

Currently you’ll have to use a function node to parse a response like that. We are working on concepts for easily working with array data, but for now, it will require a function node.

#3

Yes, the Function node is really powerful.
When Yahoo Pipes was around, it has a Loop node which allows processing every element in an array; you can drag another node (such as a Math node) into the Loop node to define what should be done to each element. Losant currently lacks a Loop node.

#4

Many thanks. Two things solved. Now I’m calculating the {{ timeMin }} by a payload provided by a prior function. would be nice a UTC time data node in the future. Regarding the items parse, is really simple to deploy from a javascript function like this:

if(payload.Events) {

var t = new Date();
payload.Events.body.Time = t;
payload.Events.body.Total = payload.Events.body.items.length;

var evento_start = new Date();
var evento_end = new Date();

var nombre = “”;
var autor = “”;

for(var i = 0; i < payload.Events.body.items.length; i++){
evento_start = new Date(payload.Events.body.items[i].start.dateTime);
evento_end = new Date(payload.Events.body.items[i].end.dateTime);

if(t > evento_start & t < evento_end){
payload.Events.body.Count = i;
nombre = payload.Events.body.items[i].summary;
autor = payload.Events.body.items[i].creator.email;
payload.Events.body.EventoStart = evento_start;
payload.Events.body.EventoEnd = evento_end;
payload.Events.body.Dentro = “Dentro”;

  return { Time: t, Count: i, Estado: "Dentro", Nombre: nombre, Autor: autor, Start: evento_start, End: evento_end};

}
else
if(t < evento_start){
payload.Events.body.Count = i;
nombre = payload.Events.body.items[i].summary;
autor = payload.Events.body.items[i].creator.email;
payload.Events.body.EventoStart = evento_start;
payload.Events.body.EventoEnd = evento_end;
payload.Events.body.Dentro = “Proximo”;

     return { Time: t, Count: i, Estado: "Proximo", Nombre: nombre, Autor: autor, Start: evento_start, End: evento_end};
  }else
     payload.Events.body.Dentro = "Todos Fuera";

}
}
return { Time: t, Count: payload.Events.body.items.length };

Now this function is providing me a payload with useful information about the status events into the calendar, I mean if we are into an event or not and information about the incoming event.

Now the next steps are about OAuth authentication, which is very useful on many services that require authentications prior to connect. I have some questions on this but I’ll open a different topic.

https://forums.losant.com/t/oauth-authentication-workflow/181?u=andres_garcia