Cloud Event To Photon/Electron?

Follow-up Question:

From the example, exposing a function with Particle.function is a way to send a integer value to the photon/electron from Web POST.

Does this chew up data between the cloud and the photon or electron, or is it event/interrupt driven?

Example from the documentation:
https://api.particle.io/v1/devices/0123456789abcdef/brew \ -d access_token=123412341234 \ -d “args=coffee”

Any and all remote internet based actions, be it from the device to the cloud or otherwise will consume data. How else would you communicate with it via the cloud? The alternative is to send it a text, using a non-Particle SIM, but that’s more expensive, so I wouldn’t recommend that.

It does “chew up” data but it should be a fairly small amount of data and you’d only be sending it whenever you want GPS coordinates.

So, the amount of data it would send would be less than sending GPS long/lat once every hour?

That would depend. If you are only requesting lat/long on demand then it would depend on how often you are requesting GPS data. What is your use case?

The GPS data would only be demanded if lost/stolen, someone didn’t come back to the boat/meeting place on time or to test to make sure everything is working. it would send/publish data in the following format GMT Time, Date, Long, Lat. (about 45 characters).

07:00.00,11072016,+29 38.1207’,-095 46.3992’

I have the following code, however, when I try to trigger the “find” Particle.function(); using the following URL

(device ID and access token have been shorten). I’ve verified my access token to be correct, so I’m thinking my URL isn’t correct.

https://api.spark.io/v1/devices/4f004/find?access_token=1fa33?args=doh"

I get back the following:

{
“error”: “invalid_token”,
“error_description”: “The access token provided is invalid.”
}

int val = LOW;

void setup() 
{
  pinMode(D1,OUTPUT);
  digitalWrite(D1,LOW);
  Particle.function("find", pubGPS);
}

void loop()
{
   val = digitalRead(D1);
   if (val == HIGH)
     {
        Particle.publish("Location","+28 38.5417,-81 56.3664");
         delay(1000);
         digitalWrite(D1,LOW);
     }
}
    
int pubGPS(String command)
    {
      if(command == "doh")
      {
        digitalWrite(D1, HIGH);
        return 1;
      }
      else return -1;
    }

For a function call you’d need a POST request, rather than the GET request your browser is making. If you want to just test for functionality, you could try this page to test the functions easily: http://jordymoors.nl/interface
If you want to learn how to do it yourself, go with this:
Tutorial: Spark Variable and Function on One Web Page

Or using the JS library perhaps this one:

2 Likes

Thanks for the tips. I’ve now decided to move away from the Particle.publish() and Particle.function() approaches. I found Particle.variable() works much better and less overhead for me. The only problem I have now is how to parse what is coming back from the URL. The HTML I have below, won’t do a post (pressing the get! button) returns a 401 unauthorized error in the console. This appears due to the fact that the access_token is not making its way to the GET request. I’m fairly certain, I’m missing something and I hope you can point me in the right direction. I’m fairly certain the access_token being null is my problem. I’m just not sure where to add it. Any help would be greatly appreciated.

https://api.particle.io/v1/devices/4f004/lonlat?access_token=1fa3 (shorten to protect the deviceID and tokenID)

The URL below returns

{
“cmd”: “VarReturn”,
“name”: “lonlat”,
“result”: “+29 38.1126’,-095 46.3988’”,
“coreInfo”: {
“last_app”: “”,
“last_heard”: “2016-07-11T20:22:41.957Z”,
“connected”: true,
“last_handshake_at”: “2016-07-11T17:49:28.164Z”,
“deviceID”: “4f004”,
“product_id”: 10
}
}

<html>
   <head>
     <title>GPS Dashboard</title>
   </head>
   <body>
     <td>
       <div class="input-group input-group-sm">
   	      <span class="input-group-btn">
   	        <input type="text" class="form-control" placeholder="Click Get!" readonly="" id="lonlat4f004">
            <button class="btn btn-default" type="button" onclick="update('4f004', 'lonlat')">Get!</button>
          </span>
        </div>
     </td>
   </body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="http://cdn.jsdelivr.net/sparkjs/1.0.0/spark.min.js" type="text/javascript" charset="utf-8"></script>
