| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899 |
- //
- // RileyLinkDeviceTableViewController.swift
- // Naterade
- //
- // Created by Nathan Racklyeft on 3/5/16.
- // Copyright © 2016 Nathan Racklyeft. All rights reserved.
- //
- import UIKit
- import LoopKitUI
- import RileyLinkBLEKit
- import RileyLinkKit
- import os.log
- let CellIdentifier = "Cell"
- public class RileyLinkSwitch: UISwitch {
-
- public var index: Int = 0
- public var section: Int = 0
- }
- public class RileyLinkCell: UITableViewCell {
- public let switchView = RileyLinkSwitch()
-
- public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
- super.init(style: style, reuseIdentifier: reuseIdentifier)
- contentView.addSubview(switchView)
- }
-
- public required init?(coder aDecoder: NSCoder) {
- super.init(coder: aDecoder)
- }
-
- public override func layoutSubviews() {
- super.layoutSubviews()
- switchView.frame = CGRect(x: frame.width - 51 - 20, y: (frame.height - 31) / 2, width: 51, height: 31)
- }
- }
- public class RileyLinkDeviceTableViewController: UITableViewController {
- private let log = OSLog(category: "RileyLinkDeviceTableViewController")
- public let device: RileyLinkDevice
- private var bleRSSI: Int?
- private var firmwareVersion: String? {
- didSet {
- guard isViewLoaded else {
- return
- }
-
- cellForRow(.version)?.detailTextLabel?.text = firmwareVersion
- }
- }
-
- private var uptime: TimeInterval? {
- didSet {
- guard isViewLoaded else {
- return
- }
-
- cellForRow(.uptime)?.setDetailAge(uptime)
- }
- }
-
- private var battery: Int? {
- didSet {
- guard isViewLoaded else {
- return
- }
- cellForRow(.battery)?.setDetailBatteryLevel(battery)
- }
- }
-
- private var frequency: Measurement<UnitFrequency>? {
- didSet {
- guard isViewLoaded else {
- return
- }
-
- cellForRow(.frequency)?.setDetailFrequency(frequency, formatter: frequencyFormatter)
- }
- }
-
- private var ledMode: RileyLinkLEDMode? {
- didSet {
- guard isViewLoaded else {
- return
- }
- cellForRow(.diagnosticLEDSMode)?.setLEDMode(ledMode)
- }
- }
- var rssiFetchTimer: Timer? {
- willSet {
- rssiFetchTimer?.invalidate()
- }
- }
-
- private var hasPiezo: Bool = false
-
- private var appeared = false
-
- private var batteryAlertLevel: Int? {
- didSet {
- batteryAlertLevelChanged?(batteryAlertLevel)
- }
- }
-
- private var batteryAlertLevelChanged: ((Int?) -> Void)?
- public init(device: RileyLinkDevice, batteryAlertLevel: Int?, batteryAlertLevelChanged: ((Int?) -> Void)? ) {
- self.device = device
- self.batteryAlertLevel = batteryAlertLevel
- self.batteryAlertLevelChanged = batteryAlertLevelChanged
- super.init(style: .grouped)
- updateDeviceStatus()
-
- NotificationCenter.default.addObserver(forName: .DeviceStatusUpdated, object: device, queue: .main)
- { (notification) in
- self.updateDeviceStatus()
- }
- }
- required public init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- public override func viewDidLoad() {
- super.viewDidLoad()
- title = device.name
-
- switch device.hardwareType {
- case .riley, .none:
- deviceRows = [
- .customName,
- .version,
- .rssi,
- .connection,
- .uptime,
- .frequency
- ]
-
- sections = [
- .device,
- .rileyLinkCommands
- ]
- case .ema:
- deviceRows = [
- .customName,
- .version,
- .rssi,
- .connection,
- .uptime,
- .frequency,
- .battery
- ]
- sections = [
- .device,
- .alert,
- .emaLinkCommands
- ]
- case .orange:
- deviceRows = [
- .customName,
- .version,
- .rssi,
- .connection,
- .uptime,
- .battery,
- .voltage
- ]
-
- if device.hasOrangeLinkService {
- sections = [
- .device,
- .alert,
- .configureCommand,
- .orangeLinkCommands
- ]
- } else {
- sections = [
- .device
- ]
- }
- }
-
- self.observe()
- }
-
- @objc func updateRSSI() {
- device.readRSSI()
- }
- // This does not trigger any BLE reads; it just gets status from the device in a safe manner, and reloads the table
- func updateDeviceStatus() {
- device.getStatus { (status) in
- DispatchQueue.main.async {
- self.firmwareVersion = status.version
- self.ledOn = status.ledOn
- self.vibrationOn = status.vibrationOn
- self.voltage = status.voltage
- self.battery = status.battery
- self.hasPiezo = status.hasPiezo
- self.tableView.reloadData()
- }
- }
- }
-
- func updateUptime() {
- device.runSession(withName: "Get stats for uptime") { (session) in
- do {
- let statistics = try session.getRileyLinkStatistics()
- DispatchQueue.main.async {
- self.uptime = statistics.uptime
- }
- } catch let error {
- self.log.error("Failed to get stats for uptime: %{public}@", String(describing: error))
- }
- }
- }
-
- func updateFrequency() {
- device.runSession(withName: "Get base frequency") { (session) in
- do {
- let frequency = try session.readBaseFrequency()
- DispatchQueue.main.async {
- self.frequency = frequency
- }
- } catch let error {
- self.log.error("Failed to get base frequency: %{public}@", String(describing: error))
- }
- }
- }
-
- func readDiagnosticLEDMode() {
- device.readDiagnosticLEDModeForBLEChip(completion: { ledMode in
- DispatchQueue.main.async {
- self.ledMode = ledMode
- }
- })
- }
- // References to registered notification center observers
- private var notificationObservers: [Any] = []
-
- deinit {
- for observer in notificationObservers {
- NotificationCenter.default.removeObserver(observer)
- }
- }
- private func observe() {
- let center = NotificationCenter.default
- let mainQueue = OperationQueue.main
-
- notificationObservers = [
- center.addObserver(forName: .DeviceNameDidChange, object: device, queue: mainQueue) { [weak self] (note) -> Void in
- if let cell = self?.cellForRow(.customName) {
- cell.detailTextLabel?.text = self?.device.name
- }
- self?.title = self?.device.name
- self?.tableView.reloadData()
- },
- center.addObserver(forName: .DeviceConnectionStateDidChange, object: device, queue: mainQueue) { [weak self] (note) -> Void in
- if let cell = self?.cellForRow(.connection) {
- cell.detailTextLabel?.text = self?.device.peripheralState.description
- }
- },
- center.addObserver(forName: .DeviceRSSIDidChange, object: device, queue: mainQueue) { [weak self] (note) -> Void in
- self?.bleRSSI = note.userInfo?[RileyLinkDevice.notificationRSSIKey] as? Int
-
- if let cell = self?.cellForRow(.rssi), let formatter = self?.integerFormatter {
- cell.setDetailRSSI(self?.bleRSSI, formatter: formatter)
- }
- },
- center.addObserver(forName: .DeviceDidStartIdle, object: device, queue: mainQueue) { [weak self] (note) in
- self?.updateDeviceStatus()
- },
- center.addObserver(forName: .DeviceStatusUpdated, object: device, queue: mainQueue) { [weak self] (note) in
- self?.updateDeviceStatus()
- },
- ]
- }
-
- public override func viewWillAppear(_ animated: Bool) {
- super.viewWillAppear(animated)
- if appeared {
- tableView.reloadData()
- }
-
- rssiFetchTimer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(updateRSSI), userInfo: nil, repeats: true)
-
- appeared = true
-
- updateRSSI()
-
- if deviceRows.contains(.frequency) {
- updateFrequency()
- }
- updateUptime()
-
- switch device.hardwareType {
- case .riley:
- readDiagnosticLEDMode()
- case .ema:
- device.updateBatteryLevel()
- readDiagnosticLEDMode()
- case .orange:
- device.updateBatteryLevel()
- device.orangeWritePwd()
- device.orangeReadSet()
- device.orangeReadVDC()
- device.orangeAction(.fw_hw)
- default:
- break
- }
- }
-
- public override func viewDidDisappear(_ animated: Bool) {
- super.viewDidDisappear(animated)
- if redOn || yellowOn {
- device.orangeAction(.off)
- }
-
- if shakeOn {
- device.orangeAction(.shakeOff)
- }
- }
-
- public override func viewWillDisappear(_ animated: Bool) {
- super.viewWillDisappear(animated)
- rssiFetchTimer = nil
- }
- // MARK: - Formatters
- private lazy var dateFormatter: DateFormatter = {
- let dateFormatter = DateFormatter()
- dateFormatter.dateStyle = .none
- dateFormatter.timeStyle = .medium
- return dateFormatter
- }()
-
- private lazy var integerFormatter = NumberFormatter()
- private lazy var decimalFormatter: NumberFormatter = {
- let decimalFormatter = NumberFormatter()
- decimalFormatter.numberStyle = .decimal
- decimalFormatter.maximumFractionDigits = 2
- return decimalFormatter
- }()
-
- private lazy var frequencyFormatter: MeasurementFormatter = {
- let formatter = MeasurementFormatter()
- formatter.numberFormatter = decimalFormatter
- return formatter
- }()
- // MARK: - Table view data source
- private enum Section: Int, CaseIterable {
- case device
- case alert
- case configureCommand
- case orangeLinkCommands
- case rileyLinkCommands
- case emaLinkCommands
- }
-
- private var sections: [Section] = []
- private enum AlertRow: Int, CaseIterable {
- case battery
- }
- private enum DeviceRow: Int, CaseIterable {
- case customName
- case version
- case rssi
- case connection
- case uptime
- case frequency
- case battery
- case voltage
- }
-
- private var deviceRows: [DeviceRow] = []
-
- private enum RileyLinkCommandRow: Int, CaseIterable {
- case diagnosticLEDSMode
- case getStatistics
- }
- private enum EmaLinkCommandRow: Int, CaseIterable {
- case logicLEDSMode
- case getStatistics
- }
- private enum OrangeLinkCommandRow: Int, CaseIterable {
- case yellow
- case red
- case shake
- case findDevice
- }
- private enum OrangeConfigureCommandRow: Int, CaseIterable {
- case connectionLED
- case connectionVibrate
- }
- private func cellForRow(_ row: DeviceRow) -> UITableViewCell? {
- guard let rowIndex = deviceRows.firstIndex(of: row),
- let sectionIndex = sections.firstIndex(of: Section.device) else
- {
- return nil
- }
- return tableView.cellForRow(at: IndexPath(row: rowIndex, section: sectionIndex))
- }
- private func cellForRow(_ row: OrangeConfigureCommandRow) -> UITableViewCell? {
- guard let sectionIndex = sections.firstIndex(of: Section.orangeLinkCommands) else
- {
- return nil
- }
- return tableView.cellForRow(at: IndexPath(row: row.rawValue, section: sectionIndex))
- }
- private func cellForRow(_ row: OrangeLinkCommandRow) -> UITableViewCell? {
- guard let sectionIndex = sections.firstIndex(of: Section.orangeLinkCommands) else
- {
- return nil
- }
- return tableView.cellForRow(at: IndexPath(row: row.rawValue, section: sectionIndex))
- }
-
- private func cellForRow(_ row: RileyLinkCommandRow) -> UITableViewCell? {
- guard let sectionIndex = sections.firstIndex(of: Section.rileyLinkCommands) else
- {
- return nil
- }
- return tableView.cellForRow(at: IndexPath(row: row.rawValue, section: sectionIndex))
- }
- private func cellForRow(_ row: EmaLinkCommandRow) -> UITableViewCell? {
- guard let sectionIndex = sections.firstIndex(of: Section.emaLinkCommands) else
- {
- return nil
- }
- return tableView.cellForRow(at: IndexPath(row: row.rawValue, section: sectionIndex))
- }
- public override func numberOfSections(in tableView: UITableView) -> Int {
- return sections.count
- }
- public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
- guard section < sections.count else {
- return 0
- }
-
- switch sections[section] {
- case .device:
- return deviceRows.count
- case .rileyLinkCommands:
- return RileyLinkCommandRow.allCases.count
- case .emaLinkCommands:
- return EmaLinkCommandRow.allCases.count
- case .configureCommand:
- return OrangeConfigureCommandRow.allCases.count
- case .orangeLinkCommands:
- let count = OrangeLinkCommandRow.allCases.count
- return hasPiezo ? count : count-1
- case .alert:
- return AlertRow.allCases.count
- }
- }
-
- @objc
- func switchAction(sender: RileyLinkSwitch) {
- switch sections[sender.section] {
- case .orangeLinkCommands:
- switch OrangeLinkCommandRow(rawValue: sender.index)! {
- case .yellow:
- if sender.isOn {
- device.orangeAction(.yellow)
- } else {
- device.orangeAction(.off)
- }
- yellowOn = sender.isOn
- redOn = false
- case .red:
- if sender.isOn {
- device.orangeAction(.red)
- } else {
- device.orangeAction(.off)
- }
- yellowOn = false
- redOn = sender.isOn
- case .shake:
- if sender.isOn {
- device.orangeAction(.shake)
- } else {
- device.orangeAction(.shakeOff)
- }
- shakeOn = sender.isOn
- default:
- break
- }
- case .configureCommand:
- switch OrangeConfigureCommandRow(rawValue: sender.index)! {
- case .connectionLED:
- device.setOrangeConfig(.connectionLED, isOn: sender.isOn)
- ledOn = sender.isOn
- case .connectionVibrate:
- device.setOrangeConfig(.connectionVibrate, isOn: sender.isOn)
- vibrationOn = sender.isOn
- }
- default:
- break
- }
- tableView.reloadData()
- }
-
- var yellowOn = false
- var redOn = false
- var shakeOn = false
- private var ledOn: Bool = false
- private var vibrationOn: Bool = false
- var voltage: Float?
- public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
- let cell: RileyLinkCell
- if let reusableCell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier) as? RileyLinkCell {
- cell = reusableCell
- } else {
- cell = RileyLinkCell(style: .value1, reuseIdentifier: CellIdentifier)
- cell.switchView.addTarget(self, action: #selector(switchAction(sender:)), for: .valueChanged)
- }
-
- let switchView = cell.switchView
- switchView.isHidden = true
- switchView.index = indexPath.row
- switchView.section = indexPath.section
-
- cell.accessoryType = .none
- cell.detailTextLabel?.text = nil
- switch sections[indexPath.section] {
- case .device:
- switch deviceRows[indexPath.row] {
- case .customName:
- cell.textLabel?.text = LocalizedString("Name", comment: "The title of the cell showing device name")
- cell.detailTextLabel?.text = device.name
- cell.accessoryType = .disclosureIndicator
- case .version:
- cell.textLabel?.text = LocalizedString("Firmware", comment: "The title of the cell showing firmware version")
- cell.detailTextLabel?.text = firmwareVersion
- case .connection:
- cell.textLabel?.text = LocalizedString("Connection State", comment: "The title of the cell showing BLE connection state")
- cell.detailTextLabel?.text = device.peripheralState.description
- case .rssi:
- cell.textLabel?.text = LocalizedString("Signal Strength", comment: "The title of the cell showing BLE signal strength (RSSI)")
- cell.setDetailRSSI(bleRSSI, formatter: integerFormatter)
- case .uptime:
- cell.textLabel?.text = LocalizedString("Uptime", comment: "The title of the cell showing uptime")
- cell.setDetailAge(uptime)
- case .frequency:
- cell.textLabel?.text = LocalizedString("Frequency", comment: "The title of the cell showing current rileylink frequency")
- cell.setDetailFrequency(frequency, formatter: frequencyFormatter)
- case .battery:
- cell.textLabel?.text = LocalizedString("Battery level", comment: "The title of the cell showing battery level")
- cell.setDetailBatteryLevel(battery)
- case .voltage:
- cell.textLabel?.text = LocalizedString("Voltage", comment: "The title of the cell showing ORL")
- cell.setVoltage(voltage)
- }
- case .alert:
- switch AlertRow(rawValue: indexPath.row)! {
- case .battery:
- cell.accessoryType = .disclosureIndicator
- cell.textLabel?.text = LocalizedString("Low Battery Alert", comment: "The title of the cell showing battery level")
- cell.setBatteryAlert(batteryAlertLevel, formatter: integerFormatter)
- }
- case .rileyLinkCommands:
- switch RileyLinkCommandRow(rawValue: indexPath.row)! {
- case .diagnosticLEDSMode:
- cell.textLabel?.text = LocalizedString("Diagnostic LEDs", comment: "The title of the command to update diagnostic LEDs")
- cell.setLEDMode(ledMode)
- case .getStatistics:
- cell.textLabel?.text = LocalizedString("Get RileyLink Statistics", comment: "The title of the command to fetch RileyLink statistics")
- }
- case .emaLinkCommands:
- switch EmaLinkCommandRow(rawValue: indexPath.row)! {
- case .logicLEDSMode:
- cell.textLabel?.text = LocalizedString("Invert LED Logic", comment: "The title of the command to invert BLE connection LED logic")
- cell.setLEDMode(ledMode)
- case .getStatistics:
- cell.textLabel?.text = LocalizedString("Get RileyLink Statistics", comment: "The title of the command to fetch RileyLink statistics")
- }
- case .orangeLinkCommands:
- cell.accessoryType = .disclosureIndicator
- cell.detailTextLabel?.text = nil
-
- switch OrangeLinkCommandRow(rawValue: indexPath.row)! {
- case .yellow:
- switchView.isHidden = false
- cell.accessoryType = .none
- switchView.isOn = yellowOn
- cell.textLabel?.text = LocalizedString("Lighten Yellow LED", comment: "The title of the cell showing Lighten Yellow LED")
- case .red:
- switchView.isHidden = false
- cell.accessoryType = .none
- switchView.isOn = redOn
- cell.textLabel?.text = LocalizedString("Lighten Red LED", comment: "The title of the cell showing Lighten Red LED")
- case .shake:
- switchView.isHidden = false
- switchView.isOn = shakeOn
- cell.accessoryType = .none
- cell.textLabel?.text = LocalizedString("Test Vibration", comment: "The title of the cell showing Test Vibration")
- case .findDevice:
- cell.textLabel?.text = LocalizedString("Find Device", comment: "The title of the cell for sounding device finding piezo")
- cell.detailTextLabel?.text = nil
- }
- case .configureCommand:
- switch OrangeConfigureCommandRow(rawValue: indexPath.row)! {
- case .connectionLED:
- switchView.isHidden = false
- switchView.isOn = ledOn
- cell.accessoryType = .none
- cell.textLabel?.text = LocalizedString("Connection LED", comment: "The title of the cell for connection LED")
- case .connectionVibrate:
- switchView.isHidden = false
- switchView.isOn = vibrationOn
- cell.accessoryType = .none
- cell.textLabel?.text = LocalizedString("Connection Vibration", comment: "The title of the cell for connection vibration")
- }
- }
- return cell
- }
- public override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
- switch sections[section] {
- case .device:
- return LocalizedString("Device", comment: "The title of the section describing the device")
- case .rileyLinkCommands:
- return LocalizedString("Test Commands", comment: "The title of the section for rileylink commands")
- case .emaLinkCommands:
- return LocalizedString("Test Commands", comment: "The title of the section for emalink commands")
- case .orangeLinkCommands:
- return LocalizedString("Test Commands", comment: "The title of the section for orangelink commands")
- case .configureCommand:
- return LocalizedString("Connection Monitoring", comment: "The title of the section for connection monitoring")
- case .alert:
- return LocalizedString("Alert", comment: "The title of the section for alerts")
- }
- }
- // MARK: - UITableViewDelegate
- public override func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
- switch sections[indexPath.section] {
- case .device:
- switch deviceRows[indexPath.row] {
- case .customName:
- return true
- default:
- return false
- }
- case .configureCommand:
- return false
- case .orangeLinkCommands:
- switch OrangeLinkCommandRow(rawValue: indexPath.row)! {
- case .findDevice:
- return true
- default:
- return false
- }
- case .rileyLinkCommands:
- return device.peripheralState == .connected
- case .emaLinkCommands:
- return device.peripheralState == .connected
- case .alert:
- return true
- }
- }
- public override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
- switch sections[indexPath.section] {
- case .device:
- switch deviceRows[indexPath.row] {
- case .customName:
- let vc = TextFieldTableViewController()
- if let cell = tableView.cellForRow(at: indexPath) {
- vc.title = cell.textLabel?.text
- vc.value = device.name
- vc.delegate = self
- vc.keyboardType = .default
- }
- show(vc, sender: indexPath)
- default:
- break
- }
- case .rileyLinkCommands:
- var vc: CommandResponseViewController?
- switch RileyLinkCommandRow(rawValue: indexPath.row)! {
- case .diagnosticLEDSMode:
- let nextMode: RileyLinkLEDMode
- switch ledMode {
- case.on:
- nextMode = .off
- default:
- nextMode = .on
- }
- vc = .setDiagnosticLEDMode(device: device, mode: nextMode)
- case .getStatistics:
- vc = .getStatistics(device: device)
- }
- if let cell = tableView.cellForRow(at: indexPath) {
- vc?.title = cell.textLabel?.text
- }
- if let vc = vc {
- show(vc, sender: indexPath)
- }
- case .emaLinkCommands:
- var vc: CommandResponseViewController?
- switch EmaLinkCommandRow(rawValue: indexPath.row)! {
- case .logicLEDSMode:
- let nextMode: RileyLinkLEDMode
- switch ledMode {
- case.on:
- nextMode = .off
- default:
- nextMode = .on
- }
- vc = .setDiagnosticLEDMode(device: device, mode: nextMode)
- case .getStatistics:
- vc = .getStatistics(device: device)
- }
- if let cell = tableView.cellForRow(at: indexPath) {
- vc?.title = cell.textLabel?.text
- }
- if let vc = vc {
- show(vc, sender: indexPath)
- }
- case .orangeLinkCommands:
- switch OrangeLinkCommandRow(rawValue: indexPath.row)! {
- case .findDevice:
- device.findDevice()
- tableView.deselectRow(at: indexPath, animated: true)
- default:
- break
- }
- case .configureCommand:
- break
- case .alert:
- switch AlertRow(rawValue: indexPath.row)! {
- case .battery:
- let alert = UIAlertController.init(title: LocalizedString("Battery level Alert", comment: "Header of list showing battery level alert options"), message: nil, preferredStyle: .actionSheet)
- let action = UIAlertAction.init(title: LocalizedString("OFF", comment: "Battery level alert OFF in list of options"), style: .default) { _ in
- self.batteryAlertLevel = nil
- self.tableView.reloadData()
- }
- alert.addAction(action)
- for value in [20,30,40,50] {
- let action = UIAlertAction.init(title: "\(value)%", style: .default) { _ in
- self.batteryAlertLevel = value
- self.tableView.reloadData()
- }
- alert.addAction(action)
- }
- present(alert, animated: true, completion: nil)
- }
- }
- }
- }
- extension RileyLinkDeviceTableViewController: TextFieldTableViewControllerDelegate {
- public func textFieldTableViewControllerDidReturn(_ controller: TextFieldTableViewController) {
- _ = navigationController?.popViewController(animated: true)
- }
- public func textFieldTableViewControllerDidEndEditing(_ controller: TextFieldTableViewController) {
- if let indexPath = tableView.indexPathForSelectedRow {
- switch sections[indexPath.section] {
- case .device:
- switch deviceRows[indexPath.row] {
- case .customName:
- device.setCustomName(controller.value!)
- default:
- break
- }
- default:
- break
- }
- }
- }
- }
- private extension TimeInterval {
- func format(using units: NSCalendar.Unit) -> String? {
- let formatter = DateComponentsFormatter()
- formatter.allowedUnits = units
- formatter.unitsStyle = .full
- formatter.zeroFormattingBehavior = .dropLeading
- formatter.maximumUnitCount = 2
-
- return formatter.string(from: self)
- }
- }
- private extension UITableViewCell {
- func setDetailDate(_ date: Date?, formatter: DateFormatter) {
- if let date = date {
- detailTextLabel?.text = formatter.string(from: date)
- } else {
- detailTextLabel?.text = "-"
- }
- }
- func setDetailRSSI(_ decibles: Int?, formatter: NumberFormatter) {
- detailTextLabel?.text = formatter.decibleString(from: decibles) ?? "-"
- }
-
- func setDetailAge(_ age: TimeInterval?) {
- if let age = age {
- detailTextLabel?.text = age.format(using: [.day, .hour, .minute])
- } else {
- detailTextLabel?.text = ""
- }
- }
-
- func setDetailBatteryLevel(_ batteryLevel: Int?) {
- if let batteryLevel = batteryLevel {
- detailTextLabel?.text = "\(batteryLevel)" + " %"
- } else {
- detailTextLabel?.text = ""
- }
- }
-
- func setDetailFrequency(_ frequency: Measurement<UnitFrequency>?, formatter: MeasurementFormatter) {
- if let frequency = frequency {
- detailTextLabel?.text = formatter.string(from: frequency)
- } else {
- detailTextLabel?.text = ""
- }
- }
-
- func setLEDMode(_ mode: RileyLinkLEDMode?) {
- switch mode {
- case .on:
- detailTextLabel?.text = LocalizedString("On", comment: "Text indicating LED Mode is on")
- case .off:
- detailTextLabel?.text = LocalizedString("Off", comment: "Text indicating LED Mode is off")
- case .auto:
- detailTextLabel?.text = LocalizedString("Auto", comment: "Text indicating LED Mode is auto")
- case .none:
- detailTextLabel?.text = ""
- }
- }
-
- func setVoltage(_ voltage: Float?) {
- if let voltage = voltage {
- detailTextLabel?.text = String(format: "%.1f%", voltage)
- } else {
- detailTextLabel?.text = ""
- }
- }
-
- func setBatteryAlert(_ level: Int?, formatter: NumberFormatter) {
- detailTextLabel?.text = formatter.percentString(from: level) ?? LocalizedString("Off", comment: "Detail text when battery alert disabled.")
- }
- }
|