Spark.function not being called

I have a Core and Relay Shield. Trying to call a function on device but not working. I stripped all the logic out so it should simply turn off a relay that is initialized on. But, The relay comes on and stays on. What am I missing? Where is the return value coming from?
The HTML runs fine and get this result when the button is pressed.

Thanks,

Data Loaded: {“id”:“123456789098765432112334”,“name”:“liftassist”,“last_app”:null,“connected”:true,“return_value”:536891216}

Here are all the components…
HTML CODE: ( with fake core id and token)
(Had to remove left angle bracket to get HTML tags to print)

<!DOCTYPE html>
html>
header>

script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">/script>
script>
var baseURL = "https://api.spark.io/v1/devices/";
var accessToken = "1234567890987654321234456678890998777";
       var coreID = "123456789098765432112334";
       var method = "pool";
       var url = baseURL + coreID + "/" + method;       

function start() {

$.post(url,
   {

   access_token: accessToken,
             params: "High" })

  .done(function( data ) {
alert( "Data Loaded: " + JSON.stringify(data) );
});

}
/script>

/header>
body>

button type="button" onclick="start()">Pool Light Switch</button>

/body>
/html>

SPARK CORE CODE:

int RELAY1 = D0;
void setup()
{
   //Initialize the relay control pins as output
   pinMode(RELAY1, OUTPUT);
   
      // Initialize all relays to an ON state
   digitalWrite(RELAY1, HIGH);
   
   
   //register the Spark function
  Spark.function("pool", poolControl);
}
void loop()
{
   // This loops for ever
 
 
}
int poolControl(String command)
{

  digitalWrite(RELAY1, LOW);
  
  return 1;
}

Sent from my iPad

Hi @Cretcheu,

Hmm, your jquery looks essentially right to me, here’s a snippet for calling a function

$.post("https://api.spark.io/v1/devices/" + yourDeviceID + "/" + yourFunctionName, {access_token: yourAccessToken, arg: v});

I’m guessing your code isn’t loaded on your core. Can you do a spark list with the CLI, or can you hit https://api.spark.io/v1/devices/your_core_id and confirm that your function is present?

Thanks,
David

The return value comes from the return statement at the end of the Spark function you wrote in your Spark firmware. In this case it should be 1. I like to make it something unique but identifiable easily like 200. It seems like it's talking to your Core, but you have some OTHER code in there that's not returning 1. If that function key "pool" wasn't available it should return something like this:

{
  "ok": false,
  "error": "Function not found"
}
2 Likes

David,
I don’t understand what you are asking me to do.
I did this and got a 400 error token was not found. I do not have CLI installed.

https://api.spark.io/v1/devices/your_core_id

If I flash the Core with code that does not have the “pool” function I get an " ok false" response. When I flash the pool code the relay is coming on and staying on. Pressing the button gives me the “data loaded” message but does not turn the relay off.

I think you are both correct that Flash is not working properly. Is there a way to reset the core to wipe out old code?

I have re flashed a least a half dozen times.

Thanks,

Peter

By “reflashing”, do you mean ‘trying to upload the firmware over and over again using the web IDE’? If that’s the case, you could try a factory reset, which might help.

1 Like

Ok I finally got this working… had a tough time actually getting it programmed from the Web IDE which is most likely most of your problem. If you leave the code as-is, you’ll know it successfully programs if the D7 led will light up blue. Try this code:

<!DOCTYPE html>
<html>
<header>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

  <script>
    var baseURL = "https://api.spark.io/v1/devices/";
    var accessToken = "12341234123412341234123412341234";
    var coreID = "1234123412341234";
    var method = "pool";
    var url = baseURL + coreID + "/" + method;       
    
    function startMe() {
      $.post(url, {
        access_token: accessToken,
              params: "High" })
        .done( function( data ) {
          alert( "Data Loaded: " + JSON.stringify(data) );
        });
    }
  </script>
</header>

<body>
  <button type="button" onclick="startMe()">Pool Light Switch</button>
</body>
</html>

And the code for the Core… in this case it’s turning on the D7 led and turning it off by function call. Change D7 to D0 for your relay, or just leave it the way it is for a known working test of the LED.

#define MYPIN D7

void setup() {
  pinMode(MYPIN, OUTPUT);
  digitalWrite(MYPIN, HIGH);
  Spark.function("pool", poolFunction);
}