<script>
	var deviceId = "4f004";
	var access_token = "1fa3";
	
	function execute(deviceId, func) {
		argument = document.getElementById(func + 'input'); 
		spark.callFunction(deviceId,func,argument.value,null);
		argument.value = "";
	};
	
	function update(deviceId, variable) {
		spark.getVariable(deviceId,variable,function(err, data){
			console.log(data);
			variableValue = document.getElementById(variable + deviceId);
			variableValue.value = data.result;
		});
	};
</script>   
</html>

Hmm, it seems as though you’re still using the old spark JS library which has since been superseded by the Particle API library. If at all possible, do consider switching. If that’s not possible, then you can check these old docs. You’re missing a login in there (you can use an accesstoken or regular credentials for that). https://github.com/spark/sparkjs/blob/master/examples/node/get-variable.js

I used your code from http://jordymoors.nl/interface/ page, so I’m fairly certain it works. When I login to your page, I get what is shown in the screenshot below.

The URL works, it gives me the data back that I need, but I suspect to do it properly, I will need to execute it from within an HTML document and then capture what comes back for it work like your code below does. If I need to change the JS lib, I have no problem doing that, I was just going with what worked on your page. Also do I have to login if I use both the deviceID and Access_Token?

https://api.particle.io/v1/devices/4f004/lonlat?access_token=1fa33 (shorten to preserve the actual deviceID and
Access Token)

That’s the important clue.
The login procedure requests an access token which will then be used for the next page.
So in order to have your own page do the same, you need to go through the login process just the same.

1 Like

If I use this URL (shorten to hid the full deviceID and access_token) and I’m not logged in, I get the results that follows the URL listed below. If I use both do I need to login?

https://api.particle.io/v1/devices/4f0043/lonlat?access_token=1fa334

Results:

{
“cmd”: “VarReturn”,
“name”: “lonlat”,
“result”: “+29 38.1213’,-095 46.4118’”,
“coreInfo”: {
“last_app”: “”,
“last_heard”: “2016-07-12T13:55:28.958Z”,
“connected”: true,
“last_handshake_at”: “2016-07-11T17:49:28.164Z”,
“deviceID”: “4f004”,
“product_id”: 10
}
}

You need to log in in order to acquire the access token rather than hard coding it.

Understood, but if I know what it is, can’t I just pass it and process the results?

It kinda depends on which library you’re using. The old JS library (the code above, and on my interface) requires you to log in with either credentials or an accesstoken. It’s a requirement for the library to somehow internally store the accesstoken for further use. The new library however allows you to log in using your credentials only after which it gets an accesstoken that it stores/uses in the ‘user code’. Thus, if you know the accesstoken, you can skip the logging in step and just use the accesstoken as-is.

So, if you’re not going to use either library, then just use that fixed URL and handle the data any way you’d like. If you do intent on using a JS library, there are two options:

  1. use the old library -> log in, using the accesstoken or regular credentials.
  2. use the new library -> use an accesstoken directly, or acquire one by logging in with regular credentials.
2 Likes

By using the new lib, will I be able to parse the returned values?

Would be kinda useless if you couldn’t, right…?
https://docs.particle.io/reference/javascript/#getvariable

Yes, it would, but I’ve made wrong assumptions before. :grinning:

I’m still working on getting the latest particle lib to work, but the this spark code works. Many thanks to everyone that helped me get on the right path!

<!DOCTYPE HTML>
<html>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<body>
    <span id="temp"></span><br>
    <span id="tstamp"></span><br>

    <button id="connectbutton" onclick="start()">Get Location</button>

    <script type="text/javascript">

    function start(objButton) {

        document.getElementById("temp").innerHTML = "Waiting for data...";
        document.getElementById("tstamp").innerHTML ="";
        var deviceID = "4f004";
        var accessToken = "1fa3";
        var varName = "lonlat";

        requestURL = "https://api.spark.io/v1/devices/" + deviceID + "/" + varName + "/?access_token=" + accessToken;
        $.getJSON(requestURL, function(json) {
                 document.getElementById("temp").innerHTML = "Current GPS Location -> " + json.result;
                 // document.getElementById("temp").style.fontSize = "28px";
                 document.getElementById("tstamp").innerHTML = "Date/Time          -> " + json.coreInfo.last_heard;
                 });
    }
    </script>
