IOS SDK subscribe and display event data

Hi All,

I’ve got a current IOS app working that gets data from a photon particle variable when I press a button on the IOS screen. I’m using Xcode 9.2, IOS 11.2, iPhone X, CocoaPods.
I want to morph the code so that the app subscribes to an event, then displays this data and updates it as a new event is published.

Are there any working examples of a similar IOS app that I can play with?

I’m pretty green with my Xcode programming, so even though I see the subscribe code in the SDK docs, I’ve been unable to get it to work.

Thx.
J

1 Like

What code did you try to get the subscription to work, and what result did that code give you? Also, are you using the latest SDK, where it uses Particle instead of Spark?

And Objective-C or Swift? (Though providing the code that you tried as Ric pointed out, is even better, and then we’d know.)

Hi Guys, thanks for the replies..

Well, the code is Objective-C, my swift is pretty lacking.

I've simplified my code as much as I can to focus on just getting the subscription.

So first - I'm not sure where to put the event listener, I put it in

viewDidLoad()

after my login (which might not be right, especially as it is in a void declaration), in the viewcontroller.m file, and I put the handler later in the same file.

Currently I get this warning at the line where I subscribe:

ViewController.m:24:8: Unused variable 'eventListenerID'

I don't know how to deal with the variable to get it into a label, which is called Total Time.
I left in the IBOutlet line that I used to put a particle variable totalTime into the label, and know that will have to be modified, but I'm not sure how to do that, either. I fear that my skills are so basic that you guys will just tell me to go back to school!

Viewcontroller.m code:

#import "ViewController.h"
#import "Particle-SDK.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UILabel *totalTime;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [[ParticleCloud sharedInstance]
    loginWithUser:@"******@****.com"
    password:@"*******" completion:^(NSError *error) {
        if (!error)
            NSLog(@"Logged in to cloud");
        else
            NSLog(@"Wrong credentials or no internet connectivity, please try again");
    }];
    id eventListenerID = [[ParticleCloud sharedInstance] subscribeToDeviceEventsWithPrefix:@"time" deviceID:@"******************" handler:handler];
}

ParticleEventHandler handler = ^(ParticleEvent *event, NSError *error) {
    if (!error)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"Got Event %@ with data: %@",event.event,event.data);
        });
    }
    else
    {
        NSLog(@"Error occured: %@",error.localizedDescription);
    }
};

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

Thanks for looking. J

Please edit your last post to format your code correctly, it’s very hard to read as is. That’s done by enclosing your code like so:

```cpp
<your code here>
```

Those are grave accent marks (on the key to left of the 1 key), and they need to be on lines by themselves

Thanks, I didn’t know about that.
J

I wouldn’t worry about that warning for now (the eventListenerID is used for unsubscribing). It should be ok to have the subscribe line in viewDidLoad. Is your login working or not (which log gets printed out)? How are your publishing? Is the publish statement marked with PRIVATE? It need to be for subscribeToMyDevicesEventsWithPrefix, and I think it should be for subscribeToDeviceEventsWithPrefix:deviceID: too.

Finally, what result does this code give you? Just nothing, or is it crashing or not compiling?

In your handler use:

dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"Got Event %@ with data: %@",event.event,event.data);
            self.totalTime.text = event.data;
        });

@Ric

The login works. It does compile. The publish is marked private, I'm just using a fixed value in it to begin with as below:

Particle.publish("Speed", 27, PRIVATE);

It logs in and I get the message Logged in to Cloud, but I never see anything in the log to show that the Event was received or that an error occurred. Maybe I should try it without the DeviceID?

@echamberlain

Thanks, I'll put that in. Currently if I add it, it won't build and throws a:

ViewController.m:32:13: Use of undeclared identifier 'self'

Do I need something like

  • (IBAction)Speed:(id)sender {
    }

To enclose the handler, or inside the handler?

J

OK, I’m getting the event in the log now, I wasn’t enclosing the number in Quotes.

Getting there…

