|
|
|
//
|
|
|
|
// DeviceViewModels.swift
|
|
|
|
// FireBoltt
|
|
|
|
//
|
|
|
|
// 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_FB.syncDataFB.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)
|
|
|
|
fbloadDefualtData()
|
|
|
|
monitor()
|
|
|
|
/// 加载功能列表
|
|
|
|
fbloadFuncation()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func transform(input: DeviceViewModels.Input) -> DeviceViewModels.Output {
|
|
|
|
input.syncData
|
|
|
|
.subscribe(onNext: { _ in
|
|
|
|
if BluetoothService.shared.checkBleCmdEnable(isShow: true) {
|
|
|
|
BluetoothService.shared.fbsendSyncDeviceData()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.disposed(by: rx.disposeBag)
|
|
|
|
let syncState = BluetoothService.shared.syncState
|
|
|
|
.flatMapLatest { (state) -> Observable<String> in
|
|
|
|
switch state {
|
|
|
|
case .normal: return Observable.just(MultiLanguageKey_FB.syncDataFB.localized)
|
|
|
|
case .syncing(let progrss): print("%@",progrss); return Observable.just("\(Int(progrss * 100))%")
|
|
|
|
}
|
|
|
|
}.asDriver(onErrorJustReturn: MultiLanguageKey_FB.syncDataFB.localized)
|
|
|
|
|
|
|
|
return Output(syncState: syncState)
|
|
|
|
}
|
|
|
|
|
|
|
|
func fbloadDefualtData() {
|
|
|
|
// 绑定状态
|
|
|
|
guard let deviceInfo = UserDefaultsManagerFrieBoltt.getDeviceInfo() else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
isBinding.accept(true)
|
|
|
|
deviceName.accept(deviceInfo.deviceName)
|
|
|
|
// 连接状态
|
|
|
|
if BluetoothFireBoltt.shareInstance()!.isConnected {
|
|
|
|
self.connectState.accept(true)
|
|
|
|
self.connctDeviceConfig()
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BluetoothFireBoltt.shareInstance()!.startAndStopReconnect(true)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func monitor() {
|
|
|
|
// 绑定成功
|
|
|
|
kNotificationCenter.rx.notification(Notification.Name(rawValue: BindingDeviceFireBoltt))
|
|
|
|
.subscribe(onNext: { [weak self] (notification) in
|
|
|
|
guard let `self` = self else { return }
|
|
|
|
self.fbloadDefualtData()
|
|
|
|
})
|
|
|
|
.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.fbloadDefualtData()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.disposed(by: rx.disposeBag)
|
|
|
|
// 设备适配更新
|
|
|
|
BluetoothService.shared.adapterInfoUpdate
|
|
|
|
.subscribe(onNext: { [weak self] (state) in
|
|
|
|
self?.fbloadFuncation()
|
|
|
|
})
|
|
|
|
.disposed(by: rx.disposeBag)
|
|
|
|
// 设备配置刷新
|
|
|
|
kNotificationCenter.rx.notification(Notification.Name(rawValue: ReadProfileNotice))
|
|
|
|
.subscribe(onNext: { [weak self] (notification) in
|
|
|
|
guard let `self` = self else { return }
|
|
|
|
self.fbloadFuncation()
|
|
|
|
})
|
|
|
|
.disposed(by: rx.disposeBag)
|
|
|
|
// 解绑设备
|
|
|
|
kNotificationCenter.rx.notification(Notification.Name(rawValue: UnBindingDeviceFireBoltt))
|
|
|
|
.subscribe(onNext: { [weak self] (notification) in
|
|
|
|
guard let `self` = self else { return }
|
|
|
|
self.isBinding.accept(false)
|
|
|
|
// 清空实时数据
|
|
|
|
UserDefaultsManagerFrieBoltt.deleteRealTimeData()
|
|
|
|
BluetoothService.shared.clearRealtimeData()
|
|
|
|
/// 清空设备信息
|
|
|
|
UserDefaultsManagerFrieBoltt.deleteDeviceInfo()
|
|
|
|
})
|
|
|
|
.disposed(by: rx.disposeBag)
|
|
|
|
// 云端固件信息
|
|
|
|
BluetoothService.shared.cloudFirmwareInfo
|
|
|
|
.subscribe(onNext: { [weak self] (isNew, isMandatory) in
|
|
|
|
self?.isNewFirmware = isNew
|
|
|
|
if isNew == false { return }
|
|
|
|
// 强制升级
|
|
|
|
if isMandatory {
|
|
|
|
// 清空当前指令队列
|
|
|
|
BluetoothFireBoltt.shareInstance()?.removeCmdItem()
|
|
|
|
let viewModel = FirmwareUpdateViewModels()
|
|
|
|
self?.mandatoryUpdate.accept(viewModel)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.disposed(by: rx.disposeBag)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
extension DeviceViewModels {
|
|
|
|
|
|
|
|
func fbloadFuncation() {
|
|
|
|
// 默认功能列表
|
|
|
|
let section1: [FunctionTypeFireBoltt] = [.findPhone, .remoteCamera]
|
|
|
|
var section2: [FunctionTypeFireBoltt] = [.callRemind, .messageRemind, .notice]
|
|
|
|
// var section3: [FunctionTypeFireBoltt] = [.unBinding]
|
|
|
|
var section3: [FunctionTypeFireBoltt] = []
|
|
|
|
// 功能适配
|
|
|
|
if let adapterInfo = UserDefaultsManagerFrieBoltt.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: [[FunctionTypeFireBoltt]] = [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: UIImage(named: type.imgName()), 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.fbsendSyncDeviceData()
|
|
|
|
// 发送天气预报
|
|
|
|
loadWeather()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 获取当前开关状态
|
|
|
|
/// - Parameter type: 功能类型
|
|
|
|
private func getSwitchState(type: FunctionTypeFireBoltt) -> 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_FB.locationTipFB.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(APIManagerFireBoltt.getHeFengLiveWeather(lat: "\(lat)", lon: "\(lon)")).asObservable(),ProviderRequest(APIManagerFireBoltt.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
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|