Skip to content

Commit 5a3afa6

Browse files
committed
Tidying up some code and prepping for Settings tab
1 parent 391d961 commit 5a3afa6

12 files changed

Lines changed: 246 additions & 198 deletions

Infini-iOS.xcodeproj/project.pbxproj

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@
2727
26A6315E26C498B7005AE404 /* NordicDFU in Frameworks */ = {isa = PBXBuildFile; productRef = 26A6315D26C498B7005AE404 /* NordicDFU */; };
2828
26A6316026C4BC25005AE404 /* DFUView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26A6315F26C4BC25005AE404 /* DFUView.swift */; };
2929
26A6316326C4C6D6005AE404 /* BLEConnectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26A6316226C4C6D6005AE404 /* BLEConnectView.swift */; };
30+
26D7816526C9EB3800BBF555 /* BLEDelegates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26D7816426C9EB3800BBF555 /* BLEDelegates.swift */; };
31+
26D7816726C9EC3100BBF555 /* BLEManagerExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26D7816626C9EC3100BBF555 /* BLEManagerExtensions.swift */; };
32+
26D7816A26C9F04400BBF555 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26D7816926C9F04400BBF555 /* SettingsView.swift */; };
33+
26D7816C26C9F9EC00BBF555 /* SettingsFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26D7816B26C9F9EC00BBF555 /* SettingsFunctions.swift */; };
3034
26F426EF26C72D7D00D0866B /* BLEStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26F426EE26C72D7D00D0866B /* BLEStatusView.swift */; };
31-
26F426F226C8468300D0866B /* SwiftUTI in Frameworks */ = {isa = PBXBuildFile; productRef = 26F426F126C8468300D0866B /* SwiftUTI */; };
3235
/* End PBXBuildFile section */
3336

3437
/* Begin PBXContainerItemProxy section */
@@ -74,6 +77,10 @@
7477
26A6315A26C49841005AE404 /* DFU.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DFU.swift; sourceTree = "<group>"; };
7578
26A6315F26C4BC25005AE404 /* DFUView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DFUView.swift; sourceTree = "<group>"; };
7679
26A6316226C4C6D6005AE404 /* BLEConnectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BLEConnectView.swift; sourceTree = "<group>"; };
80+
26D7816426C9EB3800BBF555 /* BLEDelegates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BLEDelegates.swift; sourceTree = "<group>"; };
81+
26D7816626C9EC3100BBF555 /* BLEManagerExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BLEManagerExtensions.swift; sourceTree = "<group>"; };
82+
26D7816926C9F04400BBF555 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
83+
26D7816B26C9F9EC00BBF555 /* SettingsFunctions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsFunctions.swift; sourceTree = "<group>"; };
7784
26F426EE26C72D7D00D0866B /* BLEStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BLEStatusView.swift; sourceTree = "<group>"; };
7885
/* End PBXFileReference section */
7986

