         NotificationCenter.default.addObserver(self, selector: #selector(appDidBecomeActive(_:)), name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil)
     }
 
-
     override func viewWillDisappear(_ animated: Bool) {
         NotificationCenter.default.removeObserver(self)
     }
+
+
+
 
     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
         if segue.identifier == "deviceInspector" {
             if let vc = segue.destination as? DeviceInspectorViewController {
-                let indexPath = sender as! IndexPath
-
-                vc.setup(device: self.devices[indexPath.row])
-
-                ParticleLogger.logInfo(NSStringFromClass(type(of: self)), format: "Segue into device inspector - idx: %i device: %@", withParameters: getVaList([indexPath.row, "\(self.devices[indexPath.row])"]))
-                SEGAnalytics.shared().track("Tinker_SegueToDeviceInspector", properties: ["device": self.devices[indexPath.row].type.description])
-            }
-        }
-    }
-
+                let device = sender as! ParticleDevice
+                vc.setup(device: device)
+
+                ParticleLogger.logInfo(NSStringFromClass(type(of: self)), format: "Segue into device inspector - device: %@", withParameters: getVaList(["\(device)"]))
+                SEGAnalytics.shared().track("Tinker_SegueToDeviceInspector", properties: ["device": device.type.description])
+            }
+        }
+    }
+
+    func loadDevices()
+    {
+        ParticleLogger.logInfo(NSStringFromClass(type(of: self)), format: "Load devices started", withParameters: getVaList([]))
+
+        DispatchQueue.global().async {
+            ParticleCloud.sharedInstance().getDevices({ (devices:[ParticleDevice]?, error:Error?) -> Void in
+
+                self.handleGetDevicesResponse(devices, error: error)
+
+                DispatchQueue.main.async { [weak self] () -> () in
+                    if let self = self {
+                        self.resume(animated: true)
+                        self.showTutorial()
+                    }
+                }
+            })
+        }
+    }
+
+    func handleGetDevicesResponse(_ devices:[ParticleDevice]?, error:Error?)
+    {
+        ParticleLogger.logInfo(NSStringFromClass(type(of: self)), format: "Load devices completed", withParameters: getVaList([]))
+        if let e = error
+        {
+            self.devices = []
+
+            if (e as NSError).code == 401 {
+                self.logout()
+            } else {
+                ParticleLogger.logError(NSStringFromClass(type(of: self)), format: "Load devices error", withParameters: getVaList([]))
+                RMessage.showNotification(withTitle: "Error", subtitle: "Error loading devices, please check your internet connection.", type: .error, customTypeName: nil, callback: nil)
+            }
+
+            DispatchQueue.main.async {
+                self.noDevicesLabel.isHidden = false
+                self.tableView.reloadData()
+            }
+        }
+        else
+        {
+            if let d = devices
+            {
+                // if no devices offer user to setup a new one
+                if (d.count == 0) {
+                    self.setupNewDeviceButtonTapped(self.setupNewDeviceButton)
+                }
+
+                self.devices = d
+                for device in self.devices {
+                    device.delegate = self
+                }
+
+                self.noDevicesLabel.isHidden = self.devices.count == 0 ? false : true
+
+                sortDevices()
+
+                ParticleLogger.logInfo(NSStringFromClass(type(of: self)), format: "Load devices completed. Device count: %i", withParameters: getVaList([self.devices.count]))
+                ParticleLogger.logDebug(NSStringFromClass(type(of: self)), format: "Devices: %@", withParameters: getVaList([self.devices]))
+
+                DispatchQueue.main.async {
+                    self.tableView.reloadData()
+                }
+            } else {
+                self.devices = []
+
+                ParticleLogger.logInfo(NSStringFromClass(type(of: self)), format: "Load devices completed. Device count: %i", withParameters: getVaList([self.devices.count]))
+                ParticleLogger.logDebug(NSStringFromClass(type(of: self)), format: "Devices: %@", withParameters: getVaList([self.devices]))
+
+                DispatchQueue.main.async {
+                    self.noDevicesLabel.isHidden = false
+                    self.setupNewDeviceButtonTapped(self.setupNewDeviceButton)
+                    self.tableView.reloadData()
+                }
+            }
+
+        }
+    }
+
+    private func sortDevices() {
+        self.devices.sort(by: { (firstDevice:ParticleDevice, secondDevice:ParticleDevice) -> Bool in
+            if (firstDevice.connected != secondDevice.connected) {
+                return firstDevice.connected == true
+            } else {
+                var nameA = firstDevice.name ?? " "
+                var nameB = secondDevice.name ?? " "
+                return nameA.lowercased() < nameB.lowercased()
+            }
+        })
+    }
+
+    func addRefreshControl()
+    {
+        self.tableView.addPullToRefresh(withPullText: "Pull To Refresh", refreshingText: "Refreshing Devices") { () -> Void in
+            weak var weakSelf = self
+            ParticleCloud.sharedInstance().getDevices() { (devices:[ParticleDevice]?, error: Error?) -> Void in
+                weakSelf?.handleGetDevicesResponse(devices, error: error)
+                weakSelf?.tableView.finishLoading()
+            }
+        }
+    }
 
 
     func invokeElectronSetup() {


    @IBOutlet weak var tableView: UITableView!

    var devices : [ParticleDevice] = []
    var selectedDevice : ParticleDevice? = nil
    var refreshControlAdded : Bool = false

    override var preferredStatusBarStyle : UIStatusBarStyle {

    }

    @IBAction func moreButtonTapped(_ sender: UIButton) {
        ParticleLogger.logInfo(NSStringFromClass(type(of: self)), format: "More tapped", withParameters: getVaList([]))

        let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