void loop(){
    
}

int poolFunction(String command) {
  digitalWrite(MYPIN, LOW);
  return 200;
}

1 Like

BTW @Dave I think you’ll find this interesting… the original code posted will NOT program for me OTA even with the bug-fix/ota-flash-reliability firmware that’s known to be working flashed to the Core prior to the update.

I’ve narrowed it down to something quite perplexing… if I change the first line of code from

int RELAY1 = D0;

to

#define RELAY1 D0

it flashes just fine.

In either case the code compiles just fine and it hangs at some point near the middle to end of the flashing process usually for the original int definition. This is one of those cases where a debugger on the Core would be handy… if it’s failing at exactly the same spot in the code transfer each time, then there’s something unique about this code that breaks the OTA process.

It also fails if I add this to the top of the file:

#pragma SPARK_NO_PREPROCESSOR

#include "application.h"

int poolControl(String command);

Also if I program it locally with the original int definition it flashes fine and the application works as expected.


BTW, the code specifically that I used in my Core was Satish’s spark-common-lib bug-fix/ota-flash-reliability branch only, master for the other two. I tested this code this morning and it passed 38 out of 38 times with the dual curl command script, so I know the OTA process is known-good at this location, and on this specific Core.

Heya @BDub,

Hmm, that’s super weird. Any chance you could send me that binary that causes it to fail?

Thanks,
David

Well I’m actually just clicking the Flash button in the Web IDE. You should be able to replicate it by just trying to flash this code from the web IDE. I haven’t tried to compile the code from the CLI through the Cloud. Every time it failed to re-flash OTA, I made sure to reprogram my Core locally with the OTA fix code… just to be sure I was starting with something that should work.

int RELAY1 = D0;
void setup()
{
    //Initialize the relay control pins as output
   pinMode(RELAY1, OUTPUT);

      // Initialize all relays to an ON state
   digitalWrite(RELAY1, HIGH);


   //register the Spark function
  Spark.function("pool", poolControl);
}
void loop()
{
    
}

int poolControl(String command)
{
  digitalWrite(RELAY1, LOW);

  return 1;
}

BDub/Dave,

Confirmed. All I had to do was change the int RELAY1 = D0; to #define RELAY1 D0 and it flashed and works correctly.

My problem is I don’t know what I don’t know and was just copying from examples…

Thanks all.

1 Like

Hey @BDub,

That is a weird, and awesome bug! :smiley: (Yay reproducible test cases!). Based on that firmware, I created two binaries, one is only 8 bytes bigger than the other, and one always fails OTA right as the bootloader is switching to copy the external flash back into the stm32. Cool.

Thanks!
David

1 Like

@Dave BTW I did successfully just reproduce it via CLI as well… here are the two source files with binaries appropriately labeled:

OTA-FAILS
https://dl.dropboxusercontent.com/u/41117656/OTA-FAILS.zip

OTA-PASSES
https://dl.dropboxusercontent.com/u/41117656/OTA-PASSES.zip

If you have CLI and want to follow along, just unzip the source file to a folder named OTA (it’s already this way in the zip file), then while in the directory above the one named OTA run this command:

spark flash YOUR_CORE_ID OTA

You can also create the Binary like this:

spark compile OTA --saveTo firmware.bin

1 Like

@Dave if I add one byte of RAM to the OTA FAILS code, the flash size doesn’t change and it still fails, but if I add one command to update the value of that byte in the setup() function the flash size is now 16 bytes larger (which seems like a lot of bytes for this operation) but it will now re-flash OTA.

int RELAY1 = D7;
uint8_t temp1 = 0;
void setup()
{
   temp1 = 1;

   //...   
}

So it seems like there is some issue with flash size, perhaps it’s hitting a page boundary in just the wrong way that the routine is silently failing. I haven’t tried looking at the debug output yet, but hopefully this gets us going in the right direction.

I have to knock out some other stuff now but I’ll check back tonight ! :smile:

2 Likes

my work around from when i first noticed the bug… add some useless code or comment out a useless line… worked every time!

@Dave @BDub fits exactly with what i was seeing a while back, if you need some similar code that does the same thing there is a link on the bug bounty post… there are libraries etc so its much bigger but it may help define another fail point to work out what sizes make it stop.

Glad your getting closer to nailing the problem

2 Likes