// // MainTableViewController.swift // SwiftStarter // // Created by Stephen Schiffli on 10/16/15. // Copyright © 2015 MbientLab Inc. All rights reserved. // import UIKit import MetaWear import MetaWearCpp import MBProgressHUD import BoltsSwift class MainTableViewController: UITableViewController, ScanTableViewControllerDelegate { var devices: [MetaWear] = [] var allLoggers:[String:[String: OpaquePointer]] = [:] var loggers: [String: OpaquePointer] = [:] var hud: MBProgressHUD! var accelerometerBMI160Data: [(Int64, MblMwCartesianFloat)] = [] var allAccelerometerBMI160Data: [String:(Int64, MblMwCartesianFloat)] = [:] override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated); updateList() } func updateList() { MetaWearScanner.shared.retrieveSavedMetaWearsAsync().continueOnSuccessWith(.mainThread) { self.devices = $0 self.tableView.reloadData() } } // MARK: - Scan table view delegate func scanTableViewController(_ controller: ScanTableViewController, didSelectDevice device: MetaWear) { navigationController?.popViewController(animated: true) let hud = MBProgressHUD.showAdded(to: UIApplication.shared.keyWindow!, animated: true) hud.label.text = "Programming..." device.initialDeviceSetup().continueWith(.mainThread) { hud.mode = .text hud.label.text = $0.error?.localizedDescription ?? "Success" hud.hide(animated: true, afterDelay: 2.5) self.updateList() } } // MARK: - Table view data source override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return devices.count + 1 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { var cell : UITableViewCell! if indexPath.row < devices.count { cell = tableView.dequeueReusableCell(withIdentifier: "MetaWearCell", for: indexPath) let cur = devices[indexPath.row] let name = cell.viewWithTag(1) as! UILabel name.text = cur.name let uuid = cell.viewWithTag(2) as! UILabel uuid.text = cur.mac } else { cell = tableView.dequeueReusableCell(withIdentifier: "NoDeviceCell", for: indexPath) } return cell } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) if indexPath.row < devices.count { //performSegue(withIdentifier: "ViewDevice", sender: devices[indexPath.row]) } else { performSegue(withIdentifier: "AddNewDevice", sender: nil) } } override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { // Return false if you do not want the specified item to be editable.ƒ return indexPath.row < devices.count } override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { devices[indexPath.row].eraseDevice() devices.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .automatic) } } // MARK: - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation override func prepare(for segue: UIStoryboardSegue, sender: Any?) { // Get the new view controller using segue.destinationViewController. if let scanController = segue.destination as? ScanTableViewController { scanController.delegate = self } else if let deviceController = segue.destination as? DeviceViewController { deviceController.device = (sender as! MetaWear) } } func deviceConnectedReadAnonymousLoggers(device:MetaWear) { let task = device.createAnonymousDatasignals() task.continueWith(.mainThread) { t in self.loggers = [:] if let signals = t.result { for signal in signals { let cString = mbl_mw_anonymous_datasignal_get_identifier(signal)! let identifier = String(cString: cString) self.loggers[identifier] = signal } } self.allLoggers[device.mac ?? "deviceMac"] = self.loggers mbl_mw_acc_bosch_set_range(device.board, MBL_MW_ACC_BOSCH_RANGE_2G) mbl_mw_acc_set_odr(device.board, Float(800)) mbl_mw_acc_bosch_write_acceleration_config(device.board) //start device // let signal = mbl_mw_acc_bosch_get_acceleration_data_signal(device.board)! // mbl_mw_datasignal_log(signal, bridge(obj: self)) { (context, logger) in // let _self: MainTableViewController = bridge(ptr: context!) // let cString = mbl_mw_logger_generate_identifier(logger)! // let identifier = String(cString: cString) // _self.loggers[identifier] = logger! // } mbl_mw_logging_start(device.board, 0) mbl_mw_acc_enable_acceleration_sampling(device.board) mbl_mw_acc_start(device.board) } } @IBAction func StartButtonClicked(_ sender: Any) { for device in devices { //set up accelometer for default settings device.connectAndSetup().continueWith(.mainThread) { t in self.deviceConnectedReadAnonymousLoggers(device: device) } } } func setLedColor(_ color: MblMwLedColor,device: MetaWear ) { var pattern = MblMwLedPattern(high_intensity: 31, low_intensity: 31, rise_time_ms: 0, high_time_ms: 2000, fall_time_ms: 0, pulse_duration_ms: 2000, delay_time_ms: 0, repeat_count: 0xFF) mbl_mw_led_stop_and_clear(device.board) mbl_mw_led_write_pattern(device.board, &pattern, color) mbl_mw_led_play(device.board) } @IBAction func StopButtonClicked(_ sender: Any) { hud = MBProgressHUD.showAdded(to: UIApplication.shared.keyWindow!, animated: true) hud.mode = .determinateHorizontalBar hud.label.text = "Downloading..." for device in devices { device.connectAndSetup().continueWith(.mainThread) { t in mbl_mw_acc_stop(device.board) mbl_mw_acc_disable_acceleration_sampling(device.board) var logggerCopy = self.allLoggers[device.mac ?? "deviceMac"] guard let logger = logggerCopy?.removeValue(forKey: "acceleration") else { return } //self.accelerometerBMI160Data.removeAll() mbl_mw_logger_subscribe(logger, bridge(obj: self)) { (context, obj) in let acceleration: MblMwCartesianFloat = obj!.pointee.valueAs() let _self: MainTableViewController = bridge(ptr: context!) //here need to check if device.mac has some data wlll append but currently facing error var localAccelerometerBMI160Data = _self.allAccelerometerBMI160Data[device.mac ?? "deviceMac"] _self.accelerometerBMI160Data.append((obj!.pointee.epoch, acceleration)) } var handlers = MblMwLogDownloadHandler() handlers.context = bridgeRetained(obj: self) handlers.received_progress_update = { (context, remainingEntries, totalEntries) in let _self: MainTableViewController = bridge(ptr: context!) let progress = Double(totalEntries - remainingEntries) / Double(totalEntries) DispatchQueue.main.async { _self.hud.progress = Float(progress) } } mbl_mw_logging_download(device.board, 100, &handlers) } } } } extension MetaWear { // Call once to setup a device func initialDeviceSetup(temperaturePeriodMsec: UInt32 = 1000) -> Task<()> { return eraseDevice().continueWithTask { _ -> Task> in return self.connectAndSetup() }.continueOnSuccessWithTask { _ -> Task<()> in let state = DeviceState(temperaturePeriodMsec: temperaturePeriodMsec) return state.setup(self) }.continueWithTask { t -> Task<()> in // if !t.faulted { // self.remember() // } else { // self.eraseDevice() // } return t } } // If you no longer need a device call this @discardableResult func eraseDevice() -> Task { // Remove the on-disk state try? FileManager.default.removeItem(at: uniqueUrl) // Drop the device from the MetaWearScanner saved list forget() // Reset and clear all data from the device return connectAndSetup().continueOnSuccessWithTask { self.clearAndReset() return $0 } } }