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
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) |
|
} |
|
|
|
|
|
/// 和风天气code转协议指令code |
|
/// - 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 |
|
} |
|
|
|
}
|
|
|