Team:BSC United/Software

iGEM BSC_United

DESIGN

SOFTWARE

Mobile App

The main goal of this app is to demonstrate the current blood sugar level and the historical data. It also helps track the records of drug releasing. The connection between the device and the app is based on Bluetooth 4.0. Then the data are demonstrated in a chart form, which enables users to easily understand their health conditions. The chart could alter among three different scales - hours, days, and months. Users can input an exact time to search for the blood sugar level at that time. Once users register their own accounts, they can set personal information - such as avatars, age, and type of diabetes - and access historical information on their mobile phones.

Code Illustration

Bluetooth: In Bluetooth section, we set our app as the central and the device as the peripherals. First, we import the database CoreBluetooth and define several variables to store the data. Then, we determine the Bluetooth status of the phone and find the equipment that meets the requirements. Finally, the connection event is triggered by clicking the corresponding cell.

import UIKit
import CoreBluetooth

class BluetoothTableViewController: UITableViewController {
    
//    var connected : String?
//    var unconnected = [String]()
    var peripherals = [CBPeripheral]()//all peripherals detected
    var peripheral: CBPeripheral?//peripherals connected
    var selectedRow: Int = -1
    private var centralManager: CBCentralManager?
    

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 2
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        if section == 0{
            return peripheral == nil ? 0 : 1
        } else {
            return peripherals.count
        }
    }
    
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "bluetoothCellId", for: indexPath)
        if indexPath.section == 0 {
            cell.textLabel?.text = peripheral?.name
        } else {
            cell.textLabel?.text = peripherals[indexPath.row].name
        }
        // Configure the cell...

        return cell
    }
    
    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return section == 0 ? "Connected Device" : "Unconnected Devices"
    }
    
    override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 30
    }
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        
        if indexPath.section == 1 {
            selectedRow = indexPath.row
            //connected to the selected peripheral
            centralManager?.connect(peripherals[indexPath.row], options: nil)
            HUD.shareInstance.showHUD()
        }
    }
}
extension BluetoothTableViewController: CBCentralManagerDelegate, CBPeripheralDelegate {
        //determine the Bluetooth state
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .unknown:
            print("Unknown")
        case .resetting:
            print("Resetting")
        case .unsupported:
            print("Unsupported")
        case .unauthorized:
            print("Unauthorized")
        case .poweredOff:
            print("Powered Off")
        case .poweredOn:
            print("Powered On")
            central.scanForPeripherals(withServices: nil, options: nil)
        @unknown default:
            fatalError()
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        centralManager = CBCentralManager(delegate: self, queue: .main)
    }
    //discover peripherals that meet the requirements
    
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        if let name = peripheral.name {
            //if name == "Glucose-100A" && peripherals.count == 0{}
            if !peripherals.contains(peripheral){
                peripherals.append(peripheral)
            
                self.tableView.insertRows(at: [IndexPath(row: peripherals.count-1, section: 1)], with: .automatic)
            }
        }
    }
    
    /** Connected */
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        self.centralManager?.stopScan()
        peripheral.delegate = self
        HUD.shareInstance.showHUDSuccess(message: "Connected")
        
        self.peripheral = peripheral
        peripherals.remove(at: selectedRow)
        tableView.reloadData()
    }
    /** Callback */
    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
        HUD.shareInstance.showHUDFail(message: "Connection Failed")
    }
    
}

Chart Demonstration: SwiftChart is introduced as a database. Because our data are illustrated in three time scales - day, month and year - three arrays are used to store data in different tables. Refer to the function in the database for drawing graphs.

import SwiftChart
 @IBOutlet weak var chartView: UIView!
    var chart: Chart?
    
    var dayArray = [(Int, Double)]()
    var monthArray = [(Int, Double)]()
    var yearArray = [(Int, Double)]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        chart = Chart(frame: CGRect(x: 0, y: 0, width: chartView.frame.size.width, height: chartView.frame.size.height))
        setData()
        self.changeChartView(type: "day", data: dayArray)
        // Use `xLabels` to add more labels, even if empty
        self.chartView.addSubview(chart!)
        // Do any additional setup after loading the view.
    }
    
    func setData() {
        dayArray = [
            (x: 0, y: 0),
            (x: 3, y: 2.5),
            (x: 4, y: 2),
            (x: 5, y: 2.3),
            (x: 7, y: 3),
            (x: 8, y: 2.2),
            (x4: 9, y: 2.5)
        ]
        
        monthArray = [
            (x: 1, y: 3),
            (x: 4, y: 2.5),
            (x: 6, y: 2),
            (x: 16, y: 2.3),
            (x: 26, y: 3),
            (x: 30, y: 2.2)
        ]
        yearArray = [
            (x: 1, y: 3),
            (x: 4, y: 2.5),
            (x: 6, y: 2),
            (x: 12, y: 2.3)
        ]
    }
    
    func changeChartView(type: String, data: [(Int, Double)]) {
        chart?.removeAllSeries()
        let series = ChartSeries(data: data)
        series.area = true
        if type == "day" {
            chart?.xLabels = [0, 3, 6, 9, 12, 15, 18, 21, 24]
            // Format the labels with a unit
            chart?.xLabelsFormatter = { String(Int(round($1))) + "h" }
        } else if type == "month" {
            chart?.xLabels = [1, 5, 10, 15, 20, 25, 31]
            // Format the labels with a unit
            chart?.xLabelsFormatter = { String(Int(round($1))) }
        } else {
            chart?.xLabels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
            // Format the labels with a unit
            chart?.xLabelsFormatter = { String(Int(round($1))) }
        }
        chart?.add(series)
    }
    
    @IBAction func segmentChangeAction(_ sender: UISegmentedControl) {
        if sender.selectedSegmentIndex == 0 {
            self.changeChartView(type: "day", data: dayArray)
        } else if sender.selectedSegmentIndex == 1 {
            self.changeChartView(type: "month", data: monthArray)
        } else {
            self.changeChartView(type: "year", data: yearArray)
        }
    }

Jumps: Determine whether registration has been completed by Identifier of the page, and then jump.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        IQKeyboardManager.shared.enable = true
        
        window?.frame = UIScreen.main.bounds
        let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
        let loginVC = mainStoryboard.instantiateViewController(withIdentifier: "LoginID") as! UINavigationController
        let mainVC = mainStoryboard.instantiateViewController(withIdentifier: "MainViewID") as! UITabBarController
        if UserDefaults.standard.value(forKey: "USER_NAME") != nil {
            window?.rootViewController = mainVC
        } else {
            window?.rootViewController = loginVC
        }
        
        return true
    }