Commit 10c6e004c4cb6d3fe7f79bafed04059401f5a77c
1 parent
5507c724
feat:sleep data
Showing
9 changed files
with
162 additions
and
34 deletions
HDFwear.xcodeproj/project.pbxproj
... | ... | @@ -284,6 +284,7 @@ |
284 | 284 | 8473FB622B4BF1A200409148 /* TaskManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8473FB612B4BF1A200409148 /* TaskManager.swift */; }; |
285 | 285 | 847482762B03793C0004F0C2 /* NewWeatherModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847482752B03793C0004F0C2 /* NewWeatherModel.swift */; }; |
286 | 286 | 847672B82B074E43007DC2DE /* NewBeiDouContactModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847672B72B074E43007DC2DE /* NewBeiDouContactModel.swift */; }; |
287 | + 847AF36E2B4CF35F00E3456E /* NewSleepModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847AF36D2B4CF35F00E3456E /* NewSleepModel.swift */; }; | |
287 | 288 | B212F1FD2A14CE0400781D59 /* LaunchSetting.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B212F1FF2A14CE0400781D59 /* LaunchSetting.storyboard */; }; |
288 | 289 | B212F2052A14D28E00781D59 /* LaunchMyBodySettingVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B212F2042A14D28E00781D59 /* LaunchMyBodySettingVC.swift */; }; |
289 | 290 | B23AA1032A1879E200BB3902 /* SortPageSectionHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = B23AA1022A1879E200BB3902 /* SortPageSectionHeader.xib */; }; |
... | ... | @@ -660,6 +661,7 @@ |
660 | 661 | 8473FB612B4BF1A200409148 /* TaskManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskManager.swift; sourceTree = "<group>"; }; |
661 | 662 | 847482752B03793C0004F0C2 /* NewWeatherModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewWeatherModel.swift; sourceTree = "<group>"; }; |
662 | 663 | 847672B72B074E43007DC2DE /* NewBeiDouContactModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewBeiDouContactModel.swift; sourceTree = "<group>"; }; |
664 | + 847AF36D2B4CF35F00E3456E /* NewSleepModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewSleepModel.swift; sourceTree = "<group>"; }; | |
663 | 665 | 847D1C4A2B009FAC0097A96E /* 20231111ReadMe.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = 20231111ReadMe.md; sourceTree = "<group>"; }; |
664 | 666 | 847D2DE42B3D575F001BA7EF /* 20240110ReadMe.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = 20240110ReadMe.md; sourceTree = "<group>"; }; |
665 | 667 | B0BDC40FAF3CBA7B780ED655 /* Pods_HDFwear.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_HDFwear.framework; sourceTree = BUILT_PRODUCTS_DIR; }; |
... | ... | @@ -1276,6 +1278,7 @@ |
1276 | 1278 | 6C6051BD2760C0CB00286B37 /* WeatherModel.swift */, |
1277 | 1279 | 847482752B03793C0004F0C2 /* NewWeatherModel.swift */, |
1278 | 1280 | 847672B72B074E43007DC2DE /* NewBeiDouContactModel.swift */, |
1281 | + 847AF36D2B4CF35F00E3456E /* NewSleepModel.swift */, | |
1279 | 1282 | ); |
1280 | 1283 | path = Model; |
1281 | 1284 | sourceTree = "<group>"; |
... | ... | @@ -1610,6 +1613,7 @@ |
1610 | 1613 | B279A37A2A4AC2F800A7C7B6 /* BluetoothManager+Function.swift in Sources */, |
1611 | 1614 | 6C411EE1275DF6F3009B2E02 /* Data+Extension.swift in Sources */, |
1612 | 1615 | 6C80835927F698B700C13EB2 /* BackgroundProtectionVC.swift in Sources */, |
1616 | + 847AF36E2B4CF35F00E3456E /* NewSleepModel.swift in Sources */, | |
1613 | 1617 | 6C6F405C27434AC500F9473C /* ZCNavigationController.swift in Sources */, |
1614 | 1618 | 6C41D0BE275F5DAD00747BE4 /* LoaderButtonAnimationDelegate.swift in Sources */, |
1615 | 1619 | 6C41D0BC275F5DAD00747BE4 /* LoaderBallPulseRotateAnimation.swift in Sources */, | ... | ... |
HDFwear/20240110ReadMe.md
... | ... | @@ -94,3 +94,9 @@ BluetoothManager+Function |
94 | 94 | 压力数据 |
95 | 95 | func parsePressureData (_ content: [UInt8]) |
96 | 96 | 接收: [237, 126, 0, 1, 128, 32, 0, 1, 0, 0, 172, 113] |
97 | + | |
98 | +睡眠数据 | |
99 | + func parseSleepData (_ content: [UInt8]) | |
100 | + 发送: [237, 126, 0, 1, 0, 40, 0, 1, 0, 2, 6, 1, 140, 110] | |
101 | + 接收: [237, 126, 0, 1, 128, 25, 0, 0, 0, 77, 3, 7, 9, 101, 120, 119, 200, 0, 0, 14, 16, 10, 101, 120, 133, 216, 0, 0, 14, 16, 8, 101, 120, 147, 232, 0, 0, 14, 16, 7, 101, 120, 161, 248, 0, 0, 14, 16, 9, 101, 120, 176, 8, 0, 0, 14, 16, 10, 101, 120, 190, 24, 0, 0, 14, 16, 9, 101, 120, 204, 40, 0, 0, 14, 16, 101, 121, 46, 152, 101, 121, 60, 168, 0, 0, 14, 16, 224, 73] | |
102 | + 接收: [237, 126, 0, 1, 128, 25, 0, 1, 0, 1, 255, 79, 201] | ... | ... |
HDFwear/Home/HomeViewController.swift
... | ... | @@ -770,9 +770,9 @@ extension HomeViewController: XMLParserDelegate { |
770 | 770 | if queryArray.contains("Sleep"), let index = queryArray.firstIndex(of: "Sleep") { |
771 | 771 | BluetoothManager.shared.getSleepHistoryData() {[weak self] sleepArray, error in |
772 | 772 | self?.queryArray.remove(at: index) |
773 | - if error == nil { | |
774 | - SleepModel.addArray(sleepArray) | |
775 | - } | |
773 | +// if error == nil { | |
774 | +// SleepModel.addArray(sleepArray) | |
775 | +// } | |
776 | 776 | self?.syncPressure(day) |
777 | 777 | } |
778 | 778 | } else { | ... | ... |
HDFwear/Home/Model/NewSleepModel.swift
0 → 100644
1 | +import UIKit | |
2 | +import HandyJSON | |
3 | +import SwiftDate | |
4 | + | |
5 | +enum NewSleepType: UInt8 { | |
6 | + case nightSleep = 1 | |
7 | + case shortNap = 2 | |
8 | + case nightSleepAndNap = 3 | |
9 | +} | |
10 | + | |
11 | +enum NewSleepStatus: UInt8 { | |
12 | + case awake = 7 | |
13 | + case rapidEyeMovement = 8 | |
14 | + case lightSleep = 9 | |
15 | + case deepSleep = 10 | |
16 | +} | |
17 | + | |
18 | +class NewSleepModel: NSObject { | |
19 | + required override init() { } | |
20 | + | |
21 | + struct SleepFragment { | |
22 | + var sleepStatus: NewSleepStatus | |
23 | + var startTime: Date? | |
24 | + var duration: UInt32 | |
25 | + } | |
26 | + | |
27 | + struct NapFragment { | |
28 | + var startTime: Date? | |
29 | + var endTime: Date? | |
30 | + var duration: UInt32 | |
31 | + } | |
32 | + | |
33 | + var sleepType: NewSleepType = .nightSleep | |
34 | + var sleepFragmentCount: Int = 0 | |
35 | + var sleepFragments: [SleepFragment] = [] | |
36 | + var napFragments: [NapFragment] = [] | |
37 | + | |
38 | + init(sleepType: NewSleepType, sleepFragmentCount: Int, sleepFragments: [SleepFragment], napFragments: [NapFragment]) { | |
39 | + self.sleepType = sleepType | |
40 | + self.sleepFragmentCount = sleepFragmentCount | |
41 | + self.sleepFragments = sleepFragments | |
42 | + self.napFragments = napFragments | |
43 | + } | |
44 | + | |
45 | + class func toSleepModel(_ data: [UInt8]) -> NewSleepModel { | |
46 | + let sleepModel = NewSleepModel() | |
47 | + guard data.count >= 1 else { | |
48 | + return sleepModel // 数据长度不够 | |
49 | + } | |
50 | + sleepModel.sleepType = NewSleepType(rawValue:data[0]) ?? .nightSleep | |
51 | + switch sleepModel.sleepType { | |
52 | + case .nightSleep: | |
53 | + sleepModel.sleepFragmentCount = Int(data[1]) | |
54 | + guard data.count >= 2 + 9 * sleepModel.sleepFragmentCount else { | |
55 | + return sleepModel | |
56 | + } | |
57 | + sleepModel.sleepFragments = sleepModel.parseNightSleepData(data: Array(data[2..<2 + 9 * sleepModel.sleepFragmentCount])) | |
58 | + case .shortNap: | |
59 | + sleepModel.napFragments = sleepModel.parseNapData(data: Array(data[2..<data.count])) | |
60 | + case .nightSleepAndNap: | |
61 | + sleepModel.sleepFragmentCount = Int(data[1]) | |
62 | + guard data.count >= 2 + 9 * sleepModel.sleepFragmentCount else { | |
63 | + return sleepModel | |
64 | + } | |
65 | + sleepModel.sleepFragments = sleepModel.parseNightSleepData(data: Array(data[2..<2 + 9 * sleepModel.sleepFragmentCount])) | |
66 | + sleepModel.napFragments = sleepModel.parseNapData(data: Array(data[2 + 9 * sleepModel.sleepFragmentCount..<data.count])) | |
67 | + default: | |
68 | + break | |
69 | + } | |
70 | + return sleepModel | |
71 | + } | |
72 | + | |
73 | + func parseNightSleepData(data: [UInt8]) -> [SleepFragment] { | |
74 | + // 解析 SleepFragment 数组 | |
75 | + var sleepFragments = [SleepFragment]() | |
76 | + // 将数组分成9个一组 | |
77 | + for index in stride(from: 0, to: data.count, by: 9) { | |
78 | + let sleepStatus = NewSleepStatus(rawValue: data[index]) ?? .awake | |
79 | + let rawStartTime = UInt32(data[index + 1]) | | |
80 | + (UInt32(data[index + 2]) << 8) | | |
81 | + (UInt32(data[index + 3]) << 16) | | |
82 | + (UInt32(data[index + 4]) << 24) | |
83 | + let startTimeInterval = TimeInterval(rawStartTime) | |
84 | + let startTime = Date(timeIntervalSince1970: startTimeInterval) | |
85 | + let duration = UInt32(data[index + 5]) | (UInt32(data[index + 6]) << 8) | (UInt32(data[index + 7]) << 16) | (UInt32(data[index + 8]) << 24) | |
86 | + | |
87 | + let fragment = SleepFragment(sleepStatus: sleepStatus, startTime: startTime, duration: duration) | |
88 | + sleepFragments.append(fragment) | |
89 | + } | |
90 | + return sleepFragments | |
91 | + } | |
92 | + | |
93 | + func parseNapData(data: [UInt8]) -> [NapFragment] { | |
94 | + // 解析 NapFragment 数组 | |
95 | + var napFragments = [NapFragment]() | |
96 | + // 将数组分成12个一组 | |
97 | + for index in stride(from: 0, to: data.count, by: 12) { | |
98 | + let startTime = Date(timeIntervalSince1970: TimeInterval(UInt32(data[index]) | UInt32(data[index + 1]) << 8 | UInt32(data[index + 2]) << 16 | UInt32(data[index + 3]) << 24)) | |
99 | + let endTime = Date(timeIntervalSince1970: TimeInterval(UInt32(data[index + 4]) | UInt32(data[index + 5]) << 8 | UInt32(data[index + 6]) << 16 | UInt32(data[index + 7]) << 24)) | |
100 | + let duration = UInt32(data[index + 8]) | UInt32(data[index + 9]) << 8 | UInt32(data[index + 10]) << 16 | UInt32(data[index + 11]) << 24 | |
101 | + | |
102 | + let napFragment = NapFragment(startTime: startTime, endTime: endTime, duration: duration) | |
103 | + napFragments.append(napFragment) | |
104 | + } | |
105 | + return napFragments | |
106 | + } | |
107 | +} | ... | ... |
HDFwear/Mine/MineViewController.swift
... | ... | @@ -434,12 +434,11 @@ extension MineViewController: UITableViewDataSource, UITableViewDelegate { |
434 | 434 | let alert = UIAlertController(title: "plz select fetch type", message: nil, preferredStyle: .actionSheet) |
435 | 435 | |
436 | 436 | let archiveAction9 = UIAlertAction(title: "getSleepHistoryData", style: .default) { action in |
437 | - BluetoothManager.shared.getSleepHistoryData() { sleepArray, error in | |
437 | + BluetoothManager.shared.getSleepHistoryData(option: .now) { sleepModel, error in | |
438 | 438 | if error != nil { |
439 | 439 | print("getSleepHistoryData" + (error?.description ?? "")) |
440 | 440 | }else { |
441 | 441 | print("getSleepHistoryData success") |
442 | - SleepModel.addArray(sleepArray) | |
443 | 442 | } |
444 | 443 | } |
445 | 444 | } | ... | ... |
HDFwear/Tools/BleMessage+Function.swift
... | ... | @@ -124,8 +124,8 @@ extension BleMessage { |
124 | 124 | return createDataPacket(key: .setNoDisturb, bytes: bytes) |
125 | 125 | } |
126 | 126 | |
127 | - func getSyncCmd(_ type: SyncType) -> Data { | |
128 | - let bytes: [UInt8] = [type.rawValue] | |
127 | + func getSyncCmd(_ type: SyncType, _ option:SyncOption = .now) -> Data { | |
128 | + let bytes: [UInt8] = [type.rawValue, option.rawValue] | |
129 | 129 | return createDataPacket(key: .setSynWatch, bytes: bytes) |
130 | 130 | } |
131 | 131 | ... | ... |
HDFwear/Tools/Bluetooth+Types.swift
HDFwear/Tools/BluetoothManager+Function.swift
... | ... | @@ -212,57 +212,57 @@ extension BluetoothManager { |
212 | 212 | |
213 | 213 | //MARK: - 同步健康数据 |
214 | 214 | //拉取数据 |
215 | - func newGetData(type:SyncType, completion: ((_ error: Int?) -> ())? = nil) { | |
216 | - let data = BleMessage.shared.getSyncCmd(type) | |
215 | + func newGetData(type:SyncType, option: SyncOption = .now, completion: ((_ error: Int?) -> ())? = nil) { | |
216 | + let data = BleMessage.shared.getSyncCmd(type, option) | |
217 | 217 | self.setCmdClosure = completion |
218 | 218 | sendData(data) |
219 | 219 | } |
220 | 220 | |
221 | 221 | // 拉取电量数据 |
222 | - func newGetBatteryData( completion: ((_ error: Int?) -> ())? = nil) { | |
223 | - newGetData(type: .battery, completion: completion) | |
222 | + func newGetBatteryData(option: SyncOption = .now, completion: ((_ error: Int?) -> ())? = nil) { | |
223 | + newGetData(type: .battery, option: option, completion: completion) | |
224 | 224 | } |
225 | 225 | |
226 | 226 | // 拉取GPS轨迹数据 |
227 | 227 | //jtd! 需要使用特定的回调,这样才能够直接把数据回调出来 |
228 | - func newGetGpsData( completion: ((_ error: Int?) -> ())? = nil) { | |
229 | - newGetData(type: .gps, completion: completion) | |
228 | + func newGetGpsData(option: SyncOption = .now, completion: ((_ error: Int?) -> ())? = nil) { | |
229 | + newGetData(type: .gps, option: option, completion: completion) | |
230 | 230 | } |
231 | 231 | |
232 | - //MARK: - history | |
232 | + //MARK: - old code | |
233 | 233 | // 拉取睡眠数据 |
234 | - func getSleepHistoryData( closure: SleepClosure? = nil) { | |
235 | - let data = BleMessage.shared.getSyncCmd(.sleep) | |
234 | + func getSleepHistoryData(option: SyncOption = .now, closure: SleepClosure? = nil) { | |
235 | + let data = BleMessage.shared.getSyncCmd(.sleep, option) | |
236 | 236 | newStartSyncHealthData(closure: closure, data: data, synType: .sleep) |
237 | 237 | } |
238 | 238 | |
239 | 239 | // 拉取血氧数据 |
240 | - func getBloodOxygenHistoryData( closure: BloodOxygenClosure? = nil) { | |
241 | - let data = BleMessage.shared.getSyncCmd(.bloodOxygen) | |
240 | + func getBloodOxygenHistoryData(option: SyncOption = .now, closure: BloodOxygenClosure? = nil) { | |
241 | + let data = BleMessage.shared.getSyncCmd(.bloodOxygen, option) | |
242 | 242 | newStartSyncHealthData(closure: closure, data: data, synType: .bloodOxygen) |
243 | 243 | } |
244 | 244 | |
245 | 245 | // 拉取心跳数据 |
246 | - func getHeartRateHistoryData( closure: HeartRateClosure? = nil) { | |
247 | - let data = BleMessage.shared.getSyncCmd(.heartRate) | |
246 | + func getHeartRateHistoryData(option: SyncOption = .now, closure: HeartRateClosure? = nil) { | |
247 | + let data = BleMessage.shared.getSyncCmd(.heartRate, option) | |
248 | 248 | newStartSyncHealthData(closure: closure, data: data, synType: .heartRate) |
249 | 249 | } |
250 | 250 | |
251 | 251 | // 拉取计步数据 |
252 | - func getStepHistoryData( closure: StepClosure? = nil) { | |
253 | - let data = BleMessage.shared.getSyncCmd(.step) | |
252 | + func getStepHistoryData(option: SyncOption = .now, closure: StepClosure? = nil) { | |
253 | + let data = BleMessage.shared.getSyncCmd(.step, option) | |
254 | 254 | newStartSyncHealthData(closure: closure, data: data, synType: .step) |
255 | 255 | } |
256 | 256 | |
257 | 257 | // 拉取训练数据 |
258 | - func getTrainHistoryData( closure: TrainClosure? = nil) { | |
259 | - let data = BleMessage.shared.getSyncCmd(.train) | |
258 | + func getTrainHistoryData(option: SyncOption = .now, closure: TrainClosure? = nil) { | |
259 | + let data = BleMessage.shared.getSyncCmd(.train, option) | |
260 | 260 | newStartSyncHealthData(closure: closure, data: data, synType: .train) |
261 | 261 | } |
262 | 262 | |
263 | 263 | // 拉取压力数据 |
264 | - func getPressureHistoryData( closure: PressureClosure? = nil) { | |
265 | - let data = BleMessage.shared.getSyncCmd(.pressure) | |
264 | + func getPressureHistoryData(option: SyncOption = .now, closure: PressureClosure? = nil) { | |
265 | + let data = BleMessage.shared.getSyncCmd(.pressure, option) | |
266 | 266 | newStartSyncHealthData(closure: closure, data: data, synType: .pressure) |
267 | 267 | } |
268 | 268 | |
... | ... | @@ -300,7 +300,7 @@ extension BluetoothManager { |
300 | 300 | case is SleepClosure: |
301 | 301 | if sleepClosure == nil { |
302 | 302 | sleepClosure = closure as? SleepClosure |
303 | - sleepClosure?([], -1002) | |
303 | + sleepClosure?(nil, -1002) | |
304 | 304 | sleepClosure = nil |
305 | 305 | } |
306 | 306 | case is StepClosure: |
... | ... | @@ -447,7 +447,13 @@ extension BluetoothManager { |
447 | 447 | case 0x8019:// 睡眠数据上报 |
448 | 448 | print("睡眠数据上报") |
449 | 449 | let content = parseContentFromBytes(bytes) |
450 | - parseSleepData(content) | |
450 | + if (content.first == 0xff) { | |
451 | + for delegate in syncDelegateList { | |
452 | + delegate.didReceiveFinishCommand(0x8019) | |
453 | + } | |
454 | + }else { | |
455 | + parseSleepData(content) | |
456 | + } | |
451 | 457 | case 0x8020:// 历史压力数据上报 |
452 | 458 | print("历史压力数据上报") |
453 | 459 | let content = parseContentFromBytes(bytes) |
... | ... | @@ -617,12 +623,11 @@ extension BluetoothManager { |
617 | 623 | func parseSleepData (_ content: [UInt8]) { |
618 | 624 | guard content.count > 0 else { |
619 | 625 | print("无有效的信息") |
620 | - sleepClosure?([], nil) | |
626 | + sleepClosure?(nil, nil) | |
621 | 627 | return |
622 | 628 | } |
623 | - let array = SleepModel.toSleepArray(content) | |
624 | - SleepModel.addArray(array)// 加入数据库 | |
625 | - sleepClosure?(array, nil) | |
629 | + let model = NewSleepModel.toSleepModel(content) | |
630 | + sleepClosure?(model, nil) | |
626 | 631 | } |
627 | 632 | |
628 | 633 | // 实时步数,卡路里,距离数据 | ... | ... |
HDFwear/Tools/BluetoothManager.swift
... | ... | @@ -55,6 +55,8 @@ extension BluetoothSyncDelegate { |
55 | 55 | func didReceiveFindPhoneCommand(value: Int) { } |
56 | 56 | func didReceiveCallOff(){ } |
57 | 57 | func didReceiveCameraCommand(status: UInt8) { } |
58 | + | |
59 | + func didReceiveFinishCommand(_ receiveDataType: Int) { } | |
58 | 60 | } |
59 | 61 | |
60 | 62 | |
... | ... | @@ -81,7 +83,7 @@ class BluetoothManager: NSObject { |
81 | 83 | var bloodPressureClosure: BloodPressureClosure? |
82 | 84 | typealias BloodOxygenClosure = (_ boArray: [BloodOxygenModel], _ error: Int?) -> Void |
83 | 85 | var bloodOxygenClosure: BloodOxygenClosure? |
84 | - typealias SleepClosure = (_ sleepArray: [SleepModel], _ error: Int?) -> Void | |
86 | + typealias SleepClosure = (_ sleepModel: NewSleepModel?, _ error: Int?) -> Void | |
85 | 87 | var sleepClosure: SleepClosure? |
86 | 88 | typealias StepClosure = (_ stepArray: [StepModel], _ error: Int?) -> Void |
87 | 89 | var stepClosure: StepClosure? |
... | ... | @@ -1271,7 +1273,7 @@ class BluetoothManager: NSObject { |
1271 | 1273 | heartRateClosure?([], -1001) |
1272 | 1274 | bloodPressureClosure?([], -1001) |
1273 | 1275 | bloodOxygenClosure?([], -1001) |
1274 | - sleepClosure?([], -1001) | |
1276 | + sleepClosure?(nil, -1001) | |
1275 | 1277 | stepClosure?([], -1001) |
1276 | 1278 | trainClosure?(nil, -1001) |
1277 | 1279 | pressureClosure?([], -1001) | ... | ... |