diff --git a/HDFwear.xcodeproj/project.pbxproj b/HDFwear.xcodeproj/project.pbxproj index db9040b..a30429e 100644 --- a/HDFwear.xcodeproj/project.pbxproj +++ b/HDFwear.xcodeproj/project.pbxproj @@ -285,6 +285,7 @@ 8473FB622B4BF1A200409148 /* TaskManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8473FB612B4BF1A200409148 /* TaskManager.swift */; }; 847482762B03793C0004F0C2 /* NewWeatherModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847482752B03793C0004F0C2 /* NewWeatherModel.swift */; }; 847672B82B074E43007DC2DE /* NewBeiDouContactModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847672B72B074E43007DC2DE /* NewBeiDouContactModel.swift */; }; + 8477B04C2B5A243B0018ADA8 /* NewExerciseRealtimeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8477B04B2B5A243B0018ADA8 /* NewExerciseRealtimeModel.swift */; }; 847AF36E2B4CF35F00E3456E /* NewSleepModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847AF36D2B4CF35F00E3456E /* NewSleepModel.swift */; }; 847B88EF2B5780CA00851EE7 /* NewIntensiveTimeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847B88EE2B5780CA00851EE7 /* NewIntensiveTimeModel.swift */; }; 84DA399D2B4D3A5B008D34A9 /* NewGpsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DA399C2B4D3A5B008D34A9 /* NewGpsModel.swift */; }; @@ -666,6 +667,7 @@ 8473FB612B4BF1A200409148 /* TaskManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskManager.swift; sourceTree = ""; }; 847482752B03793C0004F0C2 /* NewWeatherModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewWeatherModel.swift; sourceTree = ""; }; 847672B72B074E43007DC2DE /* NewBeiDouContactModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewBeiDouContactModel.swift; sourceTree = ""; }; + 8477B04B2B5A243B0018ADA8 /* NewExerciseRealtimeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewExerciseRealtimeModel.swift; sourceTree = ""; }; 847AF36D2B4CF35F00E3456E /* NewSleepModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewSleepModel.swift; sourceTree = ""; }; 847B88EE2B5780CA00851EE7 /* NewIntensiveTimeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewIntensiveTimeModel.swift; sourceTree = ""; }; 847D1C4A2B009FAC0097A96E /* 20231111ReadMe.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = 20231111ReadMe.md; sourceTree = ""; }; @@ -1290,6 +1292,7 @@ 84DA399C2B4D3A5B008D34A9 /* NewGpsModel.swift */, 845ADEA02B551C8E00C3AD73 /* NewStepModel.swift */, 847B88EE2B5780CA00851EE7 /* NewIntensiveTimeModel.swift */, + 8477B04B2B5A243B0018ADA8 /* NewExerciseRealtimeModel.swift */, ); path = Model; sourceTree = ""; @@ -1688,6 +1691,7 @@ 6C34A24A276DC74000849087 /* FindBraceletVC.swift in Sources */, 6C58AC51275B66930028A849 /* Sequence+Extension.swift in Sources */, 6C33CC6227E182FB0081AB98 /* CustomDialOldVC.swift in Sources */, + 8477B04C2B5A243B0018ADA8 /* NewExerciseRealtimeModel.swift in Sources */, 6C0AE838279166B10064D377 /* InfoPlist.strings in Sources */, 6CA65306278142AE0063B916 /* ShareViewController.swift in Sources */, 6C6F406027434B9C00F9473C /* UIStoryboard+Extension.swift in Sources */, diff --git a/HDFwear/20240126ReadMe.md b/HDFwear/20240126ReadMe.md index ff2db81..b72486c 100644 --- a/HDFwear/20240126ReadMe.md +++ b/HDFwear/20240126ReadMe.md @@ -107,4 +107,25 @@ BluetoothManager+Function 接收: [237, 126, 0, 1, 128, 41, 0, 1, 0, 8, 49, 52, 52, 57, 51, 48, 55, 49, 16, 131] +发起运动交互 + attension:要发起完整的运动流程,步骤:发送指令1,发送指令6,摇动手表 + status 1、准备查看运动状态 5、运动暂停 6、运动中 7、运动结束 + func newSetExerciseStatus(status: Int, type: Int, completion: ((_ error: Int?) -> ())? = nil) + 0x8027触发BluetoothSyncDelegate中的didReceiveExerciseStatus + 0x8023触发BluetoothSyncDelegate中的didReceiveExerciseRealtimeData + 发送: [237, 126, 0, 1, 0, 56, 0, 1, 0, 2, 1, 0, 50, 163] + 接收: [237, 126, 0, 1, 128, 39, 0, 1, 0, 1, 8, 127, 30] + 发送: [237, 126, 0, 1, 0, 56, 0, 1, 0, 2, 6, 0, 171, 52] + 接收: [237, 126, 0, 1, 128, 39, 0, 1, 0, 1, 0, 254, 22] + 接收: [237, 126, 0, 1, 128, 35, 0, 1, 0, 9, 0, 0, 0, 0, 64, 0, 0, 0, 0, 227, 68] + 接收: [237, 126, 0, 1, 128, 35, 0, 1, 0, 9, 0, 0, 0, 0, 64, 0, 0, 0, 0, 227, 68] + 接收: [237, 126, 0, 1, 128, 35, 0, 1, 0, 9, 0, 0, 0, 0, 73, 0, 0, 0, 0, 75, 56] + 接收: [237, 126, 0, 1, 128, 35, 0, 1, 0, 9, 0, 0, 0, 0, 82, 0, 0, 0, 0, 163, 157] + 接收: [237, 126, 0, 1, 128, 35, 0, 1, 0, 9, 0, 0, 0, 0, 91, 0, 0, 0, 0, 11, 225] + 接收: [237, 126, 0, 1, 128, 35, 0, 1, 0, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 98, 246] + 发送: [237, 126, 0, 1, 0, 9, 0, 1, 0, 7, 24, 1, 18, 17, 5, 3, 4, 161, 6] + 接收: [237, 126, 0, 1, 128, 1, 0, 1, 0, 5, 0, 1, 0, 9, 0, 76, 235] + + + 接受数据类 diff --git a/HDFwear/Home/Model/NewExerciseRealtimeModel.swift b/HDFwear/Home/Model/NewExerciseRealtimeModel.swift new file mode 100644 index 0000000..dc0cbc7 --- /dev/null +++ b/HDFwear/Home/Model/NewExerciseRealtimeModel.swift @@ -0,0 +1,35 @@ +// +// NewExerciseRealtimeModel.swift +// HDFwear +// +// Created by admin on 2024/1/19. +// + +import Foundation +import UIKit +import HandyJSON +import SwiftDate + +class NewExerciseRealtimeModel: NSObject { + required override init() { } + + var hr: UInt32 = 0 + var step: UInt32 = 0 + var calorie: UInt32 = 0 + + + override var description: String { + return "NewExerciseRealtimeModel: HR=\(hr), Step=\(step), Calorie=\(calorie)" + } + + class func toExerciseRealtimeModel(_ data: [UInt8]) -> NewExerciseRealtimeModel? { + guard data.count >= 9 else { + return nil + } + let s = NewExerciseRealtimeModel() + s.hr = data[0..<1].reduce(0) { ($0 << 8) + UInt32($1) } + s.step = data[1..<5].reduce(0) { ($0 << 8) + UInt32($1) } + s.calorie = data[5..<9].reduce(0) { ($0 << 8) + UInt32($1) } + return s; + } +} diff --git a/HDFwear/Mine/MineViewController.swift b/HDFwear/Mine/MineViewController.swift index 74ee42b..2316622 100644 --- a/HDFwear/Mine/MineViewController.swift +++ b/HDFwear/Mine/MineViewController.swift @@ -36,6 +36,7 @@ class MineViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() + BluetoothManager.shared.registerSyncDelegate(self) setupUI() @@ -398,6 +399,36 @@ extension MineViewController: UITableViewDataSource, UITableViewDelegate { } } + let archiveAction28a = UIAlertAction(title: "newSetExerciseStatus 1", style: .default) { action in + BluetoothManager.shared.newSetExerciseStatus(status: 1, type: 0) { error in + if error != nil { + print("newSetExerciseStatus" + (error?.description ?? "")) + }else { + print("newSetExerciseStatus success") + } + } + } + + let archiveAction28b = UIAlertAction(title: "newSetExerciseStatus 6", style: .default) { action in + BluetoothManager.shared.newSetExerciseStatus(status: 6, type: 0) { error in + if error != nil { + print("newSetExerciseStatus" + (error?.description ?? "")) + }else { + print("newSetExerciseStatus success") + } + } + } + + let archiveAction28c = UIAlertAction(title: "newSetExerciseStatus 7", style: .default) { action in + BluetoothManager.shared.newSetExerciseStatus(status: 7, type: 0) { error in + if error != nil { + print("newSetExerciseStatus" + (error?.description ?? "")) + }else { + print("newSetExerciseStatus success") + } + } + } + alert.addAction(archiveAction0) alert.addAction(archiveAction1) alert.addAction(archiveAction2) @@ -422,6 +453,9 @@ extension MineViewController: UITableViewDataSource, UITableViewDelegate { alert.addAction(archiveAction25) alert.addAction(archiveAction26) alert.addAction(archiveAction27) + alert.addAction(archiveAction28a) + alert.addAction(archiveAction28b) + alert.addAction(archiveAction28c) alert.addAction(UIAlertAction(title: "取消", style: .destructive, handler: nil)) present(alert, animated: true, completion: nil) @@ -661,3 +695,13 @@ extension MineViewController: UITableViewDataSource, UITableViewDelegate { present(alert, animated: true, completion: nil) } } + +extension MineViewController: BluetoothSyncDelegate { + func didReceiveExerciseStatus(value: Int) { + showDetailAlert(msg: "ExerciseStatus is " + String(value)) + } + + func didReceiveExerciseRealtimeData(realtimeData: NewExerciseRealtimeModel) { + showDetailAlert(msg: realtimeData.description) + } +} diff --git a/HDFwear/Tools/BleMessage+Function.swift b/HDFwear/Tools/BleMessage+Function.swift index 95005f0..048554c 100644 --- a/HDFwear/Tools/BleMessage+Function.swift +++ b/HDFwear/Tools/BleMessage+Function.swift @@ -236,4 +236,9 @@ extension BleMessage { let bytes: [UInt8] = [byte] return createDataPacket(key: .setMessageRemind, bytes: bytes) } + + func getExerciseStatusCmd(status: Int, type: Int) -> Data { + let bytes: [UInt8] = [UInt8(status), UInt8(type)] + return createDataPacket(key: .setExerciseStatus, bytes: bytes) + } } diff --git a/HDFwear/Tools/Bluetooth+Types.swift b/HDFwear/Tools/Bluetooth+Types.swift index 83c1989..20b8da8 100644 --- a/HDFwear/Tools/Bluetooth+Types.swift +++ b/HDFwear/Tools/Bluetooth+Types.swift @@ -145,7 +145,7 @@ enum NewCmd: UInt8 { case setHeartRateDetectInterval = 0x0032 case setBloodOxygenLowRemind = 0x0034 case setMessageRemind = 0x0035 - + case setExerciseStatus = 0x0038 } enum SyncCmd: UInt8 { @@ -219,3 +219,13 @@ enum WeekFlag: UInt8 { case friday = 5 case saturday = 6 } + +enum ExerciseStatus: UInt8 { + case sunday = 0 + case monday = 1 + case tuesday = 2 + case wednesday = 3 + case thursday = 4 + case friday = 5 + case saturday = 6 +} diff --git a/HDFwear/Tools/BluetoothManager+Function.swift b/HDFwear/Tools/BluetoothManager+Function.swift index 98d6b3a..78f5023 100644 --- a/HDFwear/Tools/BluetoothManager+Function.swift +++ b/HDFwear/Tools/BluetoothManager+Function.swift @@ -219,6 +219,15 @@ extension BluetoothManager { sendData(data) } + // 发起运动交互 + // 这里的status 1 与文档描述有区别,与开发确认过 + // status 1、准备查看运动状态 5、运动暂停 6、运动中 7、运动结束 + func newSetExerciseStatus(status: Int, type: Int, completion: ((_ error: Int?) -> ())? = nil) { + let data = BleMessage.shared.getExerciseStatusCmd(status: status, type: type) + self.setCmdClosure = completion + sendData(data) + } + //MARK: - 同步健康数据 //拉取数据 func newGetData(type:SyncType, option: SyncOption = .now, completion: ((_ error: Int?) -> ())? = nil) { @@ -548,6 +557,14 @@ extension BluetoothManager { for delegate in syncDelegateList { delegate.didReceiveCameraCommand(status: stauts) } + case 0x8023:// 运动实时数据 + print("运动实时数据") + let content = parseContentFromBytes(bytes) + if let realtimeData = NewExerciseRealtimeModel.toExerciseRealtimeModel(content) { + for delegate in syncDelegateList { + delegate.didReceiveExerciseRealtimeData(realtimeData: realtimeData) + } + } case 0x8025://手表户外运动定位轨迹 print("gps轨迹") let content = parseContentFromBytes(bytes) @@ -558,6 +575,12 @@ extension BluetoothManager { }else { parseGpsData(content) } + case 0x8027://运动状态 + print("运动状态") + let status = Int(bytes[10]) + for delegate in syncDelegateList { + delegate.didReceiveExerciseStatus(value: status) + } case 0x8028://中高强度时长 print("中高强度时长") let content = parseContentFromBytes(bytes) diff --git a/HDFwear/Tools/BluetoothManager.swift b/HDFwear/Tools/BluetoothManager.swift index e2ee46b..281df1c 100644 --- a/HDFwear/Tools/BluetoothManager.swift +++ b/HDFwear/Tools/BluetoothManager.swift @@ -40,6 +40,10 @@ protocol BluetoothSyncDelegate { func didReceiveFindPhoneCommand(value: Int) func didReceiveCallOff() func didReceiveCameraCommand(status: UInt8)// 0x00 进入拍照 0x01 拍照 0x02 关闭 + func didReceiveExerciseStatus(value: Int) + func didReceiveExerciseRealtimeData(realtimeData: NewExerciseRealtimeModel) + + func didReceiveFinishCommand(_ receiveDataType: Int) } extension BluetoothSyncDelegate { func didReceiveFindCommand(status: Bool) { } @@ -55,6 +59,8 @@ extension BluetoothSyncDelegate { func didReceiveFindPhoneCommand(value: Int) { } func didReceiveCallOff(){ } func didReceiveCameraCommand(status: UInt8) { } + func didReceiveExerciseStatus(value: Int) { } + func didReceiveExerciseRealtimeData(realtimeData: NewExerciseRealtimeModel) { } func didReceiveFinishCommand(_ receiveDataType: Int) { } }