</body>
</html>
2 Likes

Just wanted to update the code, in case it will help anyone else. This code isn’t optimized and I apologize for its sloppy nature. I’ll clean it up later.

This page will load and automatically run the java start() function. I’ve shorten the actual deviceID and Access_Token codes, but otherwise this is the code that is currently working. Thanks again for everyone’s help!

<html>
  <head>
    <title>Current Location</title>
    <meta name="viewport" content="initial-scale=1.0">
    <meta charset="utf-8">
    <style>
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
      #map {
        height: 100%;
      }
    </style>
  </head>
  <body onload= "start()">
  	<span id="temp"></span><br>
    <span id="tstamp"></span><br>
     <div id="map"></div>
    <div id="capture"></div>
    <script>
      var map;
      function initMap() {
        map = new google.maps.Map(document.getElementById('map'), {
          center: {lat: 39.833, lng: -98.585},
          zoom: 8
        });
      }
      
function ConvertDMSToDD(days, minutes, seconds, direction) {
    var dx = minutes + "." + seconds;
    var dl = (Number(dx)/60);
    var dd = Number(days) + dl;
    dd = parseFloat(dd);
    if (direction == "S" || direction == "W") {
        dd = dd * -1;
    } // Don't do anything for N or E
    return dd;
}
      
 function doh(str) {
 
        var res = str.replace("'","");
        str = res;
        res = str.replace("'","");
        str = res;
        var constr = str.split(",");
        var latstr = constr[0].replace(" ",".");;
        var longstr = constr[1].replace(" ",".");
        var latdir = latstr.charAt(0);
        var longdir = longstr.charAt(0);
        res = latstr.replace("+","");
        latstr = res;
        res = longstr.replace("-","");
        longtr = res;
        res = longstr.replace("+","");
        longstr = res;
        res = longstr.replace("-","");
        longstr = res;
        if (latdir == "+")
          {
            latdir = "N";
          }
        else
        	{
          	latdir = "S";
          }
        if (longdir == "-")
          {
            longdir = "W";
          }
        else
        	{
          	longdir = "E";
          }
        var latpart = latstr.split(".");
        var longpart = longstr.split(".");
        console.log(latstr);
        console.log(latpart[0])
        console.log(latpart[1])
        console.log(latpart[2]);
        console.log(latdir);
        console.log(longstr);
        console.log(longpart[0]);
        console.log(longpart[1]);
        console.log(longpart[2]);
        console.log(longdir);
        var lat = ConvertDMSToDD(latpart[0],latpart[1],latpart[2],latdir);
        console.log(lat);
        var long = ConvertDMSToDD(longpart[0],longpart[1],longpart[2],longdir);
        console.log(long);
        marker = new google.maps.Marker({position: new google.maps.LatLng( lat,long),map: map});
        var laLatLng = new google.maps.LatLng( lat, long);
        map.panTo(laLatLng);
        
 }

function start() {

        document.getElementById("temp").innerHTML = "Waiting for data...";
        document.getElementById("tstamp").innerHTML ="";
        var deviceID = "4f004";
        var accessToken = "1fa3342";
        var varName = "lonlat";

        requestURL = "https://api.spark.io/v1/devices/" + deviceID + "/" + varName + "/?access_token=" + accessToken;
        $.getJSON(requestURL, function(json) {
                 document.getElementById("temp").innerHTML = "Current GPS Location -> " + json.result;
                 jstr = json.result;
                 // document.getElementById("temp").style.fontSize = "28px";
                 document.getElementById("tstamp").innerHTML = "Date/Time          -> " + json.coreInfo.last_heard;
                 console.log(jstr);
                 console.log('calling DOH');
                 doh(jstr);
                 });
    }
    </script>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript" charset="utf-8"> </script>
    <script src="https://maps.googleapis.com/maps/api/js?key=<<Your Google API Key Here>>&callback=initMap"
    async defer></script>
  </body>
</html>