// // HealthHomeViewModels.swift // Lookfit // // Created by Sheldon on 2021/9/19. // Copyright © 2021 Sheldon. All rights reserved. // import UIKit class HealthHomeViewModels: ViewModel { // 用户信息 let userIcon = BehaviorRelay(value: R.image.icon_header()) let userNickname = BehaviorRelay(value: nil) // 健康数据 let relay = BehaviorRelay<[HealthSection]>(value: []) /// 用户信息 private var userInfo = BehaviorRelay(value: nil) private var sleepHeartCellVM: SleepHeartCellViewModels? /// 发现DFU设备,自动升级 let dfuDeviceUpgrate = PublishSubject() private var tempDisposeBag = DisposeBag() override init() { super.init() // 监听系统时间改变 var currenDay = DateClass.todayString() kNotificationCenter.rx.notification(UIApplication.significantTimeChangeNotification) .subscribe(onNext: { notication in // 日期改变了 let newDay = DateClass.todayString() if currenDay != newDay { currenDay = newDay kNotificationCenter.post(name: NSNotification.Name(rawValue: DateChange), object: nil) } }) .disposed(by: rx.disposeBag) loadDefaultData() loadHealthData() monitor() } private func loadDefaultData() { userInfo.accept(UserDefaultsManager.getUserInfo()) userInfo.flatMapLatest({ (userInfo) -> Observable in return Observable.just(userInfo?.avatarImg) }) .filter { $0 != nil } .bind(to: userIcon) .disposed(by: rx.disposeBag) userInfo.flatMapLatest({ (userInfo) -> Observable in return Observable.just(userInfo?.nickname) }) .bind(to: userNickname) .disposed(by: rx.disposeBag) } private func loadHealthData() { tempDisposeBag = DisposeBag() var items: [HealthSectionItem] = [] // 功能适配 var defaultTypes: [HealthType] = [.step, .heartRate] if let adapterInfo = UserDefaultsManager.getDeviceInfo()?.adapterInfo { if adapterInfo.sleep { defaultTypes.insert(.sleep, at: 1) } if adapterInfo.bodyTemperature { defaultTypes.append(.temperature) } if adapterInfo.bloodPressure { defaultTypes.append(.bloodPressure) } if adapterInfo.bloodOxygen { defaultTypes.append(.bloodOxygen) } // defaultTypes.append(.temperature) // defaultTypes.append(.bloodPressure) // defaultTypes.append(.bloodOxygen) } // 数据拼接 defaultTypes.forEach { type in var item: HealthSectionItem if type == .step { let stepCellVM = StepCellViewModels() let stepItem = HealthSectionItem.stepItem(viewModel: stepCellVM) item = stepItem // 数据绑定 BluetoothService.shared.realStep .bind(to: stepCellVM.realStepModel) .disposed(by: tempDisposeBag) }else { let healthItemCellVM = HealthCellViewModels(type: type) let healthItem = HealthSectionItem.healthItem(viewModel: healthItemCellVM) item = healthItem // 数据绑定 switch type { case .sleep: BluetoothService.shared.sleepUpdate .subscribe(onNext: { _ in DataBaseManager.shared.querySleepModel(dataDate: DateClass.todayString(), queryType: .day) { [weak self] (model) in guard let sleepModel = model.first as? SleepModel else { return } let sleep = String(format: "%.1f", Float(sleepModel.totalSleepDuration) / 60.0) let progress = Float(sleepModel.totalSleepDuration) / Float(self?.userInfo.value?.sleepTarget ?? 480) healthItemCellVM.value.accept(sleep) healthItemCellVM.progress.accept(progress) } }) .disposed(by: tempDisposeBag) userInfo.flatMapLatest { (userInfo) -> Observable in let sleepTarget = String(format: "%.1f", Float(userInfo?.sleepTarget ?? 480) / 60.0) let value = MultiLanguageKey.sleepTarget.localized + ":" + sleepTarget return Observable.just(value) }.bind(to: healthItemCellVM.target) .disposed(by: tempDisposeBag) case .heartRate: BluetoothService.shared.realHeartRate .flatMapLatest { (heartRate) -> Observable in let value = heartRate.heartRate == 0 ? "--" : String(heartRate.heartRate) return Observable.just(value) } .bind(to: healthItemCellVM.value) .disposed(by: tempDisposeBag) case .temperature: BluetoothService.shared.realTemperature .flatMapLatest { (temperature) -> Observable in let value = temperature.temperature == 0 ? "--" : String(format: "%.1f", temperature.temperature) return Observable.just(value) } .bind(to: healthItemCellVM.value) .disposed(by: tempDisposeBag) case .bloodPressure: BluetoothService.shared.realBloodPressure .flatMapLatest { (model) -> Observable in let value = model.sbp == 0 ? "--" : String(format: "%ld/%ld", model.sbp, model.dbp) return Observable.just(value) } .bind(to: healthItemCellVM.value) .disposed(by: tempDisposeBag) case .bloodOxygen: BluetoothService.shared.realBloodOxygen .flatMapLatest { (model) -> Observable in let value = model.bloodOxygen == 0 ? "--" : String(model.bloodOxygen) + "%" return Observable.just(value) } .bind(to: healthItemCellVM.value) .disposed(by: tempDisposeBag) default: break } } items.append(item) } // 插入空Item(一行四个Item,每行第一个最后一个插入) let tempItems = items[1...items.count - 1] let totalRow = tempItems.count/2 + tempItems.count%2 for i in (0.. items.count { endIndex = items.count } items.insert(HealthSectionItem.blankItem, at: endIndex) } let section = HealthSection.health(title: "", items: items) relay.accept([section]) } private func monitor() { // 用户信息更新 kNotificationCenter.rx.notification(Notification.Name(rawValue: UserInfoUpdate)) .flatMapLatest({ _ -> Observable in return Observable.just(UserDefaultsManager.getUserInfo()) }) .bind(to: userInfo) .disposed(by: rx.disposeBag) // 数据同步完成刷新睡眠 BluetoothService.shared.syncState.skip(1) .subscribe(onNext: { [weak self] (syncState) in guard let `self` = self else { return } switch syncState { case .normal: DataBaseManager.shared.querySleepModel(dataDate: DateClass.getCurrentTimeStr(formatStr: "yyyy-MM-dd"), queryType: .day) { (model) in guard let sleepModel = model.first as? SleepModel else { return } let sleep = String(format: "%.1f", Float(sleepModel.totalSleepDuration) / 60.0) let progress = Float(sleepModel.totalSleepDuration) / Float(self.userInfo.value?.sleepTarget ?? 480) self.sleepHeartCellVM?.sleep.accept(sleep) self.sleepHeartCellVM?.sleepProgress.accept(progress) } default: break } }) .disposed(by: rx.disposeBag) // 日期改变 kNotificationCenter.rx.notification(Notification.Name(rawValue: DateChange)) .subscribe(onNext: { [weak self] notication in guard let `self` = self else { return } self.loadHealthData() }) .disposed(by: rx.disposeBag) // 功能适配 BluetoothService.shared.adapterInfoUpdate .subscribe(onNext: { [weak self] _ in guard let `self` = self else { return } self.loadHealthData() }) .disposed(by: rx.disposeBag) // DFU设备 kNotificationCenter.rx.notification(Notification.Name(rawValue: BluetoothNotificationAtDFUConnectSuccess)) .subscribe(onNext: { [weak self] _ in guard let `self` = self else { return } let viewModel = FirmwareUpdateViewModels(isDFU: true) self.dfuDeviceUpgrate.onNext(viewModel) }) .disposed(by: rx.disposeBag) } }