particle-iot / spark-setup-ios

(DEPRECATED) Spark device setup library - Soft AP Cocoapod/Carthage lib for iOS
Apache License 2.0
19 stars 25 forks source link

Getting Device ID after Setup Completion #55

Closed steve-else closed 7 years ago

steve-else commented 7 years ago

I am currently implementing this library while using react-native, and I'm having issues with getting the device ID after completion of setup. This is an extension of this previous thread: https://github.com/spark/spark-setup-ios/issues/42

My current RCT export method to launch the setup is as follows:

RCT_EXPORT_METHOD(openCustom)
{
  [self createCustomSparkSetup];

  SparkSetupMainController *setupController = [[SparkSetupMainController alloc] initWithSetupOnly:YES];
  AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  [delegate.window.rootViewController presentViewController:setupController animated:YES completion:nil];
}

From that thread, it seems to catch the event you must use the following:

-(void)SparkSetupViewController:(SparkSetupMainController *)controller didFinishWithResult:(SparkSetupMainControllerResult)result device:(SparkDevice *)device;

Has anyone successfully gotten that event to trigger, and get the device ID from device.id? This is with a react-native implementation.

steve-else commented 7 years ago

Figured out my issue, can close this!

idokleinman commented 7 years ago

Thanks for the update, I'd love to get insight to your react-native implementation if thats open source.

steve-else commented 7 years ago

Unfortunately the project I'm working on isn't open source yet, it's for a company product. But I can share how to set this up for anyone who's curious. For some context, what I was trying to accomplish here was to POST the device name and device ID to our own database after successfully setting up a device on your account. We are using two-legged authentication. My main deviation from the other thread I linked in the OP was that they were somehow trying to make the AppDelegate hold the method that triggered when setup finished. I couldn't get that to work, so I basically created a new view controller that conformed to protocol instead. I don't know if this is the ideal method, but it worked for me.

First make a new ViewController to act as the delegate for spark-setup. I named mine ParticleSetupViewController.

.h file

#import <UIKit/UIKit.h>
#import <ParticleDeviceSetupLibrary/ParticleDeviceSetupLibrary.h>
#import <ParticleSDK/SparkCloud.h>
@interface ParticleSetupViewController : UIViewController <SparkSetupMainControllerDelegate>

@end

.m file

#import "ParticleSetupViewController.h"

@implementation ParticleSetupViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

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

// this method is automatically called when the setup process finishes.
- (void)sparkSetupViewController:(SparkSetupMainController *)controller didFinishWithResult:(SparkSetupMainControllerResult)result device:(SparkDevice *)device {
//just logging the id/name here, you can do whatever you need to with those values.
  NSLog(@"The device ID is: %@", device.id);
  NSLog(@"The device name is: %@", device.name);
}

Next you have to make your react-native bridge module class. I named mine SoftAPManager.

.h file

#import <Foundation/Foundation.h>
#import "React/RCTBridgeModule.h"

@interface SoftAPManager : NSObject <RCTBridgeModule>

@end

.m file

#import "SoftAPManager.h"
#import <ParticleDeviceSetupLibrary/ParticleDeviceSetupLibrary.h>
#import "AppDelegate.h"
#import <ParticleSDK/SparkCloud.h>
#import "ParticleSetupViewController.h"

@interface SoftAPManager ()
@property (nonatomic, retain) ParticleSetupViewController *particleSetup;
@end

@implementation SoftAPManager

RCT_EXPORT_MODULE();

// this is the method that you will call from your javascript code on the react-native side
RCT_EXPORT_METHOD(openCustom)
{
  //comment this out if you want the default setup screen
  [self createCustomSparkSetup];

  SparkSetupMainController *setupController = [[SparkSetupMainController alloc] initWithSetupOnly:YES];
  if(self.particleSetup == nil) {
    self.particleSetup = [[ParticleSetupViewController alloc] init];
  }
  [setupController setDelegate:self.particleSetup];
  AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  [delegate.window.rootViewController presentViewController:setupController animated:YES completion:nil];
}

-(void)createCustomSparkSetup {
    // customize your spark setup if you want
   }
}

Now back in your javascript code, you can call the RCT openCustom method from whichever component needs it.

//NativeModules holds the custom bridge classes you make
import { View, Button, NativeModules } from 'react-native';

const SoftAPManager = NativeModules.SoftAPManager;

//this will launch the particle setup process
const setupNewParticleDevice = () => {
  SoftAPManager.openCustom();
};

Now after you set up your device, the - (void)sparkSetupViewController:(SparkSetupMainController *)controller didFinishWithResult:(SparkSetupMainControllerResult)result device:(SparkDevice *)device should have gotten you the values you need right after setup has finished.