|
|
@@ -14,6 +14,30 @@ 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")
|
|
|
@@ -42,6 +66,15 @@ public class RileyLinkDeviceTableViewController: UITableViewController {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private var battery: Int? {
|
|
|
+ didSet {
|
|
|
+ guard isViewLoaded else {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ cellForRow(.battery)?.setDetailBatteryLevel(battery)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private var frequency: Measurement<UnitFrequency>? {
|
|
|
didSet {
|
|
|
guard isViewLoaded else {
|
|
|
@@ -51,6 +84,15 @@ public class RileyLinkDeviceTableViewController: UITableViewController {
|
|
|
cellForRow(.frequency)?.setDetailFrequency(frequency, formatter: frequencyFormatter)
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ private var ledMode: RileyLinkLEDMode? {
|
|
|
+ didSet {
|
|
|
+ guard isViewLoaded else {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ cellForRow(.diagnosticLEDSMode)?.setLEDMode(ledMode)
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
var rssiFetchTimer: Timer? {
|
|
|
willSet {
|
|
|
@@ -58,23 +100,31 @@ public class RileyLinkDeviceTableViewController: UITableViewController {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private lazy var frequencyFormatter: MeasurementFormatter = {
|
|
|
- let formatter = MeasurementFormatter()
|
|
|
-
|
|
|
- formatter.numberFormatter = decimalFormatter
|
|
|
-
|
|
|
- return formatter
|
|
|
- }()
|
|
|
-
|
|
|
-
|
|
|
+ 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) {
|
|
|
+ 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) {
|
|
|
@@ -85,7 +135,63 @@ public class RileyLinkDeviceTableViewController: UITableViewController {
|
|
|
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()
|
|
|
}
|
|
|
|
|
|
@@ -93,10 +199,17 @@ public class RileyLinkDeviceTableViewController: UITableViewController {
|
|
|
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.firmwareDescription
|
|
|
+ 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()
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -126,7 +239,14 @@ public class RileyLinkDeviceTableViewController: UITableViewController {
|
|
|
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
|
|
|
@@ -144,27 +264,30 @@ public class RileyLinkDeviceTableViewController: UITableViewController {
|
|
|
|
|
|
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
|
|
|
- },
|
|
|
+ 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
|
|
|
- }
|
|
|
- },
|
|
|
+ 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)
|
|
|
- }
|
|
|
- },
|
|
|
+ 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()
|
|
|
- },
|
|
|
+ self?.updateDeviceStatus()
|
|
|
+ },
|
|
|
+ center.addObserver(forName: .DeviceStatusUpdated, object: device, queue: mainQueue) { [weak self] (note) in
|
|
|
+ self?.updateDeviceStatus()
|
|
|
+ },
|
|
|
]
|
|
|
}
|
|
|
|
|
|
@@ -181,10 +304,38 @@ public class RileyLinkDeviceTableViewController: UITableViewController {
|
|
|
|
|
|
updateRSSI()
|
|
|
|
|
|
- updateFrequency()
|
|
|
+ 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) {
|
|
|
@@ -206,70 +357,213 @@ public class RileyLinkDeviceTableViewController: UITableViewController {
|
|
|
|
|
|
private lazy var integerFormatter = NumberFormatter()
|
|
|
|
|
|
- private lazy var measurementFormatter: MeasurementFormatter = {
|
|
|
- let formatter = MeasurementFormatter()
|
|
|
-
|
|
|
- formatter.numberFormatter = decimalFormatter
|
|
|
-
|
|
|
- return formatter
|
|
|
- }()
|
|
|
-
|
|
|
private lazy var decimalFormatter: NumberFormatter = {
|
|
|
let decimalFormatter = NumberFormatter()
|
|
|
|
|
|
decimalFormatter.numberStyle = .decimal
|
|
|
- decimalFormatter.minimumSignificantDigits = 5
|
|
|
-
|
|
|
+ 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, CaseCountable {
|
|
|
+ private enum Section: Int, CaseIterable {
|
|
|
case device
|
|
|
- case commands
|
|
|
+ case alert
|
|
|
+ case configureCommand
|
|
|
+ case orangeLinkCommands
|
|
|
+ case rileyLinkCommands
|
|
|
+ case emaLinkCommands
|
|
|
}
|
|
|
+
|
|
|
+ private var sections: [Section] = []
|
|
|
|
|
|
- private enum DeviceRow: Int, CaseCountable {
|
|
|
+ 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? {
|
|
|
- return tableView.cellForRow(at: IndexPath(row: row.rawValue, section: Section.device.rawValue))
|
|
|
+ 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 Section.count
|
|
|
+ return sections.count
|
|
|
}
|
|
|
|
|
|
public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
|
|
- switch Section(rawValue: section)! {
|
|
|
- case .device:
|
|
|
- return DeviceRow.count
|
|
|
- case .commands:
|
|
|
+ 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: UITableViewCell
|
|
|
+ let cell: RileyLinkCell
|
|
|
|
|
|
- if let reusableCell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier) {
|
|
|
+ if let reusableCell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier) as? RileyLinkCell {
|
|
|
cell = reusableCell
|
|
|
} else {
|
|
|
- cell = UITableViewCell(style: .value1, reuseIdentifier: CellIdentifier)
|
|
|
+ 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 Section(rawValue: indexPath.section)! {
|
|
|
+ switch sections[indexPath.section] {
|
|
|
case .device:
|
|
|
- switch DeviceRow(rawValue: indexPath.row)! {
|
|
|
+ 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
|
|
|
@@ -289,44 +583,128 @@ public class RileyLinkDeviceTableViewController: UITableViewController {
|
|
|
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 = NSLocalizedString("Battery level", comment: "The title of the cell showing battery level")
|
|
|
+ cell.setDetailBatteryLevel(battery)
|
|
|
+ case .voltage:
|
|
|
+ cell.textLabel?.text = NSLocalizedString("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 = NSLocalizedString("Low Battery Alert", comment: "The title of the cell showing battery level")
|
|
|
+ cell.setBatteryAlert(batteryAlertLevel, formatter: integerFormatter)
|
|
|
}
|
|
|
- case .commands:
|
|
|
+ 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 = NSLocalizedString("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 = NSLocalizedString("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 = NSLocalizedString("Test Vibration", comment: "The title of the cell showing Test Vibration")
|
|
|
+ case .findDevice:
|
|
|
+ cell.textLabel?.text = NSLocalizedString("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 = NSLocalizedString("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 = NSLocalizedString("Connection Vibration", comment: "The title of the cell for connection vibration")
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return cell
|
|
|
}
|
|
|
|
|
|
public override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
|
|
- switch Section(rawValue: section)! {
|
|
|
+ switch sections[section] {
|
|
|
case .device:
|
|
|
return LocalizedString("Device", comment: "The title of the section describing the device")
|
|
|
- case .commands:
|
|
|
- return LocalizedString("Commands", comment: "The title of the section describing commands")
|
|
|
+ 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 Section(rawValue: indexPath.section)! {
|
|
|
+ switch sections[indexPath.section] {
|
|
|
case .device:
|
|
|
- switch DeviceRow(rawValue: indexPath.row)! {
|
|
|
+ switch deviceRows[indexPath.row] {
|
|
|
case .customName:
|
|
|
return true
|
|
|
default:
|
|
|
return false
|
|
|
}
|
|
|
- case .commands:
|
|
|
+ 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 Section(rawValue: indexPath.section)! {
|
|
|
+ switch sections[indexPath.section] {
|
|
|
case .device:
|
|
|
- switch DeviceRow(rawValue: indexPath.row)! {
|
|
|
+ switch deviceRows[indexPath.row] {
|
|
|
case .customName:
|
|
|
let vc = TextFieldTableViewController()
|
|
|
if let cell = tableView.cellForRow(at: indexPath) {
|
|
|
@@ -340,8 +718,83 @@ public class RileyLinkDeviceTableViewController: UITableViewController {
|
|
|
default:
|
|
|
break
|
|
|
}
|
|
|
- case .commands:
|
|
|
+ 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: "Battery level Alert", message: nil, preferredStyle: .actionSheet)
|
|
|
+ let action = UIAlertAction.init(title: "OFF", 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)
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -354,9 +807,9 @@ extension RileyLinkDeviceTableViewController: TextFieldTableViewControllerDelega
|
|
|
|
|
|
public func textFieldTableViewControllerDidEndEditing(_ controller: TextFieldTableViewController) {
|
|
|
if let indexPath = tableView.indexPathForSelectedRow {
|
|
|
- switch Section(rawValue: indexPath.section)! {
|
|
|
+ switch sections[indexPath.section] {
|
|
|
case .device:
|
|
|
- switch DeviceRow(rawValue: indexPath.row)! {
|
|
|
+ switch deviceRows[indexPath.row] {
|
|
|
case .customName:
|
|
|
device.setCustomName(controller.value!)
|
|
|
default:
|
|
|
@@ -402,6 +855,14 @@ private extension UITableViewCell {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ 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)
|
|
|
@@ -409,5 +870,29 @@ private extension UITableViewCell {
|
|
|
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) ?? NSLocalizedString("Off", comment: "Detail text when battery alert disabled.")
|
|
|
+ }
|
|
|
}
|