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

//
// 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)
}
}