@@ -83,7 +90,6 @@
8390
buildActionMask = 2147483647;
8491
files = (
8592
26A6315E26C498B7005AE404 /* NordicDFU in Frameworks */,
86-
26F426F226C8468300D0866B /* SwiftUTI in Frameworks */,
8793
);
8894
runOnlyForDeploymentPostprocessing = 0;
8995
};
@@ -128,6 +134,7 @@
128134
264BFE4026BC51CE0050A223 /* Infini-iOS */ = {
129135
isa = PBXGroup;
130136
children = (
137+
26D7816826C9F02A00BBF555 /* Settings */,
131138
264BFE4126BC51CE0050A223 /* Infini_iOSApp.swift */,
132139
264BFE4326BC51CE0050A223 /* ContentView.swift */,
133140
264DB80926C62EAC00E812C3 /* View Components */,
@@ -175,6 +182,9 @@
175182
isa = PBXGroup;
176183
children = (
177184
264DB80A26C62ED600E812C3 /* SideMenu.swift */,
185+
26A6316226C4C6D6005AE404 /* BLEConnectView.swift */,
186+
26F426EE26C72D7D00D0866B /* BLEStatusView.swift */,
187+
26A6315F26C4BC25005AE404 /* DFUView.swift */,
178188
264DB80C26C633CF00E812C3 /* PageSwitcher.swift */,
179189
);
180190
path = "View Components";
@@ -200,7 +210,6 @@
200210
26A6315926C49839005AE404 /* DFU */ = {
201211
isa = PBXGroup;
202212
children = (
203-
26A6315F26C4BC25005AE404 /* DFUView.swift */,
204213
26A6315A26C49841005AE404 /* DFU.swift */,
205214
);
206215
path = DFU;
@@ -209,13 +218,22 @@
209218
26A6316126C4C6BB005AE404 /* BLE */ = {
210219
isa = PBXGroup;
211220
children = (
212-
26A6316226C4C6D6005AE404 /* BLEConnectView.swift */,
213-
26F426EE26C72D7D00D0866B /* BLEStatusView.swift */,
214221
264BFE7326BC526C0050A223 /* BLEManager.swift */,
222+
26D7816426C9EB3800BBF555 /* BLEDelegates.swift */,
223+
26D7816626C9EC3100BBF555 /* BLEManagerExtensions.swift */,
215224
);
216225
path = BLE;
217226
sourceTree = "<group>";
218227
};
228+
26D7816826C9F02A00BBF555 /* Settings */ = {
229+
isa = PBXGroup;
230+
children = (
231+
26D7816926C9F04400BBF555 /* SettingsView.swift */,
232+
26D7816B26C9F9EC00BBF555 /* SettingsFunctions.swift */,
233+
);
234+
path = Settings;
235+
sourceTree = "<group>";
236+
};
219237
/* End PBXGroup section */
220238

221239
/* Begin PBXNativeTarget section */
@@ -234,7 +252,6 @@
234252
name = "Infini-iOS";
235253
packageProductDependencies = (
236254
26A6315D26C498B7005AE404 /* NordicDFU */,
237-
26F426F126C8468300D0866B /* SwiftUTI */,
238255
);
239256
productName = "Infini-iOS";
240257
productReference = 264BFE3E26BC51CE0050A223 /* Infini-iOS.app */;
@@ -354,8 +371,11 @@
354371
isa = PBXSourcesBuildPhase;
355372
buildActionMask = 2147483647;
356373
files = (
374+
26D7816C26C9F9EC00BBF555 /* SettingsFunctions.swift in Sources */,
357375
264BFE7B26BCB9510050A223 /* Infini_iOS.xcdatamodeld in Sources */,
376+
26D7816726C9EC3100BBF555 /* BLEManagerExtensions.swift in Sources */,
358377
264BFE4B26BC51CF0050A223 /* Persistence.swift in Sources */,
378+
26D7816A26C9F04400BBF555 /* SettingsView.swift in Sources */,
359379
264BFE4426BC51CE0050A223 /* ContentView.swift in Sources */,
360380
26A6315526C0297A005AE404 /* Notifications.swift in Sources */,
361381
26A6316026C4BC25005AE404 /* DFUView.swift in Sources */,
@@ -368,6 +388,7 @@
368388
264BFE4226BC51CE0050A223 /* Infini_iOSApp.swift in Sources */,
369389
264BFE7626BC52720050A223 /* HexStringToData.swift in Sources */,
370390
26A6316326C4C6D6005AE404 /* BLEConnectView.swift in Sources */,
391+
26D7816526C9EB3800BBF555 /* BLEDelegates.swift in Sources */,
371392
26A6315B26C49841005AE404 /* DFU.swift in Sources */,
372393
);
373394
runOnlyForDeploymentPostprocessing = 0;
@@ -716,11 +737,6 @@
716737
package = 26A6315C26C498B7005AE404 /* XCRemoteSwiftPackageReference "IOS-DFU-Library" */;
717738
productName = NordicDFU;
718739
};
719-
26F426F126C8468300D0866B /* SwiftUTI */ = {
720-
isa = XCSwiftPackageProductDependency;
721-
package = 26F426F026C8468300D0866B /* XCRemoteSwiftPackageReference "SwiftUTI" */;
722-
productName = SwiftUTI;
723-
};
724740
/* End XCSwiftPackageProductDependency section */
725741

726742
/* Begin XCVersionGroup section */

Infini-iOS/BLE/BLEDelegates.swift

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
//
2+
// BLEDelegates.swift
3+
// Infini-iOS
4+
//
5+
// Created by xan-m on 8/15/21.
6+
//
7+
//
8+
9+
10+
import Foundation
11+
import CoreBluetooth
12+
13+
14+
extension BLEManager: CBPeripheralDelegate {
15+
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
16+
guard let services = peripheral.services else { return }
17+
18+
for service in services {
19+
peripheral.discoverCharacteristics(nil, for:service)
20+
}
21+
}
22+
23+
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
24+
guard let characteristics = service.characteristics else { return }
25+
26+
for characteristic in characteristics {
27+
if characteristic.properties.contains(.read) {
28+
peripheral.readValue(for: characteristic)
29+
}
30+
31+
// subscribe to HRM, battery, and music control characteristics
32+
if characteristic.properties.contains(.notify) {
33+
switch characteristic.uuid {
34+
case musicControlCBUUID:
35+
peripheral.setNotifyValue(true, for: characteristic)
36+
case hrmCBUUID:
37+
peripheral.setNotifyValue(true, for: characteristic)
38+
case batCBUUID:
39+
peripheral.setNotifyValue(true, for: characteristic)
40+
default:
41+
break
42+
}
43+
peripheral.setNotifyValue(true, for: characteristic)
44+
}
45+
46+
if characteristic.properties.contains(.write) {
47+
if characteristic.uuid == notifyCBUUID {
48+
// I'm sure there's a less clunky way to grab the full characteristic for the sendNotification() function, but this works fine for now
49+
notifyCharacteristic = characteristic
50+
sendNotification(notification: "iOS Connected!")
51+
}
52+
}
53+
}
54+
}
55+
56+
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
57+
switch characteristic.uuid {
58+
case musicControlCBUUID:
59+
// listen for the music controller notifications
60+
musicChars.control = characteristic
61+
let musicControl = [UInt8](characteristic.value!)
62+
controlMusic(controlNumber: Int(musicControl[0]))
63+
64+
case musicTrackCBUUID:
65+
// select track characteristic for writing to music app
66+
musicChars.track = characteristic
67+
68+
case musicArtistCBUUID:
69+
// select artist characteristic for writing to music app
70+
musicChars.artist = characteristic
71+
72+
case hrmCBUUID:
73+
// read heart rate hex, convert to decimal
74+
heartBPM = "Reading"
75+
let bpm = heartRate(from: characteristic)
76+
heartBPM = String(bpm)
77+
78+
case batCBUUID:
79+
// read battery hex data, convert it to decimal
80+
batteryLevel = "Reading"
81+
let batData = [UInt8](characteristic.value!)
82+
batteryLevel = String(batData[0])
83+
84+
case timeCBUUID:
85+
// convert string with hex value of time to actual hex data, then write to PineTime
86+
peripheral.writeValue(currentTime().hexData, for: characteristic, type: .withResponse)
87+
88+
case firmwareCBUUID:
89+
firmwareVersion = "Reading"
90+
firmwareVersion = String(decoding: characteristic.value!, as: UTF8.self)
91+
default:
92+
break
93+
}
94+
}
95+
}