So I get the data thru to the console, but when I add this line:

self.totalTime.text = event.data;

I get this error:

ViewController.m:32:13: Use of undeclared identifier ‘self’

And I can't get it to lead to my UILabel totalTime

How can I get this to find and update the label?

Do I need something in the viewController.h to reference the label?

You do need a property (or variable) for that label somewhere. It can be in the .h or .m file. Do you have one, and is it connected to a label in the storyboard? It’s strange that the error you’re getting is about “self” though.

I have this in the viewcontroller.m file, which I think is correct, and it is connected to the label in the storyboard.

@property (weak, nonatomic) IBOutlet UILabel *totalTime;

It just doesn't seem to link to the variable that is attached to the UILabel.

It’s not clear to me why it’s not working then. Sometimes the error messages aren’t identifying the correct problem. Please post the entire method that this line of code is in. I have to say I’m a little rusty on Objective-C these days. I moved on to Swift 3 or 4 years ago.

Here’s the whole viewcontroller.m file.


#import "ViewController.h"
#import "Particle-SDK.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UILabel *totalTime;

@end

@implementation ViewController




- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [[ParticleCloud sharedInstance]
    loginWithUser:@"******"
    password:@"******" completion:^(NSError *error) {
        if (!error)
            NSLog(@"Logged in to cloud");
        else
            NSLog(@"Wrong credentials or no internet connectivity, please try again");
    }];
   id eventListenerID = [[ParticleCloud sharedInstance] subscribeToDeviceEventsWithPrefix:@"Speed" deviceID:@"********0" handler:handler];
}

ParticleEventHandler handler = ^(ParticleEvent *event, NSError *error) {
    if (!error)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"Got Event %@ with data: %@",event.event,event.data);
            self.totalTime.text = event.data;
        });
    }
    else
    {
        NSLog(@"Error occured: %@",error.localizedDescription);
    }
};

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

The whole statement that begins with the above line should be inside a method -- try moving all that code inside of viewDidLoad.

Well, that swapped one issue to the next, now I get:

Use of undeclared identifier 'handler'

#import "ViewController.h"
#import "Particle-SDK.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UILabel *totalTime;

@end

@implementation ViewController




- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [[ParticleCloud sharedInstance]
    loginWithUser:@"****@***.com"
    password:@"*********" completion:^(NSError *error) {
        if (!error)
            NSLog(@"Logged in to cloud");
        else
            NSLog(@"Wrong credentials or no internet connectivity, please try again");
    }];
   id eventListenerID = [[ParticleCloud sharedInstance] subscribeToDeviceEventsWithPrefix:@"Speed" deviceID:@"**********" handler:handler];


ParticleEventHandler handler = ^(ParticleEvent *event, NSError *error) {
    if (!error)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"Got Event %@ with data: %@",event.event,event.data);
            self.totalTime.text = event.data;
        });
    }
    else
    {
        NSLog(@"Error occured: %@",error.localizedDescription);
    }
};
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

As I said, I’m pretty rusty at Objective-C. Try this instead and see if it works,

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [[ParticleCloud sharedInstance]
     loginWithUser:@"****@***.com"
     password:@"*********" completion:^(NSError *error) {
         if (!error)
             NSLog(@"Logged in to cloud");
         else
             NSLog(@"Wrong credentials or no internet connectivity, please try again");
     }];

    id eventListenerID = [[ParticleCloud sharedInstance] subscribeToDeviceEventsWithPrefix:@"Speed" deviceID:@"**********" handler: ^(ParticleEvent *event, NSError *error) {

        if (!error)
        {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"Got Event %@ with data: %@",event.event,event.data);
                self.totalTime.text = event.data;
            });
        }
        else
        {
            NSLog(@"Error occured: %@",error.localizedDescription);
        }
    }];
                      
}

You got that error, because you were using handler, before you defined it.

Thanks a ton, guys, it’s working!

I love the way this forum works, big thumbs up.

J

1 Like