// // HomeViewController.swift // Twear // // Created by yangbin on 2021/11/16. // import UIKit import SwiftDate import Charts import CoreBluetooth import Alamofire import HandyJSON import MJRefresh class HomeViewController: UIViewController, CLLocationManagerDelegate { @IBOutlet weak var collectionView: UICollectionView! @IBOutlet weak var collectViewHeight: NSLayoutConstraint! @IBOutlet weak var scrollView: UIScrollView! @IBOutlet weak var bindButton: UIButton! @IBOutlet weak var bindLabel: UILabel! @IBOutlet weak var stepProgressView: StepCircleView! @IBOutlet weak var stepsGoalLabel: UILabel! @IBOutlet weak var stepDateLabel: UILabel! @IBOutlet weak var stepsDistanceLabel: UILabel! @IBOutlet weak var stepsCalorieLabel: UILabel! @IBOutlet weak var topView: UIView! @IBOutlet weak var weatherImageView: UIImageView! @IBOutlet weak var weatherDateLabel: UILabel! @IBOutlet weak var weatherLabel: UILabel! private var weatherArray: [WeatherModel] = [] var collectArray: [String] = CurDevice.homePage var scanView: ScanView? = nil var queryArray: [String] = CurDevice.queryArray let locationManager = CLLocationManager() lazy private var qWeather: AllWeatherInquieirs = { let weather: AllWeatherInquieirs = AllWeatherInquieirs.sharedInstance()! weather.languageType = .ZH return weather }() override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.navigationController?.setNavigationBarHidden(true, animated: true) updateConnectView(DeviceIsConnected) updateStepView() } override func viewDidLoad() { super.viewDidLoad() // print(RealmTools.queryObjects(MotionModel.self)) // print(MotionModel.getData(0)) testDate() let header = MJRefreshNormalHeader(refreshingBlock: { [weak self] in self?.getNewestData() }) // str0 = str0.replacingOccurrences(of: "HC:", with: "").uppercased() header.setTitle(LocString("正在同步数据中..."), for: .refreshing) header.lastUpdatedTimeLabel?.isHidden = true scrollView.mj_header = header if IsSwitchLanguage { scrollView.mj_header?.isHidden = false IsSwitchLanguage = false } else { scrollView.mj_header?.isHidden = true } configureCollectionView() BluetoothManager.shared.registerDelegate(self) BluetoothManager.shared.registerSyncDelegate(self) // updateStepView() if #available(iOS 14.0, *) { locationManager.delegate = self } SystemAuth.authLocation {[weak self] isAuth, isFirst in if isAuth || isFirst { self?.updateWeatherView(true) } } } func testDate() { // let testDate = DateInRegion(year: 2022, month: 1, day: 13, hour: 0, minute: 0, second: 0) if IsTest { if let i = collectArray.firstIndex(of: "BloodPressure") { collectArray.remove(at: i) } if let i = collectArray.firstIndex(of: "BloodOxygen") { collectArray.remove(at: i) } } } @available(iOS 14.0, *) func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { switch manager.authorizationStatus { case .notDetermined: if manager.authorizationStatus == .authorizedAlways || manager.authorizationStatus == .authorizedWhenInUse { updateWeatherView(true) } else { } case .authorizedAlways, .authorizedWhenInUse: updateWeatherView(true) default: break } } private func queryLocation() { qWeather.weather(withInquireType: .GEO_CITY_LOOKUP) {[weak self] responseObject in if let geo = responseObject as? GeoBaseClass { if geo.location.count > 0 { print(geo.location[0]) self?.qWeather.city = geo.location[0].cid self?.queryWeather(geo.location[0].adm2) } } } faileureForError: { _ in } } private func queryWeather(_ city: String) { qWeather.weather(withInquireType: .WEATHER_3D, withSuccess: {[weak self] responseObject in if let weather = responseObject as? WeatherBaseClass, let daily = weather.daily { let weatherArray = WeatherModel.dailyToWeather(daily, city: city) self?.updateWeather(weatherArray) } }, faileureForError: { err in }) } private func updateWeather(_ array: [WeatherModel]) { if array.count == 3 { let weatherArray = array let nowDate = DateInRegion().date weatherArray[0].date = nowDate weatherArray[1].date = nowDate + 1.days weatherArray[2].date = nowDate + 2.days AdminHelper.shared.savaWeather(weatherArray) updateWeatherView() } } private func updateWeatherView(_ isQuery: Bool = false) { let date = DateInRegion().date weatherDateLabel.text = date.toString(.custom("yyyy/MM/dd")) + " " + date.weekText let weatherArray = AdminHelper.shared.loadLocalWeatherData() if weatherArray.count > 0, let weather = weatherArray.first { weatherLabel.text = "\(LocString(weather.text)) \(weather.lowest)℃-\(weather.highest)℃" weatherImageView.image = UIImage(named: weather.icon) if isQuery { if let lastDate = weather.date { if (date - lastDate).in(.hour) ?? 9 > 8 { queryLocation() } } } } else { queryLocation() weatherLabel.text = LocString("无法获取当前天气") } } private func updateConnectView(_ isConnected: Bool) { if CurDevice.uuid == "" { bindButton.setImage(UIImage(named: "bind_device"), for: .normal) bindLabel.text = LocString("添加设备") } else { bindButton.setImage(UIImage(named: "device_connected"), for: .normal) bindLabel.text = isConnected ? LocString("已连接") : LocString("已断开") } } private func updateStepView() { let step = StepModel.getRecentSteps() let goal = UserInfo.stepsGoal stepProgressView.stepLabel.text = "\(step.number)" stepDateLabel.text = step.date?.toString(.custom("yyyy/MM/dd")) stepProgressView.value = min(step.number*100/goal, 100) // stepsGoalLabel.text = "/\(StepsGoal)步/\(String(format:"%.2f", step.calorie))千卡/\(String(format:"%.2f", step.distance))公里" stepsGoalLabel.toUnitMode1(title: LocString("目标步数"), text: "\(goal)", unit: LocString("步"), font: RegularFont(13), unitFont: LightFont(11)) stepsDistanceLabel.toUnitMode1(title: LocString("热量"), text: "\(String(format:"%.2f", step.calorie))", unit: LocString("千卡"), font: RegularFont(13), unitFont: LightFont(11)) stepsCalorieLabel.toUnitMode1(title: LocString("距离"), text: "\(String(format:"%.2f", step.distance))", unit: LocString("公里"), font: RegularFont(13), unitFont: LightFont(11)) // print(stepDateLabel.font) } @IBAction func bindDevice(_ sender: UIButton) { if CurDevice.uuid.count > 0 { return } scanView = ScanView() scanView?.show() startScan() scanView?.clickClosure = {[weak self] index, device in if index == 2 { self?.scanView = nil BluetoothManager.shared.stopScanning() } else if index == 3 { //配对失败 重试 self?.startScan() } else if index == 4 { //重新搜索 self?.startScan() } if let per = device as? CBPeripheral { BluetoothManager.shared.connect(peripheral: per) self?.scanView?.updateUI(.Pairing) } if GCDTimer.shared.isExistTimer(WithTimerName: "StartScan") { GCDTimer.shared.cancleTimer(WithTimerName: "StartScan") } if GCDTimer.shared.isExistTimer(WithTimerName: "DevicePairing") { GCDTimer.shared.cancleTimer(WithTimerName: "DevicePairing") } GCDTimer.shared.scheduledDispatchTimerNotNow(WithTimerName: "DevicePairing", timeInterval: 12, queue: .main, repeats: false) { self?.pairingFail() } } } func setWeatherData() { if weatherArray.count == 0 { weatherArray = AdminHelper.shared.loadLocalWeatherData() } BluetoothManager.shared.setWeather(weatherArray) } private func startScan() { BluetoothManager.shared.startScanning() GCDTimer.shared.scheduledDispatchTimerNotNow(WithTimerName: "StartScan", timeInterval: 10, queue: .main, repeats: false) { BluetoothManager.shared.stopScanning() self.scanView?.updateUI(.ScanComplete) } } @IBAction func share(_ sender: Any) { let shareView = ShareView(getShareImage()) // shareView.shareImage = getShareImage() shareView.show() } func getShareImage() -> UIImage? { scrollView.removeFromSuperview() let image = scrollView.captureLongImage view.addSubview(scrollView) scrollView.snp.makeConstraints { (make) in make.top.equalTo(topView.snp.bottom) make.left.bottom.right.equalToSuperview() } return image } @IBAction func sortPage(_ sender: Any) { let vc = UIStoryboard.loadViewControllerIdentifier(storyboardName: "Home", identifier: "HomePageSortVC") as! HomePageSortVC vc.ary1 = collectArray vc.sortClosure = {[weak self] array in self?.collectArray = array self?.collectViewHeight.constant = CGFloat(array.count/2 + array.count%2)*200 + 25 self?.collectionView.reloadData() } navigationController?.pushViewController(vc, animated: true) } @IBAction func clickStepView(_ sender: Any) { let vc = UIStoryboard.loadViewControllerIdentifier(storyboardName: "Home", identifier: "StepViewController") as! StepViewController navigationController?.pushViewController(vc, animated: true) } deinit { BluetoothManager.shared.unRegisterSyncDelegate(self) BluetoothManager.shared.unRegisterDelegate(self) print("deinit\(NSStringFromClass(type(of: self)))!!!!!!!") } } extension HomeViewController: BluetoothManagerDelegate { func centralManagerDidUpdateState(_ state: Int) { switch state { case 4: bindLabel.text = LocString("已断开") case 5: if CurDevice.uuid != "" { bindLabel.text = LocString("连接中...") } default: print(" ") } } func didDisconnected() { DeviceIsConnected = false updateConnectView(false) // bindLabel.text = LocString("已断开") } func didDiscover(devices: [ScanDevice]) { if scanView != nil { scanView?.deviceArray = devices } } func didConnect(_ peripheral: CBPeripheral) { updateConnectView(true) collectArray = CurDevice.homePage testDate() collectViewHeight.constant = CGFloat(collectArray.count/2 + collectArray.count%2)*200 + 25 if GCDTimer.shared.isExistTimer(WithTimerName: "StartScan") { GCDTimer.shared.cancleTimer(WithTimerName: "StartScan") } if GCDTimer.shared.isExistTimer(WithTimerName: "DevicePairing") { GCDTimer.shared.cancleTimer(WithTimerName: "DevicePairing") } collectionView.reloadData() scanView?.updateUI(.PairSuccess) } private func pairingFail() { if !DeviceIsConnected { BluetoothManager.shared.pairFail() scanView?.updateUI(.PairFail) } } } extension HomeViewController: UICollectionViewDataSource,UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let cell = collectionView.cellForItem(at: indexPath) var cellId: String = "" switch cell { case is BloodPressureCell: cellId = "BloodPressureVC" case is BloodOxygenCell: cellId = "BloodOxygenVC" case is HeartRateCell: cellId = "HeartRateVC" case is SleepCell: cellId = "SleepViewController" case is TrainCell: cellId = "TrainViewController" case is MotionCell: cellId = "MotionRecordVC" // case is WomenHealthCell: // cellId = "WomenHealthVC" default: break } if cell is WomenHealthCell { if UserInfo.menstrual.days == 0 { let vc = UIStoryboard.loadViewControllerIdentifier(storyboardName: "Home", identifier: "WomenHealthVC") as! WomenHealthVC vc.isFirst = true vc.setClosure = {[weak self] in if let index = self?.collectArray.firstIndex(of: "WomenHealth") { self?.collectionView.reloadItems(at: [IndexPath(row: index, section: 0)]) } } navigationController?.pushViewController(vc, animated: true) cellId = "MenstrualCalendarVC" } else { let vc = UIStoryboard.loadViewControllerIdentifier(storyboardName: "Home", identifier: "MenstrualCalendarVC") as! MenstrualCalendarVC vc.setClosure = {[weak self] in if let index = self?.collectArray.firstIndex(of: "WomenHealth") { self?.collectionView.reloadItems(at: [IndexPath(row: index, section: 0)]) } } navigationController?.pushViewController(vc, animated: true) } } else { let vc = UIStoryboard.loadViewControllerIdentifier(storyboardName: "Home", identifier: cellId) navigationController?.pushViewController(vc, animated: true) } } private func configureCollectionView(){ collectViewHeight.constant = CGFloat(collectArray.count/2 + collectArray.count%2)*200 + 25 let flowLayout = UICollectionViewFlowLayout() flowLayout.scrollDirection = .vertical flowLayout.minimumLineSpacing = 10 flowLayout.minimumInteritemSpacing = 10 flowLayout.sectionInset = UIEdgeInsets(top: 10, left: 12.5, bottom: 15, right: 12.5) flowLayout.itemSize = CGSize(width: (SCREEN_WIDTH-35)/2, height: 190) collectionView.showsVerticalScrollIndicator = false collectionView.bounces = false collectionView.collectionViewLayout = flowLayout collectionView.register(UINib.init(nibName: "BloodPressureCell", bundle: .main), forCellWithReuseIdentifier: "BloodPressureCell") collectionView.register(UINib.init(nibName: "BloodOxygenCell", bundle: .main), forCellWithReuseIdentifier: "BloodOxygenCell") collectionView.register(UINib.init(nibName: "HeartRateCell", bundle: .main), forCellWithReuseIdentifier: "HeartRateCell") collectionView.register(UINib.init(nibName: "SleepCell", bundle: .main), forCellWithReuseIdentifier: "SleepCell") collectionView.register(UINib.init(nibName: "TrainCell", bundle: .main), forCellWithReuseIdentifier: "TrainCell") collectionView.register(UINib.init(nibName: "WomenHealthCell", bundle: .main), forCellWithReuseIdentifier: "WomenHealthCell") collectionView.register(UINib.init(nibName: "MotionCell", bundle: .main), forCellWithReuseIdentifier: "MotionCell") } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return collectArray.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { switch collectArray[indexPath.row] { case "BloodPressure": let cell: BloodPressureCell = collectionView.dequeueReusableCell(withReuseIdentifier: "BloodPressureCell", for: indexPath) as! BloodPressureCell cell.bpHistory = BloodPressureModel.getRecentData() return cell case "BloodOxygen": let cell: BloodOxygenCell = collectionView.dequeueReusableCell(withReuseIdentifier: "BloodOxygenCell", for: indexPath) as! BloodOxygenCell cell.boHistory = BloodOxygenModel.getRecentData() return cell case "HeartRate": let cell: HeartRateCell = collectionView.dequeueReusableCell(withReuseIdentifier: "HeartRateCell", for: indexPath) as! HeartRateCell cell.hrHistory = HeartRateModel.getRecentData() return cell case "Sleep": let cell: SleepCell = collectionView.dequeueReusableCell(withReuseIdentifier: "SleepCell", for: indexPath) as! SleepCell cell.sleep = SleepModel.getRecentData() return cell case "Train": let cell: TrainCell = collectionView.dequeueReusableCell(withReuseIdentifier: "TrainCell", for: indexPath) as! TrainCell // let t1 = TrainModel(type: .running, date: DateInRegion().date-100, length: 100, calorie: 200, mileage: 300, steps: 500) // let t2 = TrainModel(type: .steppers, date: DateInRegion().date-300.minutes, length: 66, calorie: 1000, mileage: 300, steps: 500) // let t3 = TrainModel(type: .steppers, date: DateInRegion().date+7.hours, length: 1000, calorie: 1000, mileage: 300, steps: 500) cell.trainHistory = TrainModel.getRecentData() return cell case "WomenHealth": let cell: WomenHealthCell = collectionView.dequeueReusableCell(withReuseIdentifier: "WomenHealthCell", for: indexPath) as! WomenHealthCell cell.menstrual = UserInfo.menstrual return cell case "Motion": let cell: MotionCell = collectionView.dequeueReusableCell(withReuseIdentifier: "MotionCell", for: indexPath) as! MotionCell cell.motion = MotionModel.getRecentData().last ?? MotionModel() return cell default: let cell: MotionCell = collectionView.dequeueReusableCell(withReuseIdentifier: "MotionCell", for: indexPath) as! MotionCell cell.motion = MotionModel.getRecentData().last ?? MotionModel() return cell } } } extension HomeViewController: BluetoothSyncDelegate { func didReceiveHeartRate() { if let index = collectArray.firstIndex(of: "HeartRate") { collectionView.reloadItems(at: [IndexPath(row: index, section: 0)]) } } func didReceiveBloodOxygen() { if let index = collectArray.firstIndex(of: "BloodOxygen") { collectionView.reloadItems(at: [IndexPath(row: index, section: 0)]) } } func didReceiveBloodPressure() { if let index = collectArray.firstIndex(of: "BloodPressure") { collectionView.reloadItems(at: [IndexPath(row: index, section: 0)]) } } func firstSync() { getNewestData() } func didReceiveStep() { updateStepView() } } extension HomeViewController { func getNewestData() { isFirstSync = true queryArray = CurDevice.queryArray print("开始同步数据 Home") BluetoothManager.shared.syncBug() syncStep(.today) } func syncStep(_ day: SyncDay) { if day == .yesterday { queryArray = CurDevice.queryArray } print("\(queryArray)---同步步数---\(day)") if queryArray.contains("Step"), let index = queryArray.firstIndex(of: "Step") { BluetoothManager.shared.getStepHistoryData(day: day) {[weak self] stepArray, error in self?.queryArray.remove(at: index) if error == nil { // print(stepArray) StepModel.addArray(stepArray) } self?.syncBloodOxygen(day) } } else { syncBloodOxygen(day) } } func syncBloodOxygen(_ day: SyncDay) { print("\(queryArray)---同步血氧---\(day)") if queryArray.contains("BloodOxygen"), let index = queryArray.firstIndex(of: "BloodOxygen") { BluetoothManager.shared.getBloodOxygenHistoryData(day: day) {[weak self] boArray, error in self?.queryArray.remove(at: index) if error == nil { BloodOxygenModel.addArray(boArray) } self?.syncBloodPressure(day) } } else { syncBloodPressure(day) } } func syncBloodPressure(_ day: SyncDay) { print("\(queryArray)---同步血压---\(day)") if queryArray.contains("BloodPressure"), let index = queryArray.firstIndex(of: "BloodPressure") { BluetoothManager.shared.getBloodPressureHistoryData(day: day) {[weak self] bpArray, error in self?.queryArray.remove(at: index) if error == nil { BloodPressureModel.addArray(bpArray) } self?.syncHeartRate(day) } } else { syncHeartRate(day) } } func syncHeartRate(_ day: SyncDay) { print("\(queryArray)---同步心率---\(day)") if queryArray.contains("HeartRate"), let index = queryArray.firstIndex(of: "HeartRate") { BluetoothManager.shared.getHeartRateHistoryData(day: day) {[weak self] hrArray, error in self?.queryArray.remove(at: index) if error == nil { HeartRateModel.addArray(hrArray) } self?.syncSleep(day) } } else { syncSleep(day) } } func syncSleep(_ day: SyncDay) { print("\(queryArray)---同步睡眠---\(day)") if queryArray.contains("Sleep"), let index = queryArray.firstIndex(of: "Sleep") { BluetoothManager.shared.getSleepHistoryData(day: day) {[weak self] sleepArray, error in self?.queryArray.remove(at: index) if error == nil { SleepModel.addArray(sleepArray) } self?.syncTrain(day) } } else { syncTrain(day) } } func syncTrain(_ day: SyncDay) { print("\(queryArray)---同步训练---\(day)") if queryArray.contains("Train"), let index = queryArray.firstIndex(of: "Train") { BluetoothManager.shared.getTrainHistoryData(day: day) {[weak self] train, error in if error == nil || error == 2000 || error == -1001 { self?.queryArray.remove(at: index) if day == .today { self?.syncStep(.yesterday) } else { self?.getSettingData() } } } } else { if day == .today { syncStep(.yesterday) } else { getSettingData() } } } func getSettingData() { print("\(queryArray)---同步设置---") if queryArray.contains("Setting"), let index = queryArray.firstIndex(of: "Setting") { BluetoothManager.shared.getSettingData {[weak self] error in self?.queryArray.remove(at: index) // isFirstSync = false self?.syncFinish() } } else { syncFinish() } } func syncFinish() { print("\(queryArray)---同步完成!!!---") collectionView.reloadData() queryArray = CurDevice.queryArray updateStepView() setWeatherData() isFirstSync = false scrollView.mj_header?.endRefreshing() scrollView.mj_header?.isHidden = false } func syncBug() { // if !isFirstSync { syncFinish() // } } }