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.
 
 
 

318 lines
13 KiB

//
// DeviceViewModels.swift
// Lookfit
//
// Created by lemo. on 2020/3/7.
// Copyright © 2020 Sheldon. All rights reserved.
//
import UIKit
import CoreLocation
import RxSwift
/// KEY
fileprivate let LocalWeatherKEY = "LocalWeatherKEY"
struct Weather: HandyJSON {
var lowTemperature: String = ""
var highTemperature: String = ""
var currenTemperature: String = ""
var weatherType: Int = 0
var date: String = ""
}
class DeviceViewModels: ViewModel, ViewModelType {
struct Input {
let syncData: Observable<Void>
}
struct Output {
let syncState: Driver<String>
}
///
let isBinding = BehaviorRelay<Bool>(value: false)
//
let deviceName = BehaviorRelay<String>(value: "")
let connectState = BehaviorRelay<Bool>(value: false)
let powerState = BehaviorRelay<UIImage?>(value: R.image.power_0())
let syncState = BehaviorRelay<String?>(value: MultiLanguageKey.syncData.localized)
///
let datasource = BehaviorRelay<[SectionModel<String, TableViewCellModel>]>.init(value: [])
///
let mandatoryUpdate = BehaviorRelay<FirmwareUpdateViewModels?>(value: nil)
///
private var locationManager: CLLocationManager?
///
private var isNewFirmware: Bool = false
override init() {
super.init()
BluetoothService.shared.powerState
.bind(to: powerState)
.disposed(by: rx.disposeBag)
loadDefualtData()
monitor()
///
loadFuncation()
}
func transform(input: DeviceViewModels.Input) -> DeviceViewModels.Output {
input.syncData
.subscribe(onNext: { _ in
if BluetoothService.shared.checkBleCmdEnable(isShow: true) {
BluetoothService.shared.sendSyncDeviceData()
}
})
.disposed(by: rx.disposeBag)
let syncState = BluetoothService.shared.syncState
.flatMapLatest { (state) -> Observable<String> in
switch state {
case .normal: return Observable.just(MultiLanguageKey.syncData.localized)
case .syncing(let progrss): print("%@",progrss); return Observable.just("\(Int(progrss * 100))%")
}
}.asDriver(onErrorJustReturn: MultiLanguageKey.syncData.localized)
return Output(syncState: syncState)
}
func loadDefualtData() {
//
guard let deviceInfo = UserDefaultsManager.getDeviceInfo() else {
return
}
isBinding.accept(true)
deviceName.accept(deviceInfo.deviceName)
//
if Bluetooth.shareInstance()!.isConnected {
self.connectState.accept(true)
self.connctDeviceConfig()
}
else
{
Bluetooth.shareInstance()!.startAndStopReconnect(true)
}
}
func monitor() {
//
kNotificationCenter.rx.notification(Notification.Name(rawValue: BindingDevice))
.subscribe(onNext: { [weak self] (notification) in
guard let `self` = self else { return }
self.loadDefualtData()
})
.disposed(by: rx.disposeBag)
//
BluetoothService.shared.deviceConnectState
.subscribe(onNext: { [weak self] (state) in
guard let `self` = self else { return }
self.connectState.accept(state)
if state {
self.loadDefualtData()
}
})
.disposed(by: rx.disposeBag)
//
BluetoothService.shared.adapterInfoUpdate
.subscribe(onNext: { [weak self] (state) in
self?.loadFuncation()
})
.disposed(by: rx.disposeBag)
//
kNotificationCenter.rx.notification(Notification.Name(rawValue: ReadProfileNotice))
.subscribe(onNext: { [weak self] (notification) in
guard let `self` = self else { return }
self.loadFuncation()
})
.disposed(by: rx.disposeBag)
//
kNotificationCenter.rx.notification(Notification.Name(rawValue: UnBindingDevice))
.subscribe(onNext: { [weak self] (notification) in
guard let `self` = self else { return }
self.isBinding.accept(false)
//
UserDefaultsManager.deleteRealTimeData()
BluetoothService.shared.clearRealtimeData()
///
UserDefaultsManager.deleteDeviceInfo()
})
.disposed(by: rx.disposeBag)
//
BluetoothService.shared.cloudFirmwareInfo
.subscribe(onNext: { [weak self] (isNew, isMandatory) in
self?.isNewFirmware = isNew
if isNew == false { return }
//
if isMandatory {
//
Bluetooth.shareInstance()?.removeCmdItem()
let viewModel = FirmwareUpdateViewModels()
self?.mandatoryUpdate.accept(viewModel)
return
}
})
.disposed(by: rx.disposeBag)
}
}
extension DeviceViewModels {
func loadFuncation() {
//
let section1: [FunctionType] = [.findPhone, .remoteCamera]
var section2: [FunctionType] = [.callRemind, .messageRemind, .notice]
var section3: [FunctionType] = [.unBinding]
//
if let adapterInfo = UserDefaultsManager.getDeviceInfo()?.adapterInfo {
// Section2
if adapterInfo.notDisturb { section2.insert(.handUp, at: 0) }
if adapterInfo.notDisturb { section2.append(.notDisturb) }
if adapterInfo.heartRate { section2.append(.heartCheck) }
if adapterInfo.bodyTemperature { section2.append(.tempeartureCheck) }
if adapterInfo.alarmRemind { section2.append(.alarmClock) }
if adapterInfo.drinkRemind { section2.append(.drinkRemind) }
if adapterInfo.sedentaryRemind { section2.append(.sedentary) }
if adapterInfo.telephoneBook { section2.append(.telephoneBook) }
if adapterInfo.businessCard { section2.append(.businessCard) }
if adapterInfo.theWallet { section2.append(.theWallet) }
if adapterInfo.music { section2.append(.music) }
// Section3
if adapterInfo.firmwareVersion { section3.insert(.firmwareUpgrade, at: 0) }
if adapterInfo.wechatSport { section3.insert(.wechatSport, at: 1) }
if adapterInfo.dailPush { section3.insert(.dialPush, at: 0) }
}
let funcations: [[FunctionType]] = [section1, section2, section3]
var sections: [SectionModel<String, TableViewCellModel>] = []
funcations.forEach { (types) in
var cellModels: [TableViewCellModel] = []
types.enumerated().forEach { (index, type) in
let isBottomLine = index != types.count - 1
let isON = getSwitchState(type: type)
var description: String?
if type == .firmwareUpgrade, let firmwareVersion = GlobalDeviceProfileModel.shareInstance.firwareModel?.firmwareVersion {
description = "V" + firmwareVersion
}
let cellModel = TableViewCellModel(title: type.title(), isSwitch: type.isSwitch(), description: description, isArrows: !type.isSwitch(), isOn: isON, image: nil, isBottomLine: isBottomLine, functionType: type)
if type == .firmwareUpgrade {
cellModel.redPoint.accept(isNewFirmware)
}
cellModels.append(cellModel)
}
sections.append(SectionModel(model: "", items: cellModels))
}
datasource.accept(sections)
}
///
func connctDeviceConfig() {
BluetoothService.shared.bloothPrepare()
BluetoothService.shared.sendSyncDeviceData()
//
loadWeather()
}
///
/// - Parameter type:
private func getSwitchState(type: FunctionType) -> Bool {
switch type {
case .handUp: return GlobalDeviceProfileModel.shareInstance.gestureModel?.Raise ?? false
case .callRemind: return PushType.call.getSwitchState(currenValue: GlobalDeviceProfileModel.shareInstance.pushSetValue)
case .messageRemind: return PushType.message.getSwitchState(currenValue: GlobalDeviceProfileModel.shareInstance.pushSetValue)
default: return false
}
}
}
// MARK:-
extension DeviceViewModels: CLLocationManagerDelegate {
private func loadWeather() {
//
let todayStr = DateClass.getCurrentTimeStr(formatStr: "yyyy-MM-dd")
if let jsons = kUserDefualt.string(forKey: LocalWeatherKEY), let weathers: [Weather?] = [Weather].deserialize(from: jsons), let today = weathers.first, today?.date == todayStr {
var tempWeathers: [Weather] = []
weathers.forEach { item in
if let item = item {
tempWeathers.append(item)
}
}
if weathers.count > 0 {
//
BluetoothService.shared.setWeatherPushWithBleCmdType(weathers: tempWeathers)
}
return
}
//
let location = CLLocationManager.locationServicesEnabled()
if location {
locationManager = CLLocationManager()
locationManager?.delegate = self
locationManager?.requestWhenInUseAuthorization()
locationManager?.startUpdatingLocation()
}else {
showAlert(keyWindow.rootViewController!, MultiLanguageKey.locationTip.localized, confirmText: "OK", handle: {})
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let fristLocation = locations.first else { return }
//
locationManager?.delegate = nil
//
let lat = fristLocation.coordinate.latitude
let lon = fristLocation.coordinate.longitude
Observable.zip(ProviderRequest(APIManager.getHeFengLiveWeather(lat: "\(lat)", lon: "\(lon)")).asObservable(),ProviderRequest(APIManager.getHeFengForecastWeather(lat: "\(lat)", lon: "\(lon)")).asObservable())
.subscribe(onNext: { [weak self] (liveJson, forecastJson) in
guard let `self` = self else { return }
let liveData = liveJson["data"]
let currenTemperature = liveData["tmp"].stringValue
let forecastData = forecastJson["data"].arrayValue
var weathers: [Weather] = []
//
let weatherType = self.getWeatherCode(hfCode: liveData["cond_code"].stringValue)
let currenData = forecastData[0]
let lowTemperature = currenData["tmp_min"].stringValue
let highTemperature = currenData["tmp_max"].stringValue
let liveDate = currenData["date"].stringValue
let currenWeather = Weather(lowTemperature: lowTemperature, highTemperature: highTemperature, currenTemperature: currenTemperature, weatherType: weatherType, date: liveDate)
weathers.append(currenWeather)
//
forecastData.enumerated().forEach { index, json in
if index > 0 {
let weatherType = self.getWeatherCode(hfCode: liveData["cond_code_n"].stringValue)
let lowTemperature = json["tmp_min"].stringValue
let highTemperature = json["tmp_max"].stringValue
let date = currenData["date"].stringValue
let weather = Weather(lowTemperature: lowTemperature, highTemperature: highTemperature, currenTemperature: "0", weatherType: weatherType, date: date)
weathers.append(weather)
}
}
BluetoothService.shared.setWeatherPushWithBleCmdType(weathers: weathers)
//
kUserDefualt.set(weathers.toJSONString(), forKey: LocalWeatherKEY)
})
.disposed(by: rx.disposeBag)
}
/// codecode
/// - Parameter hfCode: code
private func getWeatherCode(hfCode: String) -> Int {
let codeInt = hfCode.integerValue
if codeInt >= 100 && codeInt < 104 {
return 0
}else if codeInt >= 104 && codeInt < 300 {
return 1
}else if codeInt >= 300 && codeInt < 400 {
return 2
}else if codeInt >= 400 && codeInt < 500 {
return 3
}
return 1
}
}