Can't read Photon firmware variable from iPhone app (with IOS Cloud SDK)

Photon firmware has double variable.
I can read it from CLI particle get OK.
But from example app of IOS Clos SDK, modified for my variable, nothing seems to happen when I call [myPhoton getVariable …
…the ‘completion:’ doesn’t seem to fire.

I run on iPhone6+, and do the example app’s “Login” ok and then “Test sequence”.

Here’s the FW code and the iOS code:

IOS…

 	printf("\n	   reading a variable" );
   [myPhoton getVariable:@"button_press" completion:^(id result, NSError *error) {
        if (!error)
        {
            NSNumber*  button_press = (NSNumber*  )result;
            NSLog(@"button_press is #%f ",button_press.doubleValue);
        }
        else
        {
            NSLog(@"Failed reading button_press from Photon device");
        }
    }];

FIRMWARE…

#include "InternetButton/InternetButton.h"

/* How about we make this interactive? */

InternetButton b = InternetButton();

double button_press = 0;     // none

void setup() {
    // Tell b to get everything ready to go
    // Use b.begin(1); if you have the original SparkButton, which does not have a buzzer or a plastic enclosure
    // to use, just add a '1' between the parentheses in the code below.
    b.begin();
    b.setBrightness(50);
    
      Serial.begin(9600);
      Serial.println("Hello World!  2016-08-19a");
}

void loop(){
   
 
    // When you click the second button (at the 3 o'clock position) let's turn that LED on
    if(b.buttonOn(1))
    {
        button_press = 1;
          Particle.variable( "button_press", button_press );
      b.ledOn(1, 255, 0, 0);
        b.ledOn(11, 255, 0, 0);
       Serial.println("button_press = 1");
   }
    else if(b.buttonOn( 2 ))
    {
        button_press = 2;
          Particle.variable( "button_press", button_press );
      b.ledOn(2, 0, 255, 0);
        b.ledOn(3, 0, 255, 0);
        b.ledOn(4, 0, 255, 0);
       Serial.println("button_press = 2");
    }
    else if(b.buttonOn(3))
    {
        button_press = 3;
          Particle.variable( "button_press", button_press );
      b.ledOn(5, 0, 0, 255);
        b.ledOn(6, 0, 0, 255);
        b.ledOn(7, 0, 0, 255);
       Serial.println("button_press = 3");
    }
    else if(b.buttonOn( 4 ))
    {
        button_press = 4;
        Particle.variable( "button_press", button_press );
        b.ledOn(8, 255, 255, 0);
        b.ledOn(9, 255, 255, 0);
        b.ledOn(10, 255, 255, 0);
        Serial.println("button_press = 4");
   }
    // And if the button's not on, then the LED should be off
    else {
        button_press = 0;
        Particle.variable( "button_press", button_press );
        b.ledOff(1);
        b.ledOff(2);
        b.ledOff(3);
        b.ledOff(4);
        b.ledOff(5);
        b.ledOff(6);
        b.ledOff(7);
        b.ledOff(8);
        b.ledOff(9);
        b.ledOff(10);
        b.ledOff(11);
    }
    


    /* Much like the LEDs, there are also functions to check if all the buttons are on- b.allButtonsOn()
    or if all the buttons are off- b.allButtonsOff() */
}

What exactly does happen? Anything? Since you said that it seems like the completion code isn't running, I assume that your NSLogs aren't printing out. Have you verified that myPhoton is not nil?

Is there a build.particle.io library for Photon firmware that matches (works with) the example app in the IOS Cloud SDK?

I’m having trouble getting the IOS Cloud SDK to read a variable in my app on my Internet Button Photon.

Sorry that I have to remind you if the docs as well.
The way you are using Particle.variable() is not how you do it.

Particle.variable() is only called once in setup() to expose a global variable to the cloud and is not used to push the value of the variable to the cloud.

1 Like

Ric:
After calling getDevices, myPhoton = 0, so getVariables fails.
However, according to my logs, getDevices doesn’t seem to run until after testButton() returns.
What causes that?? I have made no changes to the example app, other than my login info.

ScruffR: Correction made; Particle.variable() now only called once, in setup.

Code and output follow…

- (IBAction)testButton:(id)sender {
    // logging in
	printf("\n >>>>>>   %s...", __FUNCTION__ );

	///////////////////////    C O N N E C T   W I T H   C L O U D   //////////////////////

	printf("\n	   loginWithUser" );
    [[SparkCloud sharedInstance] loginWithUser:TEST_USER password:TEST_PASS completion:^(NSError *error) {
 		printf("\n	   loginWithUser" );
       if (!error)
            NSLog(@"Logged in to cloud");
        else
            NSLog(@"Wrong credentials or no internet connectivity, please try again");
    }];
    
    // get specific device by name:
    __block SparkDevice *myPhoton;

	/////////////////////  D E T E R M I N E   O N L I N E   D E V I C E S   /////////////////////
    
	printf("\n	   get specific device by name:\n" );
    [[SparkCloud sharedInstance] getDevices:^(NSArray *sparkDevices, NSError *error) {
 		printf("\n	   get specific device by name:\n" );
       NSLog(@"%@",sparkDevices.description); // print all devices claimed to user
      
        // search for a specific device by name
        for (SparkDevice *device in sparkDevices)
        {
			if ([device.name isEqualToString:@"IB_A"])		// one of my Internet Button Photon's
			{
                myPhoton = device;
                NSLog(@"\n	device.name %@    FOUND		myPhoton=%x \n", device.name, myPhoton );
			}
			else
			{
                NSLog(@"\n	device.name %@    NOT FOUND \n", device.name );
			}
        }
    }];

	////////////////////////   R E A D   D E V I C E   B U T T O N   ///////////////////////
    
    // reading a variable
 	printf("\n	   reading a variable" );
   [myPhoton getVariable:@"button_press" completion:^(id result, NSError *error) {
 		printf("\n	   reading a variable" );
        if (!error)
        {
            NSNumber*  button_press = (NSNumber*  )result;
            NSLog(@"button_press is #%f ",button_press.doubleValue);
        }
        else
        {
            NSLog(@"Failed reading button_press from Photon device");
        }
    }];


    
    

    // logout
    [[SparkCloud sharedInstance] logout];
    
	printf("\n <<<<<<   %s done.\n\n", __FUNCTION__ );

return;

===========================================================
OUTPUT:

">>>>>>"   -[SparkViewController testButton:]...
	   loginWithUser
	   get specific device by name:

	   reading a variable
 "<<<<<<"   -[SparkViewController testButton:] done.


	   loginWithUser2016-08-20 06:15:33.257 AudMan1 x2[2710:942837] Logged in to cloud

	   get specific device by name:
2016-08-20 06:15:33.740 AudMan1 x2[2710:942837] (
    "<SparkDevice 0x12f696e00, type: Photon, id: 280032000947353138383138, name: IB-B, connected: false, variables: {\n}, functions: (\n), version: (null), requires update: false, last app: (null), last heard: 2016-08-11 00:43:46 +0000>",
    "<SparkDevice 0x12f699a20, type: Photon, id: 32001b000747353138383138, name: IB_A, connected: true, variables: {\n    \"button_press\" = double;\n}, functions: (\n), version: (null), requires update: false, last app: (null), last heard: 2016-08-20 13:15:19 +0000>"
)
2016-08-20 06:15:33.740 AudMan1 x2[2710:942837] 
	device.name IB-B    NOT FOUND 
2016-08-20 06:15:33.741 AudMan1 x2[2710:942837] 
	device.name IB_A    FOUND		myPhoton=2f699a20

So, I worked around the problem in the testButton() by moving the getVariable{} snippet into within getDevices{} where myPhoton is set, thus:

/////////////////////  D E T E R M I N E   O N L I N E   D E V I C E S   /////////////////////

printf("\n     get specific device by name:\n" );
[[SparkCloud sharedInstance] getDevices: ^ (NSArray * sparkDevices, NSError * error) {
  printf("\n     get specific device by name:\n" );
  NSLog(@"%@", sparkDevices.description); // print all devices claimed to user

  // search for a specific device by name
  for (SparkDevice * device in sparkDevices)
  {
    if ([device.name isEqualToString:@"IB_A"])    // one of my Internet Button Photon's
    {
      myPhoton = device;
      NSLog(@"\n  device.name %@    FOUND   myPhoton=%x \n", device.name, myPhoton );

      ////////////////////////   R E A D   D E V I C E   B U T T O N   ///////////////////////

      // reading a variable
      printf("\n     reading a variable" );
      [myPhoton getVariable:@"button_press" completion: ^ (id result, NSError * error) {
        printf("\n     reading a variable" );
        if (!error)
        {
          NSNumber*  button_press = (NSNumber*  )result;
          NSLog(@"button_press is #%f ", button_press.doubleValue);
        }
        else
        {
          NSLog(@"Failed reading button_press from Photon device");
        }
      }];
    }
    else
    {
      NSLog(@"\n  device.name %@    NOT FOUND \n", device.name );
    }
  }
}];

Why doesn’t the example app work as is?

Did you fix this part of your Photon code yet? You need to call Particle.variable during setup() not during loop() and only call it once.

1 Like

Yes, he said

1 Like

What’s happening is due to the asynchronous nature of the getDevices and getVariable methods. In the code you included in your previous post, you call getVariable outside the completion block of getDevices. Because getDevices is asynchronous, the method returns before the completion block is executed, and then getDevices is called immediately after; at this time, myPhoton will still be nil.

In the code you have in your last post, you’re calling getVariable inside the completion block of getDevices, so it won’t run until that block gets executed. I haven’t looked at the example code you’re drawing from (I use my own code written in Swift), so I don’t know if that code works correctly or not, and that maybe it was your modification that caused it to not work. Where did you get the example from?

1 Like