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.
211 lines
9.7 KiB
211 lines
9.7 KiB
// |
|
// HealthHomeViewModels.swift |
|
// Lookfit |
|
// |
|
// Created by Sheldon on 2021/9/19. |
|
// Copyright © 2021 Sheldon. All rights reserved. |
|
// |
|
|
|
import UIKit |
|
|
|
class HealthHomeViewModels: ViewModel { |
|
|
|
// 用户信息 |
|
let userIcon = BehaviorRelay<UIImage?>(value: R.image.icon_header()) |
|
let userNickname = BehaviorRelay<String?>(value: nil) |
|
|
|
// 健康数据 |
|
let relay = BehaviorRelay<[HealthSection]>(value: []) |
|
/// 用户信息 |
|
private var userInfo = BehaviorRelay<UserInfo?>(value: nil) |
|
private var sleepHeartCellVM: SleepHeartCellViewModels? |
|
|
|
/// 发现DFU设备,自动升级 |
|
let dfuDeviceUpgrate = PublishSubject<FirmwareUpdateViewModels>() |
|
|
|
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<UIImage?> in |
|
return Observable.just(userInfo?.avatarImg) |
|
}) |
|
.filter { $0 != nil } |
|
.bind(to: userIcon) |
|
.disposed(by: rx.disposeBag) |
|
userInfo.flatMapLatest({ (userInfo) -> Observable<String?> 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<String> 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<String> 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<String> 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<String> 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<String> 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..<totalRow) { |
|
items.insert(HealthSectionItem.blankItem, at: 1 + i * 4) |
|
var endIndex = 4 + i * 4 |
|
if endIndex > 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<UserInfo?> 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) |
|
} |
|
}
|
|
|