Commit b867ff0ea6c6095132da9e89f2983de498aa526b
1 parent
0f975482
feat:fetch exercise data
Showing
10 changed files
with
332 additions
and
33 deletions
HDFwear.xcodeproj/project.pbxproj
... | ... | @@ -286,6 +286,7 @@ |
286 | 286 | 847482762B03793C0004F0C2 /* NewWeatherModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847482752B03793C0004F0C2 /* NewWeatherModel.swift */; }; |
287 | 287 | 847672B82B074E43007DC2DE /* NewBeiDouContactModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847672B72B074E43007DC2DE /* NewBeiDouContactModel.swift */; }; |
288 | 288 | 8477B04C2B5A243B0018ADA8 /* NewExerciseRealtimeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8477B04B2B5A243B0018ADA8 /* NewExerciseRealtimeModel.swift */; }; |
289 | + 8477B04E2B5A79EE0018ADA8 /* NewExerciseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8477B04D2B5A79EE0018ADA8 /* NewExerciseModel.swift */; }; | |
289 | 290 | 847AF36E2B4CF35F00E3456E /* NewSleepModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847AF36D2B4CF35F00E3456E /* NewSleepModel.swift */; }; |
290 | 291 | 847B88EF2B5780CA00851EE7 /* NewIntensiveTimeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847B88EE2B5780CA00851EE7 /* NewIntensiveTimeModel.swift */; }; |
291 | 292 | 84DA399D2B4D3A5B008D34A9 /* NewGpsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DA399C2B4D3A5B008D34A9 /* NewGpsModel.swift */; }; |
... | ... | @@ -668,6 +669,7 @@ |
668 | 669 | 847482752B03793C0004F0C2 /* NewWeatherModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewWeatherModel.swift; sourceTree = "<group>"; }; |
669 | 670 | 847672B72B074E43007DC2DE /* NewBeiDouContactModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewBeiDouContactModel.swift; sourceTree = "<group>"; }; |
670 | 671 | 8477B04B2B5A243B0018ADA8 /* NewExerciseRealtimeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewExerciseRealtimeModel.swift; sourceTree = "<group>"; }; |
672 | + 8477B04D2B5A79EE0018ADA8 /* NewExerciseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewExerciseModel.swift; sourceTree = "<group>"; }; | |
671 | 673 | 847AF36D2B4CF35F00E3456E /* NewSleepModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewSleepModel.swift; sourceTree = "<group>"; }; |
672 | 674 | 847B88EE2B5780CA00851EE7 /* NewIntensiveTimeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewIntensiveTimeModel.swift; sourceTree = "<group>"; }; |
673 | 675 | 847D1C4A2B009FAC0097A96E /* 20231111ReadMe.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = 20231111ReadMe.md; sourceTree = "<group>"; }; |
... | ... | @@ -1293,6 +1295,7 @@ |
1293 | 1295 | 845ADEA02B551C8E00C3AD73 /* NewStepModel.swift */, |
1294 | 1296 | 847B88EE2B5780CA00851EE7 /* NewIntensiveTimeModel.swift */, |
1295 | 1297 | 8477B04B2B5A243B0018ADA8 /* NewExerciseRealtimeModel.swift */, |
1298 | + 8477B04D2B5A79EE0018ADA8 /* NewExerciseModel.swift */, | |
1296 | 1299 | ); |
1297 | 1300 | path = Model; |
1298 | 1301 | sourceTree = "<group>"; |
... | ... | @@ -1642,6 +1645,7 @@ |
1642 | 1645 | 6CC6E57927717FF8006C01A7 /* DailSyncViewController.swift in Sources */, |
1643 | 1646 | 6C6F406D2743509500F9473C /* MotionViewController.swift in Sources */, |
1644 | 1647 | 6C1D4D3F27B89BD000C43AA3 /* NFCCardCell.swift in Sources */, |
1648 | + 8477B04E2B5A79EE0018ADA8 /* NewExerciseModel.swift in Sources */, | |
1645 | 1649 | 847482762B03793C0004F0C2 /* NewWeatherModel.swift in Sources */, |
1646 | 1650 | 6C6505CE2799059D0043DB7A /* TitleView.swift in Sources */, |
1647 | 1651 | 6C5B545C27759CFA007F7901 /* RemindViewController.swift in Sources */, | ... | ... |
HDFwear/20240126ReadMe.md
... | ... | @@ -127,5 +127,19 @@ BluetoothManager+Function |
127 | 127 | 接收: [237, 126, 0, 1, 128, 1, 0, 1, 0, 5, 0, 1, 0, 9, 0, 76, 235] |
128 | 128 | |
129 | 129 | |
130 | +拉取运动记录 | |
131 | + func getExerciseData(option: SyncOption = .now, closure: ExerciseClosure? = nil) | |
132 | + 建议用代理来处理回调,这里不确定所有的0x8024都由拉取动作而来 | |
133 | + 0x8024触发BluetoothSyncDelegate中的didReceiveExerciseData | |
134 | + 发送: [237, 126, 0, 1, 0, 40, 0, 1, 0, 2, 7, 1, 191, 95] | |
135 | + 接收: [237, 126, 0, 1, 128, 36, 0, 1, 0, 56, 1, 101, 167, 77, 196, 0, 0, 0, 1, 54, 0, 0, 13, 152, 0, 0, 0, 72, 0, 183, 0, 23, 0, 0, 0, 29, 0, 120, 0, 45, 1, 128, 3, 12, 0, 120, 0, 100, 86, 6, 180, 60, 120, 0, 0, 0, 0, 2, 60, 180, 120, 120, 0, 0, 0, 120, 0, 92] | |
136 | + 接收: [237, 126, 0, 1, 128, 36, 0, 2, 0, 12, 0, 5, 0, 100, 0, 150, 0, 200, 0, 250, 1, 44, 12, 70] | |
137 | + 接收: [237, 126, 0, 1, 128, 36, 0, 3, 0, 12, 0, 5, 0, 120, 0, 135, 0, 110, 0, 150, 0, 60, 227, 165] | |
138 | + 接收: [237, 126, 0, 1, 128, 36, 0, 4, 0, 12, 0, 5, 0, 183, 0, 150, 0, 200, 0, 100, 0, 160, 68, 241] | |
139 | + 接收: [237, 126, 0, 1, 128, 36, 0, 5, 0, 12, 0, 5, 0, 80, 0, 150, 0, 170, 0, 120, 0, 60, 53, 89] | |
140 | + 接收: [237, 126, 0, 1, 128, 36, 0, 6, 0, 12, 0, 5, 0, 100, 0, 120, 0, 150, 0, 170, 0, 190, 169, 1] | |
141 | + 接收: [237, 126, 0, 1, 128, 36, 0, 7, 0, 12, 0, 5, 0, 65, 0, 48, 0, 98, 0, 115, 0, 140, 194, 200] | |
142 | + 接收: [237, 126, 0, 1, 128, 36, 0, 1, 0, 1, 255, 46, 6] | |
143 | + | |
130 | 144 | |
131 | 145 | 接受数据类 | ... | ... |
HDFwear/Home/HomeViewController.swift
... | ... | @@ -798,7 +798,7 @@ extension HomeViewController: XMLParserDelegate { |
798 | 798 | func syncTrain(_ day: SyncDay) { |
799 | 799 | print("\(queryArray)---同步训练---\(day)") |
800 | 800 | if queryArray.contains("Train"), let index = queryArray.firstIndex(of: "Train") { |
801 | - BluetoothManager.shared.getTrainHistoryData() {[weak self] train, error in | |
801 | + BluetoothManager.shared.getExerciseData() {[weak self] train, error in | |
802 | 802 | if error == nil || error == 2000 || error == -1001 { |
803 | 803 | self?.queryArray.remove(at: index) |
804 | 804 | if day == .today { | ... | ... |
HDFwear/Home/Model/NewExerciseModel.swift
0 → 100644
1 | +// | |
2 | +// NewExerciseModel.swift | |
3 | +// HDFwear | |
4 | +// | |
5 | +// Created by admin on 2024/1/19. | |
6 | +// | |
7 | + | |
8 | +import Foundation | |
9 | +import UIKit | |
10 | +import HandyJSON | |
11 | +import SwiftDate | |
12 | + | |
13 | +var localExerciseModel : NewExerciseModel? | |
14 | + | |
15 | +class NewExerciseModel: NSObject { | |
16 | + required override init() { } | |
17 | + | |
18 | + // 每次分7组数据传过来,一定会有7组,不管是否空 | |
19 | + // 第一组 | |
20 | + var starter: UInt32 = 0//谁发起的运动 | |
21 | + var type: UInt32 = 0//运动类型 | |
22 | + var startTimeInterval: TimeInterval = 0 | |
23 | + var startTime: Date?//运动开始时间 | |
24 | + var strength: UInt32 = 0//训练负荷 | |
25 | + var duration: UInt32 = 0//运动时长 | |
26 | + var distance: Float = 0//距离 | |
27 | + var calorie: Float = 0//卡路里 | |
28 | + var avaragePace: Float = 0//平均配速 | |
29 | + var maxPace: Float = 0//最大配速 | |
30 | + var step: UInt32 = 0//步数 | |
31 | + var stepPitch: Float = 0//步距 | |
32 | + var avarageFrequency: Float = 0//平均步频 | |
33 | + var maxFrequency: Float = 0//最大步频 | |
34 | + var climbAltitude: Float = 0//海拔 累计爬升 | |
35 | + var maxAltitude: Float = 0//最大海拔 | |
36 | + var minAltitude: Float = 0//最小海拔 | |
37 | + var maxOxygenUptake: UInt32 = 0//最大摄氧量 | |
38 | + var oxygenUptakeGrade: UInt32 = 0//摄氧量等级 | |
39 | + var maxHr: UInt32 = 0//最大心率 | |
40 | + var minHr: UInt32 = 0//最小心率 | |
41 | + var avarageHr: UInt32 = 0//平均心率 | |
42 | + var hrSectionPercent_warmUp: UInt32 = 0//心率区间百分比 热身 | |
43 | + var hrSectionPercent_fatBurning: UInt32 = 0//心率区间百分比 燃脂 | |
44 | + var hrSectionPercent_cardiopulmonary: UInt32 = 0//心率区间百分比 心肺提高 | |
45 | + var hrSectionPercent_anaerobic: UInt32 = 0//心率区间百分比 无氧 | |
46 | + var masterSwimming: UInt32 = 0//主泳姿 | |
47 | + var strokes: UInt32 = 0//划水次数 | |
48 | + var lap: UInt32 = 0//趟数 | |
49 | + var avarageSwolf: UInt32 = 0//平均swolf | |
50 | + var maxSwolf: UInt32 = 0//最大swolf | |
51 | + var hiits: UInt32 = 0//hiit个数 | |
52 | + //第二组 | |
53 | + var altitudeCount: UInt32 = 0//海拔高度个数 | |
54 | + var altitudeArray: [Float] = []//实时海拔 | |
55 | + //第三组 | |
56 | + var frequencyCount: UInt32 = 0//步频个数 | |
57 | + var frequencyArray: [Float] = []//实时步频 | |
58 | + //第四组 | |
59 | + var paceCount: UInt32 = 0//配速个数 | |
60 | + var paceArray: [Float] = []//实时配速 | |
61 | + //第五组 | |
62 | + var speedCount: UInt32 = 0//速度个数 | |
63 | + var speedArray: [Float] = []//实时速度 | |
64 | + //第六组 | |
65 | + var swolfCount: UInt32 = 0//swolf个数 | |
66 | + var swolfArray: [UInt32] = []//实时swolf | |
67 | + //第七组 | |
68 | + var strokeCount: UInt32 = 0//划水个数 | |
69 | + var strokeArray: [UInt32] = []//划水速度 | |
70 | + | |
71 | + override var description: String { | |
72 | + let dateFormatter = DateFormatter() | |
73 | + dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" | |
74 | + dateFormatter.timeZone = TimeZone.current | |
75 | + | |
76 | + var desc = "NewExerciseModel\n" | |
77 | + desc += "Starter: \(starter)\n" | |
78 | + desc += "Type: \(type)\n" | |
79 | + desc += "StartTime: \(dateFormatter.string(from:(startTime ?? Date())))\n" | |
80 | + desc += "Strength: \(strength)\n" | |
81 | + desc += "Duration: \(duration)\n" | |
82 | + desc += "Distance: \(distance)\n" | |
83 | + desc += "Calorie: \(calorie)\n" | |
84 | + desc += "AveragePace: \(avaragePace)\n" | |
85 | + desc += "MaxPace: \(maxPace)\n" | |
86 | + desc += "Step: \(step)\n" | |
87 | + desc += "StepPitch: \(stepPitch)\n" | |
88 | + desc += "AverageFrequency: \(avarageFrequency)\n" | |
89 | + desc += "MaxFrequency: \(maxFrequency)\n" | |
90 | + desc += "ClimbAltitude: \(climbAltitude)\n" | |
91 | + desc += "MaxAltitude: \(maxAltitude)\n" | |
92 | + desc += "MinAltitude: \(minAltitude)\n" | |
93 | + desc += "MaxOxygenUptake: \(maxOxygenUptake)\n" | |
94 | + desc += "OxygenUptakeGrade: \(oxygenUptakeGrade)\n" | |
95 | + desc += "MaxHr: \(maxHr)\n" | |
96 | + desc += "MinHr: \(minHr)\n" | |
97 | + desc += "AvarageHr: \(avarageHr)\n" | |
98 | + desc += "HrSectionPercent_warmUp: \(hrSectionPercent_warmUp)\n" | |
99 | + desc += "HrSectionPercent_fatBurning: \(hrSectionPercent_fatBurning)\n" | |
100 | + desc += "HrSectionPercent_cardiopulmonary: \(hrSectionPercent_cardiopulmonary)\n" | |
101 | + desc += "HrSectionPercent_anaerobic: \(hrSectionPercent_anaerobic)\n" | |
102 | + desc += "MasterSwimming: \(masterSwimming)\n" | |
103 | + desc += "Strokes: \(strokes)\n" | |
104 | + desc += "Lap: \(lap)\n" | |
105 | + desc += "AvarageSwolf: \(avarageSwolf)\n" | |
106 | + desc += "MaxSwolf: \(maxSwolf)\n" | |
107 | + desc += "Hiits: \(hiits)\n" | |
108 | + | |
109 | + // 第二组 | |
110 | + desc += "Altitude Count: \(altitudeCount)\n" | |
111 | + desc += "Altitude Array: \(altitudeArray)\n" | |
112 | + | |
113 | + // 第三组 | |
114 | + desc += "Frequency Count: \(frequencyCount)\n" | |
115 | + desc += "Frequency Array: \(frequencyArray)\n" | |
116 | + | |
117 | + // 第四组 | |
118 | + desc += "Pace Count: \(paceCount)\n" | |
119 | + desc += "Pace Array: \(paceArray)\n" | |
120 | + | |
121 | + // 第五组 | |
122 | + desc += "Speed Count: \(speedCount)\n" | |
123 | + desc += "Speed Array: \(speedArray)\n" | |
124 | + | |
125 | + // 第六组 | |
126 | + desc += "Swolf Count: \(swolfCount)\n" | |
127 | + desc += "Swolf Array: \(swolfArray)\n" | |
128 | + | |
129 | + // 第七组 | |
130 | + desc += "Stroke Count: \(strokeCount)\n" | |
131 | + desc += "Stroke Array: \(strokeArray)\n" | |
132 | + | |
133 | + return desc | |
134 | + } | |
135 | + | |
136 | + class func toExerciseModel(_ data: [UInt8], _ index: Int) { | |
137 | + if index == 1 { | |
138 | + guard data.count >= 57 else { | |
139 | + return | |
140 | + } | |
141 | + }else { | |
142 | + guard data.count >= 1, localExerciseModel != nil else { | |
143 | + return | |
144 | + } | |
145 | + } | |
146 | + | |
147 | + switch index { | |
148 | + case 1: | |
149 | + localExerciseModel = NewExerciseModel() | |
150 | + localExerciseModel?.starter = data[0..<1].reduce(0) { ($0 << 8) + UInt32($1) } | |
151 | + localExerciseModel?.type = data[1..<2].reduce(0) { ($0 << 8) + UInt32($1) } | |
152 | + let hexValue = data[2..<6].reduce(0) { ($0 << 8) + UInt32($1) } | |
153 | + localExerciseModel?.startTimeInterval = TimeInterval(hexValue) | |
154 | + localExerciseModel?.startTime = Date(timeIntervalSince1970: TimeInterval(hexValue)) | |
155 | + localExerciseModel?.strength = data[6..<7].reduce(0) { ($0 << 8) + UInt32($1) } | |
156 | + localExerciseModel?.duration = data[7..<11].reduce(0) { ($0 << 8) + UInt32($1) } | |
157 | + localExerciseModel?.distance = Float(data[11..<15].reduce(0) { ($0 << 8) + UInt32($1) }) / 100 | |
158 | + localExerciseModel?.calorie = Float(data[15..<19].reduce(0) { ($0 << 8) + UInt32($1) }) / 100 | |
159 | + localExerciseModel?.avaragePace = Float(data[19..<21].reduce(0) { ($0 << 8) + UInt32($1) }) / 100 | |
160 | + localExerciseModel?.maxPace = Float(data[21..<23].reduce(0) { ($0 << 8) + UInt32($1) }) / 100 | |
161 | + localExerciseModel?.step = data[23..<27].reduce(0) { ($0 << 8) + UInt32($1) } | |
162 | + localExerciseModel?.stepPitch = Float(data[27..<29].reduce(0) { ($0 << 8) + UInt32($1) }) / 100 | |
163 | + localExerciseModel?.avarageFrequency = Float(data[29..<31].reduce(0) { ($0 << 8) + UInt32($1) }) / 100 | |
164 | + localExerciseModel?.maxFrequency = Float(data[31..<33].reduce(0) { ($0 << 8) + UInt32($1) }) / 100 | |
165 | + localExerciseModel?.climbAltitude = Float(data[33..<35].reduce(0) { ($0 << 8) + UInt32($1) }) / 100 | |
166 | + localExerciseModel?.maxAltitude = Float(data[35..<37].reduce(0) { ($0 << 8) + UInt32($1) }) / 100 | |
167 | + localExerciseModel?.minAltitude = Float(data[37..<39].reduce(0) { ($0 << 8) + UInt32($1) }) / 100 | |
168 | + localExerciseModel?.maxOxygenUptake = data[39..<40].reduce(0) { ($0 << 8) + UInt32($1) } | |
169 | + localExerciseModel?.oxygenUptakeGrade = data[40..<41].reduce(0) { ($0 << 8) + UInt32($1) } | |
170 | + localExerciseModel?.maxHr = data[41..<42].reduce(0) { ($0 << 8) + UInt32($1) } | |
171 | + localExerciseModel?.minHr = data[42..<43].reduce(0) { ($0 << 8) + UInt32($1) } | |
172 | + localExerciseModel?.avarageHr = data[43..<44].reduce(0) { ($0 << 8) + UInt32($1) } | |
173 | + localExerciseModel?.hrSectionPercent_warmUp = data[44..<45].reduce(0) { ($0 << 8) + UInt32($1) } | |
174 | + localExerciseModel?.hrSectionPercent_fatBurning = data[45..<46].reduce(0) { ($0 << 8) + UInt32($1) } | |
175 | + localExerciseModel?.hrSectionPercent_cardiopulmonary = data[46..<47].reduce(0) { ($0 << 8) + UInt32($1) } | |
176 | + localExerciseModel?.hrSectionPercent_anaerobic = data[47..<48].reduce(0) { ($0 << 8) + UInt32($1) } | |
177 | + localExerciseModel?.masterSwimming = data[48..<49].reduce(0) { ($0 << 8) + UInt32($1) } | |
178 | + localExerciseModel?.strokes = data[49..<50].reduce(0) { ($0 << 8) + UInt32($1) } | |
179 | + localExerciseModel?.lap = data[50..<51].reduce(0) { ($0 << 8) + UInt32($1) } | |
180 | + localExerciseModel?.avarageSwolf = data[51..<52].reduce(0) { ($0 << 8) + UInt32($1) } | |
181 | + localExerciseModel?.maxSwolf = data[52..<53].reduce(0) { ($0 << 8) + UInt32($1) } | |
182 | + localExerciseModel?.hiits = data[53..<57].reduce(0) { ($0 << 8) + UInt32($1) } | |
183 | + case 2: | |
184 | + localExerciseModel!.altitudeCount = data[0..<2].reduce(0) { ($0 << 8) + UInt32($1) } | |
185 | + if data.count >= 2 * localExerciseModel!.altitudeCount + 2 { | |
186 | + // 从下标1开始,每次取2个元素,合并为一个数 | |
187 | + localExerciseModel!.altitudeArray = stride(from: 2, to: data.count, by: 2).map { index in | |
188 | + let combinedValue = data[index..<index + 2].reduce(0) { ($0 << 8) + UInt32($1) } | |
189 | + return Float(combinedValue) / 100 | |
190 | + } | |
191 | + } | |
192 | + case 3: | |
193 | + localExerciseModel!.frequencyCount = data[0..<2].reduce(0) { ($0 << 8) + UInt32($1) } | |
194 | + if data.count >= 2 * localExerciseModel!.frequencyCount + 2 { | |
195 | + // 从下标1开始,每次取2个元素,合并为一个数 | |
196 | + localExerciseModel!.frequencyArray = stride(from: 2, to: data.count, by: 2).map { index in | |
197 | + let combinedValue = data[index..<index + 2].reduce(0) { ($0 << 8) + UInt32($1) } | |
198 | + return Float(combinedValue) / 100 | |
199 | + } | |
200 | + } | |
201 | + case 4: | |
202 | + localExerciseModel!.paceCount = data[0..<2].reduce(0) { ($0 << 8) + UInt32($1) } | |
203 | + if data.count >= 2 * localExerciseModel!.paceCount + 2 { | |
204 | + // 从下标1开始,每次取2个元素,合并为一个数 | |
205 | + localExerciseModel!.paceArray = stride(from: 2, to: data.count, by: 2).map { index in | |
206 | + let combinedValue = data[index..<index + 2].reduce(0) { ($0 << 8) + UInt32($1) } | |
207 | + return Float(combinedValue) / 100 | |
208 | + } | |
209 | + } | |
210 | + case 5: | |
211 | + localExerciseModel!.speedCount = data[0..<2].reduce(0) { ($0 << 8) + UInt32($1) } | |
212 | + if data.count >= 2 * localExerciseModel!.speedCount + 2 { | |
213 | + // 从下标1开始,每次取2个元素,合并为一个数 | |
214 | + localExerciseModel!.speedArray = stride(from: 2, to: data.count, by: 2).map { index in | |
215 | + let combinedValue = data[index..<index + 2].reduce(0) { ($0 << 8) + UInt32($1) } | |
216 | + return Float(combinedValue) / 100 | |
217 | + } | |
218 | + } | |
219 | + case 6: | |
220 | + localExerciseModel!.swolfCount = data[0..<2].reduce(0) { ($0 << 8) + UInt32($1) } | |
221 | + if data.count >= 2 * localExerciseModel!.swolfCount + 2 { | |
222 | + // 从下标1开始,每次取2个元素,合并为一个数 | |
223 | + localExerciseModel!.swolfArray = stride(from: 2, to: data.count, by: 2).map { index in | |
224 | + let combinedValue = data[index..<index + 2].reduce(0) { ($0 << 8) + UInt32($1) } | |
225 | + return combinedValue | |
226 | + } | |
227 | + } | |
228 | + case 7: | |
229 | + localExerciseModel!.strokeCount = data[0..<2].reduce(0) { ($0 << 8) + UInt32($1) } | |
230 | + if data.count >= 2 * localExerciseModel!.strokeCount + 2 { | |
231 | + // 从下标1开始,每次取2个元素,合并为一个数 | |
232 | + localExerciseModel!.strokeArray = stride(from: 2, to: data.count, by: 2).map { index in | |
233 | + let combinedValue = data[index..<index + 2].reduce(0) { ($0 << 8) + UInt32($1) } | |
234 | + return combinedValue | |
235 | + } | |
236 | + } | |
237 | + default: break | |
238 | + } | |
239 | + } | |
240 | +} | ... | ... |
HDFwear/Home/Model/NewExerciseRealtimeModel.swift
... | ... | @@ -15,7 +15,7 @@ class NewExerciseRealtimeModel: NSObject { |
15 | 15 | |
16 | 16 | var hr: UInt32 = 0 |
17 | 17 | var step: UInt32 = 0 |
18 | - var calorie: UInt32 = 0 | |
18 | + var calorie: Float = 0 | |
19 | 19 | |
20 | 20 | |
21 | 21 | override var description: String { |
... | ... | @@ -29,7 +29,7 @@ class NewExerciseRealtimeModel: NSObject { |
29 | 29 | let s = NewExerciseRealtimeModel() |
30 | 30 | s.hr = data[0..<1].reduce(0) { ($0 << 8) + UInt32($1) } |
31 | 31 | s.step = data[1..<5].reduce(0) { ($0 << 8) + UInt32($1) } |
32 | - s.calorie = data[5..<9].reduce(0) { ($0 << 8) + UInt32($1) } | |
32 | + s.calorie = Float(data[5..<9].reduce(0) { ($0 << 8) + UInt32($1) }) / 100 | |
33 | 33 | return s; |
34 | 34 | } |
35 | 35 | } | ... | ... |
HDFwear/Home/TrainViewController.swift
... | ... | @@ -52,7 +52,7 @@ class TrainViewController: UIViewController, DateSegmentViewDelegate, RangeSlide |
52 | 52 | } |
53 | 53 | override func viewDidAppear(_ animated: Bool) { |
54 | 54 | super.viewDidAppear(animated) |
55 | - BluetoothManager.shared.getTrainHistoryData() {[weak self] train, error in | |
55 | + BluetoothManager.shared.getExerciseData() {[weak self] train, error in | |
56 | 56 | if error == 2000 || error == nil { |
57 | 57 | self?.updateTodayData() |
58 | 58 | // self?.didSelectedDate(date: DateInRegion((self?.selectedDate)!, region: .current), dateType: .day) | ... | ... |
HDFwear/Mine/MineViewController.swift
... | ... | @@ -561,17 +561,6 @@ extension MineViewController: UITableViewDataSource, UITableViewDelegate { |
561 | 561 | } |
562 | 562 | } |
563 | 563 | |
564 | - let archiveAction16 = UIAlertAction(title: "getTrainHistoryData", style: .default) {[weak self] action in | |
565 | - BluetoothManager.shared.getTrainHistoryData() { tArray, error in | |
566 | - if error != nil { | |
567 | - print("getTrainHistoryData" + (error?.description ?? "")) | |
568 | - }else { | |
569 | - self?.showDetailAlert(msg: tArray?.description) | |
570 | - print("getTrainHistoryData success") | |
571 | - } | |
572 | - } | |
573 | - } | |
574 | - | |
575 | 564 | let archiveAction17a = UIAlertAction(title: "getPressureData now", style: .default) {[weak self] action in |
576 | 565 | BluetoothManager.shared.getPressureData(option: .now) { pArray, error in |
577 | 566 | if error != nil { |
... | ... | @@ -656,6 +645,27 @@ extension MineViewController: UITableViewDataSource, UITableViewDelegate { |
656 | 645 | } |
657 | 646 | } |
658 | 647 | |
648 | + let archiveAction104a = UIAlertAction(title: "getExerciseData now", style: .default) {[weak self] action in | |
649 | + BluetoothManager.shared.getExerciseData() {exerciseModel, error in | |
650 | + if error != nil { | |
651 | + print("getExerciseData" + (error?.description ?? "")) | |
652 | + }else { | |
653 | +// self?.showDetailAlert(msg: card) | |
654 | + print("getExerciseData success") | |
655 | + } | |
656 | + } | |
657 | + } | |
658 | + let archiveAction104b = UIAlertAction(title: "getExerciseData history", style: .default) {[weak self] action in | |
659 | + BluetoothManager.shared.getExerciseData(option: .history) {exerciseModel, error in | |
660 | + if error != nil { | |
661 | + print("getExerciseData" + (error?.description ?? "")) | |
662 | + }else { | |
663 | +// self?.showDetailAlert(msg: card) | |
664 | + print("getExerciseData success") | |
665 | + } | |
666 | + } | |
667 | + } | |
668 | + | |
659 | 669 | alert.addAction(archiveAction9a) |
660 | 670 | alert.addAction(archiveAction9b) |
661 | 671 | alert.addAction(archiveAction10a) |
... | ... | @@ -664,7 +674,6 @@ extension MineViewController: UITableViewDataSource, UITableViewDelegate { |
664 | 674 | alert.addAction(archiveAction14b) |
665 | 675 | alert.addAction(archiveAction15a) |
666 | 676 | alert.addAction(archiveAction15b) |
667 | - alert.addAction(archiveAction16) | |
668 | 677 | alert.addAction(archiveAction17a) |
669 | 678 | alert.addAction(archiveAction17b) |
670 | 679 | alert.addAction(archiveAction22) |
... | ... | @@ -673,6 +682,8 @@ extension MineViewController: UITableViewDataSource, UITableViewDelegate { |
673 | 682 | alert.addAction(archiveAction102a) |
674 | 683 | alert.addAction(archiveAction102b) |
675 | 684 | alert.addAction(archiveAction103) |
685 | + alert.addAction(archiveAction104a) | |
686 | + alert.addAction(archiveAction104b) | |
676 | 687 | |
677 | 688 | alert.addAction(UIAlertAction(title: "取消", style: .destructive, handler: nil)) |
678 | 689 | present(alert, animated: true, completion: nil) |
... | ... | @@ -704,4 +715,8 @@ extension MineViewController: BluetoothSyncDelegate { |
704 | 715 | func didReceiveExerciseRealtimeData(realtimeData: NewExerciseRealtimeModel) { |
705 | 716 | showDetailAlert(msg: realtimeData.description) |
706 | 717 | } |
718 | + | |
719 | + func didReceiveExerciseData(exerciseData: NewExerciseModel) { | |
720 | + showDetailAlert(msg: exerciseData.description) | |
721 | + } | |
707 | 722 | } | ... | ... |
HDFwear/ReadMe.txt
... | ... | @@ -39,10 +39,6 @@ BluetoothManager+Function |
39 | 39 | func newSetNotDisturb(remind: RemindModel, weekflag:[WeekFlag], isRepeat:Bool, completion: @escaping(_ error: Int?) -> ()) |
40 | 40 | 发送: [237, 126, 0, 1, 0, 39, 0, 1, 0, 7, 0, 1, 33, 22, 0, 22, 0, 159, 5] |
41 | 41 | |
42 | -23. 拉取训练数据 | |
43 | - func getTrainHistoryData(closure: TrainClosure? = nil) | |
44 | - 发送: [237, 126, 0, 1, 0, 40, 0, 1, 0, 1, 7, 224, 11] | |
45 | - | |
46 | 42 | 接受数据类 |
47 | 43 | 1. 通用返回数据 |
48 | 44 | private func parseDefaultResponseData(_ bytes: [UInt8]) | ... | ... |
HDFwear/Tools/BluetoothManager+Function.swift
... | ... | @@ -284,8 +284,8 @@ extension BluetoothManager { |
284 | 284 | newStartSyncHealthData(closure: closure, data: data, synType: .step) |
285 | 285 | } |
286 | 286 | |
287 | - // 拉取训练数据 | |
288 | - func getTrainHistoryData(option: SyncOption = .now, closure: TrainClosure? = nil) { | |
287 | + // 拉取运动记录 | |
288 | + func getExerciseData(option: SyncOption = .now, closure: ExerciseClosure? = nil) { | |
289 | 289 | let data = BleMessage.shared.getSyncCmd(.train, option) |
290 | 290 | newStartSyncHealthData(closure: closure, data: data, synType: .train) |
291 | 291 | } |
... | ... | @@ -339,11 +339,11 @@ extension BluetoothManager { |
339 | 339 | stepClosure?([], -1002) |
340 | 340 | stepClosure = nil |
341 | 341 | } |
342 | - case is TrainClosure: | |
343 | - if trainClosure == nil { | |
344 | - trainClosure = closure as? TrainClosure | |
345 | - trainClosure?(nil, -1002) | |
346 | - trainClosure = nil | |
342 | + case is ExerciseClosure: | |
343 | + if exerciseClosure == nil { | |
344 | + exerciseClosure = closure as? ExerciseClosure | |
345 | + exerciseClosure?(nil, -1002) | |
346 | + exerciseClosure = nil | |
347 | 347 | } |
348 | 348 | case is PressureClosure: |
349 | 349 | if pressureClosure == nil { |
... | ... | @@ -565,6 +565,17 @@ extension BluetoothManager { |
565 | 565 | delegate.didReceiveExerciseRealtimeData(realtimeData: realtimeData) |
566 | 566 | } |
567 | 567 | } |
568 | + case 0x8024:// 运动实时数据 | |
569 | + print("运动实时数据") | |
570 | + let content = parseContentFromBytes(bytes) | |
571 | + if (content.count == 1 && content.first == 0xff) { | |
572 | + for delegate in syncDelegateList { | |
573 | + delegate.didReceiveFinishCommand(0x8028) | |
574 | + } | |
575 | + }else { | |
576 | + let index = Int(UInt16(bytes[6]) << 8 | UInt16(bytes[7])) | |
577 | + parseExerciseData(content, index) | |
578 | + } | |
568 | 579 | case 0x8025://手表户外运动定位轨迹 |
569 | 580 | print("gps轨迹") |
570 | 581 | let content = parseContentFromBytes(bytes) |
... | ... | @@ -807,4 +818,21 @@ extension BluetoothManager { |
807 | 818 | let card = String(bytes: content, encoding: .ascii) |
808 | 819 | beidouCardClosure?(card, nil) |
809 | 820 | } |
821 | + | |
822 | + // 运动数据 | |
823 | + func parseExerciseData(_ content: [UInt8], _ index: Int) { | |
824 | + guard content.count > 0 else { | |
825 | + print("无有效的信息") | |
826 | + exerciseClosure?(nil, nil) | |
827 | + return | |
828 | + } | |
829 | + NewExerciseModel.toExerciseModel(content, index) | |
830 | + if let em = localExerciseModel, index == 7 { | |
831 | + for delegate in syncDelegateList { | |
832 | + delegate.didReceiveExerciseData(exerciseData: em) | |
833 | + } | |
834 | + exerciseClosure?(em, nil) | |
835 | + } | |
836 | + | |
837 | + } | |
810 | 838 | } | ... | ... |
HDFwear/Tools/BluetoothManager.swift
... | ... | @@ -42,6 +42,7 @@ protocol BluetoothSyncDelegate { |
42 | 42 | func didReceiveCameraCommand(status: UInt8)// 0x00 进入拍照 0x01 拍照 0x02 关闭 |
43 | 43 | func didReceiveExerciseStatus(value: Int) |
44 | 44 | func didReceiveExerciseRealtimeData(realtimeData: NewExerciseRealtimeModel) |
45 | + func didReceiveExerciseData(exerciseData: NewExerciseModel) | |
45 | 46 | |
46 | 47 | func didReceiveFinishCommand(_ receiveDataType: Int) |
47 | 48 | } |
... | ... | @@ -61,6 +62,7 @@ extension BluetoothSyncDelegate { |
61 | 62 | func didReceiveCameraCommand(status: UInt8) { } |
62 | 63 | func didReceiveExerciseStatus(value: Int) { } |
63 | 64 | func didReceiveExerciseRealtimeData(realtimeData: NewExerciseRealtimeModel) { } |
65 | + func didReceiveExerciseData(exerciseData: NewExerciseModel) { } | |
64 | 66 | |
65 | 67 | func didReceiveFinishCommand(_ receiveDataType: Int) { } |
66 | 68 | } |
... | ... | @@ -93,8 +95,8 @@ class BluetoothManager: NSObject { |
93 | 95 | var sleepClosure: SleepClosure? |
94 | 96 | typealias StepClosure = (_ stepArray: [NewStepModel], _ error: Int?) -> Void |
95 | 97 | var stepClosure: StepClosure? |
96 | - typealias TrainClosure = (_ trainArray: TrainModel?, _ error: Int?) -> Void | |
97 | - var trainClosure: TrainClosure? | |
98 | + typealias ExerciseClosure = (_ trainArray: NewExerciseModel?, _ error: Int?) -> Void | |
99 | + var exerciseClosure: ExerciseClosure? | |
98 | 100 | typealias PressureClosure = (_ pressureArray: [PressureModel], _ error: Int?) -> Void |
99 | 101 | var pressureClosure: PressureClosure? |
100 | 102 | typealias MettClosure = (_ mettArray: [MettModel], _ error: Int?) -> Void |
... | ... | @@ -1287,7 +1289,7 @@ class BluetoothManager: NSObject { |
1287 | 1289 | bloodOxygenClosure?([], -1001) |
1288 | 1290 | sleepClosure?(nil, -1001) |
1289 | 1291 | stepClosure?([], -1001) |
1290 | - trainClosure?(nil, -1001) | |
1292 | + exerciseClosure?(nil, -1001) | |
1291 | 1293 | pressureClosure?([], -1001) |
1292 | 1294 | mettClosure?([], -1001) |
1293 | 1295 | } |
... | ... | @@ -1298,7 +1300,7 @@ class BluetoothManager: NSObject { |
1298 | 1300 | bloodOxygenClosure = nil |
1299 | 1301 | sleepClosure = nil |
1300 | 1302 | stepClosure = nil |
1301 | - trainClosure = nil | |
1303 | + exerciseClosure = nil | |
1302 | 1304 | pressureClosure = nil |
1303 | 1305 | mettClosure = nil |
1304 | 1306 | gpsClosure = nil |
... | ... | @@ -1315,8 +1317,8 @@ class BluetoothManager: NSObject { |
1315 | 1317 | sleepClosure = closure as? SleepClosure |
1316 | 1318 | case is StepClosure: |
1317 | 1319 | stepClosure = closure as? StepClosure |
1318 | - case is TrainClosure: | |
1319 | - trainClosure = closure as? TrainClosure | |
1320 | + case is ExerciseClosure: | |
1321 | + exerciseClosure = closure as? ExerciseClosure | |
1320 | 1322 | case is PressureClosure: |
1321 | 1323 | pressureClosure = closure as? PressureClosure |
1322 | 1324 | case is MettClosure: | ... | ... |