You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

974 lines
40 KiB

2 years ago
//
// BluetoothService.swift
// FireBoltt
2 years ago
//
// Created by lemo on 2018/7/3.
// Copyright © 2020 ecell. All rights reserved.
//
import Foundation
import UIKit
import AVFoundation
import RxSwift
import Moya
///
let ReadProfileNotice = "ReadProfileNotice"
///
let CmdSuccess = "CmdSuccess"
///
let CmdTimeout = "CmdTimeout"
fileprivate let SendSyncDeviceDataTimer = "BluetoothService_SendSyncDeviceDataTimer"
enum HealthDataSyncState {
case normal
case syncing(progress: Double)
}
class BluetoothService: NSObject {
///
static let shared = BluetoothService()
/// oc
@objc open class func ocShareInstance() -> BluetoothService {
return shared
}
let baseBl = BLEBaseBlFireBoltt()
2 years ago
var totalCount = 0
///
private var isPlaying: Bool = false
private var systemSoundID: SystemSoundID = 0
private var alertController: UIAlertController?
///
private var totalRequestCount: Int = 0
private var progress: Double = 0.2
//
let deviceConnectState = BehaviorRelay<Bool>(value: false)
//
let power = BehaviorRelay<Int>(value: 0)
let powerState = BehaviorRelay<UIImage?>(value: R.image.power_0())
//
let syncState = BehaviorRelay<HealthDataSyncState>(value: .normal)
//
let realStep = BehaviorRelay<RealtimeStepModel>(value: RealtimeStepModel())
//
let realHeartRate = BehaviorRelay<RealtimeHeartRateModel>(value: RealtimeHeartRateModel())
//
let realTemperature = BehaviorRelay<RealtimeTemperatureModel>(value: RealtimeTemperatureModel())
//
let realBloodPressure = BehaviorRelay<RealtimeBloodPressureModel>(value: RealtimeBloodPressureModel())
//
let realBloodOxygen = BehaviorRelay<RealtimeBloodOxygenModel>(value: RealtimeBloodOxygenModel())
//
let sportUpdate = PublishSubject<Void>()
//
let sleepUpdate = BehaviorSubject<Void>(value: ())
///
let cloudFirmwareInfo = PublishSubject<(isNew: Bool, isMandatory: Bool)>()
///
let adapterInfoUpdate = PublishSubject<AdapterInfo>()
override init() {
super.init()
baseBl.delegate = self
loadDefaultData()
monitorNotification()
//
// finishedHandle(BLEBaseBl(), data: ["deviceName": "ceshi", "platform": 0, "macID": "asdasd", "adapterNumber": 9527, "firmwareVersion": "1.0.0"], cmd: .firmwareVersion)
}
private func loadDefaultData() {
//
if let json = UserDefaultsManagerFrieBoltt.objectFromSandBox(UserDefaultsKey.kfRealTimeStep), let step = RealtimeStepModel.deserialize(from: json as? [String: Any]) {
2 years ago
if Date(timeIntervalSince1970: TimeInterval(step.timestamp)).isToday() {
realStep.accept(step)
}
}
//
if let json = UserDefaultsManagerFrieBoltt.objectFromSandBox(UserDefaultsKey.kfRealTimeHeartRate), let heartRate = RealtimeHeartRateModel.deserialize(from: json as? [String: Any]) {
2 years ago
if Date(timeIntervalSince1970: TimeInterval(heartRate.timestamp)).isToday() {
realHeartRate.accept(heartRate)
}
}
//
if let json = UserDefaultsManagerFrieBoltt.objectFromSandBox(UserDefaultsKey.kfRealTimeTemperature), let model = RealtimeTemperatureModel.deserialize(from: json as? [String: Any]) {
2 years ago
if Date(timeIntervalSince1970: TimeInterval(model.timestamp)).isToday() {
realTemperature.accept(model)
}
}
//
if let json = UserDefaultsManagerFrieBoltt.objectFromSandBox(UserDefaultsKey.kfRealTimeBloodPressure), let model = RealtimeBloodPressureModel.deserialize(from: json as? [String: Any]) {
2 years ago
if Date(timeIntervalSince1970: TimeInterval(model.timestamp)).isToday() {
realBloodPressure.accept(model)
}
}
//
if let json = UserDefaultsManagerFrieBoltt.objectFromSandBox(UserDefaultsKey.kfRealTimeBloodOxygen), let model = RealtimeBloodOxygenModel.deserialize(from: json as? [String: Any]) {
2 years ago
if Date(timeIntervalSince1970: TimeInterval(model.timestamp)).isToday() {
realBloodOxygen.accept(model)
}
}
}
private func monitorNotification() {
//
kNotificationCenter.rx.notification(Notification.Name(rawValue: BluetoothNotificationAtConnectSuccess))
.subscribe(onNext: { [weak self] (notification) in
guard let `self` = self else { return }
self.deviceConnectState.accept(true)
})
.disposed(by: rx.disposeBag)
//
kNotificationCenter.rx.notification(Notification.Name(rawValue: BluetoothNotificationAtDisconnect))
.subscribe(onNext: { [weak self] (notification) in
guard let `self` = self else { return }
self.deviceConnectState.accept(false)
})
.disposed(by: rx.disposeBag)
//
kNotificationCenter.rx.notification(Notification.Name(rawValue: DeviceControlNotification))
.subscribe(onNext: { [weak self] notification in
guard let `self` = self else { return }
guard let cmd = notification.object as? Int, let bleCmd = BleCMD_FireBoltt(rawValue: cmd) else { return }
2 years ago
let data = notification.userInfo?["data"] as! NSData
let contentData = data.subdata(with: NSMakeRange(13, data.length - 13)) as NSData
self.handleDeviceCmd(blecmd: bleCmd, data: contentData)
})
.disposed(by: rx.disposeBag)
//
kNotificationCenter.rx.notification(Notification.Name(rawValue: DeviceReportRealTimeHealthData))
.subscribe(onNext: { [weak self] notification in
guard let `self` = self else { return }
guard let cmd = notification.object as? Int, let bleCmd = BleCMD_FireBoltt(rawValue: cmd), let dict = notification.userInfo as? [String: Any] else { return }
2 years ago
self.handleRealTimeHealthData(bleCmd: bleCmd, dict: dict)
})
.disposed(by: rx.disposeBag)
}
/// - 使
func clearRealtimeData() {
realStep.accept(RealtimeStepModel())
realHeartRate.accept(RealtimeHeartRateModel())
realTemperature.accept(RealtimeTemperatureModel())
realBloodOxygen.accept(RealtimeBloodOxygenModel())
realBloodPressure.accept(RealtimeBloodPressureModel())
}
}
// MARK: -
extension BluetoothService {
///
func findDevice() {
baseBl.findDevice(withBleCmdTypeFB: .findPhone)
2 years ago
}
///
func handup(isOn: Bool) {
baseBl.gesturesControl(withBleCmdTypeFB: .gesturesControl, hand: 0, raise: isOn, flip: false)
2 years ago
}
///
/// - Parameters:
/// - pushType:
func setPushStatus(pushType: PushType, isOn: Bool) {
let value = pushType.tranfromPushValue(currenValue: GlobalDeviceProfileModel.shareInstance.pushSetValue, isOn: isOn)
GlobalDeviceProfileModel.shareInstance.pushSetValue = value
baseBl.setPushWithBleCmdTypeFB(.setPush, value: value)
2 years ago
}
///
func setHeartRateCheckWithBleCmdType(model: HeartRateCheckModel) {
baseBl.setHeartRateCheckWithBleCmdTypeFB(.heartRateCheck, rateONOFF: model.IsOpen, startTime: model.StartTime, endTime: model.EndTime, interval: model.Interval)
2 years ago
}
///
func notDisturbWithBleCmdType(model: NoDisturbModel) {
baseBl.notDisturb(withBleCmdTypeFB: .notDisturb, onoff: model.IsOpen, startTime: model.StartTime, endTime: model.EndTime)
2 years ago
}
///
func setDrinkRemindWithBleCmdType(model: DrinkingModel) {
baseBl.setDrinkRemindWithBleCmdTypeFB(.setDrinkRemind, drinkONOFF: model.IsOpen, startTime: model.StartTime, endTime: model.EndTime, cycle: model.Cycle, interval: model.Interval)
2 years ago
}
///
func setSedentaryWithBleCmdType(model: SedentaryModel) {
baseBl.setSedentaryWithBleCmdTypeFB(.setSedentary, onoff: model.IsOpen, startTime: model.StartHour, endTime: model.EndHour, cycle: model.Cycle, sittingTime: model.SittingTime, sittingThreshold: model.SittingThreshold)
2 years ago
}
///
func setAlarmClockWithBleCmdType(models: [AlarmModel]) {
baseBl.setAlarmClockWithBleCmdTypeFB(.setAlarmClock, alarmClockArr: models)
2 years ago
}
///
func cameraSwitchWithBleCmdType(isOpen: Bool) {
baseBl.cameraSwitch(withBleCmdTypeFB: .cameraSwitch, onoff: isOpen)
2 years ago
}
///
/// - Parameter isMetric: 0: 1
func unitSetting(metric: Int) {
baseBl.unitSetting(withBleCmdTypeFB: .unitSetting, measure: metric, temperature: 0)
2 years ago
}
///
/// - Parameters:
/// - step:
/// - sportMode: 0: 1: 2: 3: 4:
func setSportTarget(step: Int, sportMode: Int) {
baseBl.setSportTargetWithBleCmdTypeFB(.setSportTarget, targetSteps: step, sportMode: sportMode)
2 years ago
}
///
/// - Parameter user:
func sendBleCmdSetUserInfo(user: UserInfo) {
//
let goal = String(format: "%d", user.stepTarget)
let age = String(format: "%d", user.age())
let sex = user.gender ? "0" : "1"
if let bluetooth = BluetoothFireBoltt.shareInstance(), bluetooth.isConnected {
baseBl.setUserInfoWithBleCmdTypeFB(.setUserInfo, gender: sex, age: age, height: String(user.heightCM), weight: String(user.weightKG), goal: goal, bmi: String(user.bmi()))
2 years ago
}
}
/// ()
/// - Parameter weathers:
func setWeatherPushWithBleCmdType(weathers: [Weather]) {
baseBl.setWeatherPushWithBleCmdTypeFB(.fireBoltt_weatherPush, weathers: weathers.toJSON())
2 years ago
}
/// FLASH
/// - Parameter data:
func falshSendWithBleCmdType(total: Int, curren: Int, lenght: Int, data: Data) {
baseBl.falshSend(withBleCmdTypeFB: .falshSend, total: total, curren: curren, lenght: lenght, data: data)
2 years ago
}
///
/// - Parameters:
/// - number:
/// - type: 0: 1: 2:
/// - fileLenght:
func newDialPushWithBleCmdType(number: Int, type: Int, fileLenght: Int) {
baseBl.newDialPush(withBleCmdTypeFB: .newDialPush, number: number, type: type, fileLenght: fileLenght)
2 years ago
}
///
/// - Parameter filePath:
func newJerryDialPushWithBleCmdType(filePath:String, url:String, fileData:Data) {
baseBl.newJerryDialPush(filePath, urlName: url, fileData: fileData)
}
///
func setTemperatureCheckWithBleCmdType(model: TemperatureCheckModel) {
baseBl.setTemperatureCheckWithBleCmdTypeFB(.temperatureCheck, rateONOFF: model.IsOpen, startTime: model.StartTime, endTime: model.EndTime, interval: model.Interval)
2 years ago
}
///
func syncContactWithBleCmdType(seleteArr:NSArray){
baseBl.syncContact(withBleCmdTypeFB: .syncContact, contentArr: seleteArr as? [Any])
2 years ago
}
///
func qrCodePushWithBleCmdType(payImgStr: UIImage, type: Int){
baseBl.qrCodePush(withBleCmdTypeFB: .qrCodePush, payType:type , qrCodeImg: payImgStr)
2 years ago
}
}
// MARK: -
extension BluetoothService {
///
func checkBleCmdEnable(isShow:Bool) -> Bool {
2 years ago
//
let isConnect = BluetoothFireBoltt.shareInstance()?.isConnected ?? false
2 years ago
if !isConnect {
SVProgressHUD.showError(withStatus: MultiLanguageKey_FB.bleTipFB.localized)
2 years ago
return isConnect
}
//
switch syncState.value {
case .normal:
return true
case .syncing(_):
if isShow
{
SVProgressHUD.showError(withStatus: MultiLanguageKey_FB.syncDataTipFB.localized)
}
2 years ago
return false
}
}
///
func bloothPrepare() {
let bluetooth = BluetoothFireBoltt.shareInstance()!
2 years ago
if !bluetooth.isConnected {
return
}
//
baseBl.setIngTimeWithBleCmdTypeFB(.setIngTime)
2 years ago
//
baseBl.firmwareVersion(withBleCmdTypeFB: .firmwareVersion)
2 years ago
//
baseBl.setSystemUserWithBleCmdTypeFB(.setSystemUser)
2 years ago
//
let userInfo = UserDefaultsManagerFrieBoltt.getUserInfo()!
2 years ago
sendBleCmdSetUserInfo(user: userInfo)
//
baseBl.requestBattery(withBleCmdTypeFB: .requestBattery)
2 years ago
//
baseBl.readProfile(withBleCmdTypeFB: .readProfile)
2 years ago
//
baseBl.readBraceletSet(withBleCmdTypeFB: .readBraceletSet)
2 years ago
//
baseBl.realTimesync(withBleCmdTypeFB: .realTimesync, syncType: 3)
baseBl.realTimesync(withBleCmdTypeFB: .realTimesync, syncType: 2)
baseBl.realTimesync(withBleCmdTypeFB: .realTimesync, syncType: 8)
2 years ago
}
///
func readDeviceProfile() {
let bluetooth = BluetoothFireBoltt.shareInstance()
2 years ago
if let isConnected = bluetooth?.isConnected {
if isConnected {
//
baseBl.readProfile(withBleCmdTypeFB: .readProfile)
2 years ago
}
}
}
/// +
func fbsendSyncDeviceData() {
2 years ago
//
totalCount = 0
//
let adapterInfo = UserDefaultsManagerFrieBoltt.getDeviceInfo()?.adapterInfo
2 years ago
let immediately = adapterInfo != nil
// ok
GCDTimer.shared.scheduledDispatchTimer(WithTimerName: SendSyncDeviceDataTimer, timeInterval: 3.0, queue: .main, repeats: false, immediately: immediately) { [weak self] in
guard let `self` = self else { return }
let adapterInfo = UserDefaultsManagerFrieBoltt.getDeviceInfo()?.adapterInfo
2 years ago
//
self.baseBl.readProfile(withBleCmdTypeFB: .readProfile)
2 years ago
// ,,,,
DataBaseManagerFireBoltt.shared.fbqueryLastRecordData(dataType: .step) { (timestamp) in
2 years ago
self.getHealthData(timestamp: timestamp, type: 3)
}
DataBaseManagerFireBoltt.shared.fbqueryLastRecordData(dataType: .sleep) { (timestamp) in
2 years ago
self.getHealthData(timestamp: timestamp, type: 1)
}
DataBaseManagerFireBoltt.shared.fbqueryLastRecordData(dataType: .heartRate) { (timestamp) in
2 years ago
self.getHealthData(timestamp: timestamp, type: 2)
}
if adapterInfo?.bodyTemperature ?? false == true {
DataBaseManagerFireBoltt.shared.fbqueryLastRecordData(dataType: .temperature) { (timestamp) in
2 years ago
self.getHealthData(timestamp: timestamp, type: 8)
}
}
if adapterInfo?.bloodPressure ?? false == true {
DataBaseManagerFireBoltt.shared.fbqueryLastRecordData(dataType: .bloodPressure) { (timestamp) in
2 years ago
self.getHealthData(timestamp: timestamp, type: 5)
}
}
if adapterInfo?.bloodOxygen ?? false == true {
DataBaseManagerFireBoltt.shared.fbqueryLastRecordData(dataType: .bloodOxygen) { (timestamp) in
2 years ago
self.getHealthData(timestamp: timestamp, type: 7)
}
}
self.totalCount += 1
let todaytimeStr = "\(DateClass.getNowTimeS())"
self.baseBl.syncHealth(withBleCmdTypeFB: .syncHealth, type: 4, timeArr: [todaytimeStr])
2 years ago
//
self.totalRequestCount = BluetoothFireBoltt.shareInstance()!.bluetoothItems.count
2 years ago
self.syncState.accept(.syncing(progress: self.progress))
}
}
private func getHealthData(timestamp: Int?, type: Int) {
// ,
var count = 0
// ,->
if let timeInterval = timestamp {
//
let createDate = Date(timeIntervalSince1970: TimeInterval(timeInterval))
//便
let calendar = Calendar.current
// NSCalendarUnit
let cmps = calendar.dateComponents([.year, .month, .day], from: createDate, to: Date())
if let days = cmps.day {
count = days > 7 ? 7 : (days > 0 ? days : 2)
}
}else {
count = 7
}
//
if (type == 1) {
count += 1
}
//
if (count < 2) {
count = 2
}
//
totalCount += count
//
for i in 1...count {
let time = "\(Int32(Date().timeIntervalSince1970) - Int32((count - i) * 86400))"
//
baseBl.syncHealth(withBleCmdTypeFB: .syncHealth, type: type, timeArr: [time])
2 years ago
}
}
}
// MARK: -
extension BluetoothService {
func handleDeviceCmd(blecmd: BleCMD_FireBoltt, data: NSData) {
2 years ago
//
if blecmd == .findPhone {
// 0 1
let state = data.bytes.load(as: Int.self)
if state == 0 {
stopFindPhone()
}else {
if !isPlaying {
setVoiceStatus()
}
}
}
//
if blecmd == .batteryBack {
let power = (data.subdata(with: NSRange(location: 0, length: 1)) as NSData).bytes.load(as: Int.self)
let status = (data.subdata(with: NSRange(location: 1, length: 1)) as NSData).bytes.load(as: Int.self)
self.power.accept(power)
if status == 2 {
powerState.accept(R.image.fb_power_charge_icon())
2 years ago
return
}
powerState.accept(getPowerImage(power: power))
}
}
func setVoiceStatus() {
//
let audioSession = AVAudioSession.sharedInstance()
//
try? audioSession.setCategory(AVAudioSession.Category.playAndRecord, options: AVAudioSession.CategoryOptions.defaultToSpeaker)
//
try? audioSession.setActive(true)
//
if let path = Bundle.main.path(forResource: "fbs_music", ofType: "m4r") {
2 years ago
AudioServicesCreateSystemSoundID(URL(fileURLWithPath: path) as CFURL, &systemSoundID)
}
//
//
let observer = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
AudioServicesAddSystemSoundCompletion(systemSoundID, nil, nil, {
(soundID, inClientData) -> Void in
let mySelf = Unmanaged<BluetoothService>.fromOpaque(inClientData!)
.takeUnretainedValue()
mySelf.AudioCallback(soundID: soundID)
mySelf.systemAudioCallBack()
}, observer)
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
AudioServicesPlaySystemSound(SystemSoundID(systemSoundID))
GlobalDeviceProfileModel.shareInstance.isPlaying = true
isPlaying = true
showFindPhoneAlert()
localNotification(title: MultiLanguageKey_FB.tipFB.localized, body: MultiLanguageKey_FB.findThePhoneCMDFB.localized)
2 years ago
}
func showFindPhoneAlert() {
let alertVC = UIAlertController(title: MultiLanguageKey_FB.tipFB.localized, message: MultiLanguageKey_FB.findThePhoneCMDFB.localized, preferredStyle: .alert)
let sureAction = UIAlertAction(title: MultiLanguageKey_FB.cancelFB.localized, style: UIAlertAction.Style.default) { [weak self] (action) in
2 years ago
guard let `self` = self else { return }
self.stopFindPhone()
}
alertVC.addAction(sureAction)
self.alertController = alertVC
currentViewController()?.present(alertVC, animated: true, completion: nil)
}
///
func systemAudioCallBack() {
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
}
func AudioCallback(soundID: SystemSoundID) {
AudioServicesPlaySystemSound(soundID)
}
func stopFindPhone() {
isPlaying = false
AudioServicesDisposeSystemSoundID(systemSoundID)
AudioServicesRemoveSystemSoundCompletion(systemSoundID)
AudioServicesDisposeSystemSoundID(kSystemSoundID_Vibrate)
AudioServicesRemoveSystemSoundCompletion(kSystemSoundID_Vibrate)
systemSoundID = 0
alertController?.dismiss(animated: true, completion: nil)
}
// MARK: -
func localNotification(title: String, body: String, dateComponents: DateComponents? = nil, userInfo : [AnyHashable : Any]? = nil) {
if #available(iOS 10, *) {
let content = UNMutableNotificationContent()
content.title = title
content.body = body
content.userInfo = userInfo ?? [:]
var trigger: UNNotificationTrigger?
if let dataCompontnts = dateComponents {
trigger = UNCalendarNotificationTrigger(dateMatching: dataCompontnts, repeats: false)
}
let random = Int(arc4random_uniform(999999999))
let request = UNNotificationRequest(identifier: "id\(random)", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: { error in
print(error ?? "error:nil")
})
} else {
let localNotification = UILocalNotification()
localNotification.fireDate = dateComponents?.date ?? Date()
localNotification.alertBody = body
localNotification.alertTitle = title
localNotification.userInfo = userInfo
localNotification.timeZone = NSTimeZone.default
localNotification.soundName = UILocalNotificationDefaultSoundName
UIApplication.shared.scheduleLocalNotification(localNotification)
}
}
2 years ago
}
// MARK: -
extension BluetoothService: BLEBLDelegate {
func finishedHandle(_ bl: BLEBaseBlFireBoltt!, data: [AnyHashable : Any]!, cmd: BleCMD_FireBoltt) {
2 years ago
switch cmd {
case .setAlarmClock:
print("")
case .setSportTarget:
print("")
case .setUserInfo:
print("")
case .setTheLost:
print("")
case .setSedentary:
print("")
case .setSleep:
print("")
case .setSystemUser:
print("")
case .setDrinkRemind:
print("")
case .setPush:
print("")
case .readBraceletSet:
// mac
if let macStr = data["MACString"] as? String {
if var deviceInfo = UserDefaultsManagerFrieBoltt.getDeviceInfo() {
2 years ago
deviceInfo.MACString = macStr
UserDefaultsManagerFrieBoltt.saveDeviceInfo(deviceInfo: deviceInfo)
2 years ago
}
}
case .readProfile:
let profileModel = GlobalDeviceProfileModel.shareInstance
if data.keys.count == 0 {
return
}
//
let alarmClocks = data["AlarmClock"] as! [[String: Any]]
let alarmModels = [AlarmModel].deserialize(from: alarmClocks) as? [AlarmModel]
profileModel.alarmModels = alarmModels?.filter{ $0.Label == "1" }
//
let remindMode = data["RemindMode"] as! [String: Any]
if let mode = remindMode["RemindType"] {
profileModel.remindMode = (mode as? Int) ?? 1
}
//
let sedentary = data["Sedentary"] as! [String: Any]
profileModel.sedentaryModel = SedentaryModel.deserialize(from: sedentary)
//
let heartRate = data["HeartRate"] as! [String: Any]
profileModel.heartRateModel = HeartRateCheckModel.deserialize(from: heartRate)
//
let drink = data["DrinkRemind"] as! [String: Any]
profileModel.drinkModel = DrinkingModel.deserialize(from: drink)
//
let noDisturb = data["NotDisturb"] as! [String: Any]
profileModel.noDisturbModel = NoDisturbModel.deserialize(from: noDisturb)
//
let gesturesSet = data["GesturesDict"] as! [String: Any]
profileModel.gestureModel = GestureSetModel.deserialize(from: gesturesSet)
//
let push = data["SetPush"] as! [String: Any]
profileModel.pushSetValue = push["IsOpen"] as! Int
//
let temperature = data["Temperature"] as! [String: Any]
profileModel.temperatureModel = TemperatureCheckModel.deserialize(from: temperature)
//
let notificationName = Notification.Name(rawValue: ReadProfileNotice)
NotificationCenter.default.post(name: notificationName, object: nil)
case .fireBoltt_weatherPush:
2 years ago
print("")
case .fireBoltt_ultravioletPush:
2 years ago
print("")
case .fireBoltt_airPressurePush:
2 years ago
print("")
case .fireBoltt_altitudePush:
2 years ago
print("")
case .requestBattery:
//
let power = data["power"] as? Int ?? 0
let status = data["status"] as? Int ?? 0
self.power.accept(power)
if status == 2 {
powerState.accept(R.image.fb_power_charge_icon())
2 years ago
return
}
powerState.accept(getPowerImage(power: power))
case .batteryBack:
print("")
case .unbundledDevice:
print("")
case .unbundledReply:
print("")
case .bindingReply:
print("")
case .relationDisplay:
print("")
case .gesturesControl:
print("")
case .bindingDevice:
print("")
case .cameraSwitch:
print("")
case .cameraON:
print("")
case .cameraOFF:
print("")
case .dialPush:
print("")
case .dialRequest:
print("")
case .findPhone:
print("")
case .findDevice:
print("")
case .syncHealth:
let dicData = data as! [String:Any]
handleHealthData(dict: dicData)
totalCount -= 1
//
progressUpdate()
case .syncBack:
print("")
case .sleepData:
print("")
case .stepData:
print("")
case .heartData:
print("")
case .sportModelData:
print("")
case .realTimesync:
//
guard let temp = data["DataType"] as? Int, let bleCmd = BleCMD_FireBoltt(rawValue: temp) else { return }
2 years ago
handleRealTimeHealthData(bleCmd: bleCmd, dict: data as! [String : Any])
case .realStep:
print("")
case .realHeartData:
print("")
case .bloodPressure:
print("")
case .bloodOxygen:
print("")
case .realBloodPressure:
print("")
case .realBloodOxygen:
print("")
case .sportStateToDevice:
print("")
case .sportStateToIphone:
print("")
case .gpsSignalStrength:
print("")
case .firmwareUpdate:
print("")
case .firmwareVersion:
//
let firwareModel = FirmwareModel.deserialize(from: data as? [String: Any])
GlobalDeviceProfileModel.shareInstance.firwareModel = firwareModel
//
if let adapterNumbe = firwareModel?.adapterNumber, var deviceInfo = UserDefaultsManagerFrieBoltt.getDeviceInfo() {
2 years ago
deviceInfo.adapterNumber = adapterNumbe
UserDefaultsManagerFrieBoltt.saveDeviceInfo(deviceInfo: deviceInfo)
2 years ago
}
// &
if let adapterNumber = firwareModel?.adapterNumber, let firmwareVersion = firwareModel?.firmwareVersion {
ProviderRequest(.getLastAppUpgrade(packageName: "FireBoltt.\(adapterNumber)"))
2 years ago
.subscribe(onNext: { [weak self] json in
var url = json["data"]["url"].stringValue
url += json["data"]["apkName"].stringValue
let version = json["data"]["version"].intValue
let newVersion = String(format: "%d.%d.%d", version / 1000, version / 100 % 10, version % 100)
let isNew = newVersion > firmwareVersion
let isMandatory = json["data"]["imposed"].boolValue
self?.cloudFirmwareInfo.onNext((isNew, isMandatory))
})
.disposed(by: rx.disposeBag)
ProviderRequest(.getDeviceFunByBrandCode(brandCode: adapterNumber))
.subscribe(onNext: { [weak self] json in
if let data = json["data"].array, data.count > 0 {
let funcCmds = data.map { $0["funcCmd"].intValue }
let adapterInfo = AdapterInfo(funcCmds: funcCmds, adapterNumber: adapterNumber)
if var deviceInfo = UserDefaultsManagerFrieBoltt.getDeviceInfo() {
2 years ago
deviceInfo.adapterInfo = adapterInfo
UserDefaultsManagerFrieBoltt.saveDeviceInfo(deviceInfo: deviceInfo)
2 years ago
}
//
self?.adapterInfoUpdate.onNext(adapterInfo)
}
})
.disposed(by: rx.disposeBag)
}
case .remindSwitch:
print("")
case .notDisturb:
print("")
case .remindModel:
print("")
case .messageSync:
print("")
case .getSleepData:
print("")
case .sleepDataBack:
print("")
case .checkDaySport:
print("")
case .heartRateCheck:
print("")
case .qrCodePush:
NotificationCenter.default.post(name: Notification.Name(rawValue: CmdSuccess), object: cmd)
print("")
case .weatherIndex:
print("")
case .braceletPialPush:
print("")
case .unitSetting:
print("")
case .restoreFactory:
print("")
case .syncContact:
NotificationCenter.default.post(name: Notification.Name(rawValue: CmdSuccess), object: cmd)
default: break
}
//
NotificationCenter.default.post(name: Notification.Name(rawValue: CmdSuccess), object: cmd)
}
func timeOutHandle(_ bl: BLEBaseBlFireBoltt!, data: [AnyHashable : Any]!, cmd: BleCMD_FireBoltt) {
2 years ago
if cmd == .syncHealth {
switch syncState.value {
case .syncing:
//
progressUpdate()
default: break
}
}
//
NotificationCenter.default.post(name: Notification.Name(rawValue: CmdTimeout), object: cmd)
}
///
private func progressUpdate() {
//
let itemsCount = BluetoothFireBoltt.shareInstance()!.bluetoothItems.count
2 years ago
let realProgress = Double(totalRequestCount - itemsCount) / Double(totalRequestCount)
if realProgress - progress >= 0.2 {
progress += 0.2
syncState.accept(.syncing(progress: progress))
}
//
if totalCount <= 0 && progress < 1.0 {
progress = 1.0
syncState.accept(.normal)
}
//
if progress >= 1 {
progress = 0.2
}
}
}
// MARK: -
extension BluetoothService {
private func handleHealthData(dict: [String: Any]) {
//
let deviceInfo = UserDefaultsManagerFrieBoltt.getDeviceInfo()
2 years ago
let macID = deviceInfo?.MACString ?? ""
//
if let data = dict["STEP"], let stepModel = StepModel.deserialize(from: data as? [String: Any]) {
// 0
if stepModel.stepNumber <= 0 { return }
stepModel.macID = macID
DataBaseManagerFireBoltt.shared.insertModels(models: [stepModel], dataType: .step)
2 years ago
}
if let data = dict["SLEEP"], let sleepModel = SleepModel.deserialize(from: data as? [String: Any]) {
// 0
if sleepModel.totalSleepDuration <= 0 { return }
sleepModel.macID = macID
// >12+1
let fallingSleepHour = DateClass.getTimeStrToDate(formatStr: "yyyy-MM-dd HH:mm", timeStr: sleepModel.fallingSleepTimes).hour()
if fallingSleepHour > 12, let dataDate = DateClass.getTimeStrToDate(formatStr: "yyyy-MM-dd", timeStr: sleepModel.dataDate).getDay(offset: 1)?.string(withFormat: "yyyy-MM-dd") {
sleepModel.dataDate = dataDate
}
DataBaseManagerFireBoltt.shared.insertModels(models: [sleepModel], dataType: .sleep)
2 years ago
//
sleepUpdate.onNext(())
}
if let data = dict["HEARTRATE"], let heartRateModel = HeartRateModel.deserialize(from: data as? [String: Any]) {
// 0
if heartRateModel.heartAvg <= 0 { return }
heartRateModel.macID = macID
DataBaseManagerFireBoltt.shared.insertModels(models: [heartRateModel], dataType: .heartRate)
2 years ago
}
if let data = dict["SPORT"], let sportModels = [SportModel].deserialize(from: data as? [[String: Any]]) as? [SportModel] {
var temps: [SportModel] = []
sportModels.forEach { sportModel in
sportModel.macID = macID
// 0
if sportModel.duration > 0 {
temps.append(sportModel)
}
}
DataBaseManagerFireBoltt.shared.insertModels(models: temps, dataType: .sport)
2 years ago
//
sportUpdate.onNext(())
}
if let data = dict["TEMPERATURE"], let model = TemperatureModel.deserialize(from: data as? [String: Any]) {
// 0
if model.temperatureAvg <= 0 { return }
model.macID = macID
DataBaseManagerFireBoltt.shared.insertModels(models: [model], dataType: .temperature)
2 years ago
}
if let data = dict["BLOODPRESSURE"], let model = BloodPressureModel.deserialize(from: data as? [String: Any]) {
// 0
if model.sbpAvg <= 0 { return }
model.macID = macID
DataBaseManagerFireBoltt.shared.insertModels(models: [model], dataType: .bloodPressure)
2 years ago
}
if let data = dict["BLOODOXYGEN"], let model = BloodOxygenModel.deserialize(from: data as? [String: Any]) {
// 0
if model.bloodOxygenAvg <= 0 { return }
model.macID = macID
DataBaseManagerFireBoltt.shared.insertModels(models: [model], dataType: .bloodOxygen)
2 years ago
}
}
private func handleRealTimeHealthData(bleCmd: BleCMD_FireBoltt, dict: [String: Any]) {
let deviceInfo = UserDefaultsManagerFrieBoltt.getDeviceInfo()
2 years ago
let macID = deviceInfo?.MACString ?? ""
switch bleCmd {
case .realStep:
guard let realtimeStepModel = RealtimeStepModel.deserialize(from: dict) else { return }
if realtimeStepModel.stepNumber <= 0 { return }
realStep.accept(realtimeStepModel)
//
if let json = realtimeStepModel.toJSON() {
UserDefaultsManagerFrieBoltt.saveObjectsToSandBox(key: UserDefaultsKey.kfRealTimeStep, value: json)
2 years ago
}
// //
// let stepModel = StepModel()
// let dataDate = DateClass.timeIntervalChangeToTimeStr(timeInterval: Double(realtimeStepModel.timestamp))
//
// stepModel.macID = macID
// stepModel.dataDate = dataDate
// stepModel.stepNumber = realtimeStepModel.stepNumber
// stepModel.stepDistance = realtimeStepModel.stepDistance
// stepModel.stepCalorie = realtimeStepModel.stepCalorie
// DataBaseManagerFireBoltt.shared.insertModels(models: [stepModel], dataType: .step)
2 years ago
case .realHeartData:
guard let realtimeHeartRateModel = RealtimeHeartRateModel.deserialize(from: dict) else { return }
if realtimeHeartRateModel.heartRate <= 0 { return }
realHeartRate.accept(realtimeHeartRateModel)
//
if let json = realtimeHeartRateModel.toJSON() {
UserDefaultsManagerFrieBoltt.saveObjectsToSandBox(key: UserDefaultsKey.kfRealTimeHeartRate, value: json)
2 years ago
}
case .realTemperature:
guard let model = RealtimeTemperatureModel.deserialize(from: dict) else { return }
if model.temperature <= 0 { return }
realTemperature.accept(model)
//
if let json = model.toJSON() {
UserDefaultsManagerFrieBoltt.saveObjectsToSandBox(key: UserDefaultsKey.kfRealTimeTemperature, value: json)
2 years ago
}
case .realBloodPressure:
guard let model = RealtimeBloodPressureModel.deserialize(from: dict) else { return }
if model.sbp <= 0 { return }
realBloodPressure.accept(model)
//
if let json = model.toJSON() {
UserDefaultsManagerFrieBoltt.saveObjectsToSandBox(key: UserDefaultsKey.kfRealTimeBloodPressure, value: json)
2 years ago
}
case .realBloodOxygen:
guard let model = RealtimeBloodOxygenModel.deserialize(from: dict) else { return }
if model.bloodOxygen <= 0 { return }
realBloodOxygen.accept(model)
//
if let json = model.toJSON() {
UserDefaultsManagerFrieBoltt.saveObjectsToSandBox(key: UserDefaultsKey.kfRealTimeBloodOxygen, value: json)
2 years ago
}
default: break
}
}
}
extension BluetoothService {
private func getPowerImage(power: Int) -> UIImage? {
if power > 75 {
return R.image.power_4()
}
if power > 50 {
return R.image.power_3()
}
if power > 25 {
return R.image.power_2()
}
if power > 10 {
return R.image.power_1()
}
return R.image.power_0()
}
}