Infini-iOS/BLE/BLEManager.swift

Lines changed: 0 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -58,22 +58,17 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate {
5858

5959
myCentral = CBCentralManager(delegate: self, queue: nil)
6060
myCentral.delegate = self
61-
heartBPM = "Reading"
62-
batteryLevel = "Reading"
63-
firmwareVersion = "Reading"
6461

6562
}
6663

6764
func startScanning() {
68-
print("startScanning")
6965
myCentral.scanForPeripherals(withServices: nil, options: nil)
7066
isScanning = true
7167
peripherals = [Peripheral]()
7268
peripheralDictionary = [:]
7369
}
7470

7571
func stopScanning() {
76-
print("stopScanning")
7772
myCentral.stopScan()
7873
isScanning = false
7974
}
@@ -141,148 +136,3 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate {
141136
}
142137
}
143138

144-
extension BLEManager: CBPeripheralDelegate {
145-
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
146-
guard let services = peripheral.services else { return }
147-
148-
for service in services {
149-
peripheral.discoverCharacteristics(nil, for:service)
150-
}
151-
}
152-
153-
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
154-
guard let characteristics = service.characteristics else { return }
155-
156-
for characteristic in characteristics {
157-
if characteristic.properties.contains(.read) {
158-
peripheral.readValue(for: characteristic)
159-
}
160-
161-
// subscribe to all values that can be subscribed to.
162-
// TODO: separate this out and subscribe individually for each service in a separate .swift document so this isn't so monolithic
163-
if characteristic.properties.contains(.notify) {
164-
switch characteristic.uuid {
165-
case musicControlCBUUID:
166-
peripheral.setNotifyValue(true, for: characteristic)
167-
print("subscribed to", characteristic.uuid)
168-
case hrmCBUUID:
169-
peripheral.setNotifyValue(true, for: characteristic)
170-
print("subscribed to", characteristic.uuid)
171-
case batCBUUID:
172-
peripheral.setNotifyValue(true, for: characteristic)
173-
print("subscribed to", characteristic.uuid)
174-
default:
175-
break
176-
}
177-
peripheral.setNotifyValue(true, for: characteristic)
178-
}
179-
180-
if characteristic.properties.contains(.write) {
181-
if characteristic.uuid == notifyCBUUID {
182-
// I'm sure there's a less clunky way to grab the full characteristic for the sendNotification() function, but this works fine for now
183-
notifyCharacteristic = characteristic
184-
sendNotification(notification: "iOS Connected!")
185-
}
186-
}
187-
}
188-
}
189-
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
190-
switch characteristic.uuid {
191-
case musicControlCBUUID:
192-
// listen for the music controller notifications
193-
musicChars.control = characteristic
194-
let musicControl = [UInt8](characteristic.value!)
195-
controlMusic(controlNumber: Int(musicControl[0]))
196-
197-
case musicTrackCBUUID:
198-
// select track characteristic for writing to music app
199-
musicChars.track = characteristic
200-
201-
case musicArtistCBUUID:
202-
// select artist characteristic for writing to music app
203-
musicChars.artist = characteristic
204-
205-
case hrmCBUUID:
206-
// read heart rate hex, convert to decimal
207-
let bpm = heartRate(from: characteristic)
208-
heartBPM = String(bpm)
209-
210-
case batCBUUID:
211-
// read battery hex data, convert it to decimal
212-
let batData = [UInt8](characteristic.value!)
213-
batteryLevel = String(batData[0])
214-
215-
case timeCBUUID:
216-
// convert string with hex value of time to actual hex data, then write to PineTime
217-
peripheral.writeValue(currentTime().hexData, for: characteristic, type: .withResponse)
218-
219-
case firmwareCBUUID:
220-
firmwareVersion = String(decoding: characteristic.value!, as: UTF8.self)
221-
default:
222-
break
223-
}
224-
}
225-
226-
// this function converts string to ascii and writes to the selected characteristic. Used for notifications and music app
227-
func writeASCIIToPineTime(message: String, characteristic: CBCharacteristic) {
228-
let writeData = message.data(using: .ascii)!
229-
infiniTime.writeValue(writeData, for: characteristic, type: .withResponse)
230-
}
231-
232-
233-
// function to translate heart rate to decimal, copied straight up from this tut: https://www.raywenderlich.com/231-core-bluetooth-tutorial-for-ios-heart-rate-monitor#toc-anchor-014
234-
private func heartRate(from characteristic: CBCharacteristic) -> Int {
235-
guard let characteristicData = characteristic.value else { return -1 }
236-
let byteArray = [UInt8](characteristicData)
237-
238-
let firstBitValue = byteArray[0] & 0x01
239-
if firstBitValue == 0 {
240-
// Heart Rate Value Format is in the 2nd byte
241-
return Int(byteArray[1])
242-
} else {
243-
// Heart Rate Value Format is in the 2nd and 3rd bytes
244-
return (Int(byteArray[1]) << 8) + Int(byteArray[2])
245-
}
246-
}
247-
248-
// this function pulls date from phone, shuffles it into the correct order, and then hex-encodes it to a format that InfiniTime can understand
249-
private func currentTime() -> String {
250-
let now = Date() // current time
251-
252-
// formatting setup for the date, not including the year because we have to reformat the year hex to match what the PT expects
253-
let dateFormatter = DateFormatter()
254-
dateFormatter.dateFormat = "MM dd H m s e SSSS"
255-
256-
// prepare formatting for year
257-
let yearFormatter = DateFormatter()
258-
yearFormatter.dateFormat = "y"
259-
let yearString = yearFormatter.string(from: now)
260-
let intYear = Int(yearString)
261-
262-
// convert year string to hex-encoded string. conditionally prepend 0 in case by some miracle this application and your watch is still functional in the year 4096
263-
var hexYear = String (format: "%02X", intYear!)
264-
if hexYear.count == 3 {
265-
hexYear.insert("0", at: hexYear.startIndex)
266-
}
267-
268-
// infinitime (and BLE in general? I dunno...) requires the MSB first, so we have to switch the year from XXYY to YYXX
269-
var revYearChars = hexYear.suffix(2)
270-
revYearChars += hexYear.prefix(2)
271-
272-
var fullDateString = String(revYearChars)
273-
274-
let dateString = dateFormatter.string(from: now)
275-
let dateParts = dateString.components(separatedBy: " ")
276-
277-
// convert the rest of the date parts to hex, and append them to the date string
278-
279-
for part in dateParts {
280-
let intPart = Int(part)
281-
let hex = String(format: "%02X", intPart!)
282-
fullDateString.append(hex)
283-
}
284-
285-
// print(fullDateString) // debug
286-
return fullDateString
287-
}
288-
}

0 commit comments

Comments
 (0)