Files
POCloud-iOS/pocloud/Controller/DeviceDetailViewController.swift
2018-06-01 11:29:47 -05:00

215 lines
8.0 KiB
Swift

//
// DeviceDetailViewController.swift
// pocloud
//
// Created by Patrick McDonagh on 5/24/18.
// Copyright © 2018 patrickjmcd. All rights reserved.
//
import UIKit
import Alamofire
import PromiseKit
import RealmSwift
import SwiftyJSON
import SVProgressHUD
import FirebaseDatabase
class DeviceDetailViewController: UITableViewController {
let realm = try! Realm()
var ref: DatabaseReference!
let baseURL = (UIApplication.shared.delegate as! AppDelegate).baseURL
let user = (UIApplication.shared.delegate as! AppDelegate).user
var thisDevice : Device?
var deviceTypes : Results<DeviceType>?
var selectedChannel : Channel?
var channelLookup : [String : Int] = [:]
var values : [String : MeshifyValue] = [:]
var updatedChannelNames : [String] = [String]()
var changedChannelNames : [String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
ref = Database.database().reference()
let macAddress = String((thisDevice?.macAddress.replacingOccurrences(of: ":", with: "").uppercased().dropLast(4))!)
let deviceTypeName = (thisDevice?.parentDeviceType.first?.name)!
SVProgressHUD.show()
firstly {
loadData()
}.done { _ in
self.tableView.reloadData()
}.catch{ error in
print("Error in loadData: \(error)")
}
self.navigationItem.title = thisDevice?.vanityName
self.refreshControl = UIRefreshControl()
refreshControl?.attributedTitle = NSAttributedString(string: "Pull to refresh")
refreshControl?.addTarget(self, action: #selector(refresh), for: UIControlEvents.valueChanged)
// tableView.addSubview(refreshControl!)
firstly {
getChannels(deviceTypeId: thisDevice!.deviceTypeId, baseURL: baseURL, authToken: (user?.authToken)!)
}.then { _ in
getChannelValues(deviceId: self.thisDevice!.id, baseURL: self.baseURL, authToken: (self.user?.authToken)!)
}.done { (valueDict) in
self.values = valueDict
self.tableView.reloadData()
SVProgressHUD.dismiss()
if let dev = self.thisDevice {
for chanIndex in 0..<dev.values.count {
let chanName = dev.values[chanIndex].name
self.channelLookup[chanName] = chanIndex
}
}
self.getFirebaseDeviceValues(deviceMacAddress: macAddress, deviceTypeName: deviceTypeName)
}.catch { error in
print("Error fetching data in DeviceDetailViewController: \(error)")
}
}
override func viewWillDisappear(_ animated: Bool) {
Database.database().reference().removeAllObservers()
}
func getFirebaseDeviceValues(deviceMacAddress : String, deviceTypeName : String) {
// let getVals = Database.database().reference().child("devices")
// .child(deviceMacAddress)
// .child(deviceTypeName)
// .child("channels")
// .observe(.value) { snapshot in
// let snapValue = snapshot.value as! NSDictionary
//
//
// let chanVal = MeshifyValue()
// chanVal.name = (value["name"] as? String)!
// chanVal.timestamp = Int((value["timestamp"] as? String)!)!
// chanVal.value = (value["value"] as? String)!
// self.values[chanVal.name] = chanVal
// print("should set \(chanVal.value) as \(chanVal.name)")
// self.updatedChannelNames.append(chanVal.name)
// self.tableView.reloadData()
// }
// Database.database().reference().removeObserver(withHandle: getVals)
Database.database().reference().child("devices")
.child(deviceMacAddress)
.child(deviceTypeName)
.child("channels")
.observe(.childChanged) { snapshot in
let value = snapshot.value as! NSDictionary
let chanVal = MeshifyValue()
chanVal.name = (value["name"] as? String)!
chanVal.timestamp = Int((value["timestamp"] as? String)!)!
chanVal.value = (value["value"] as? String)!
let prevChanValue = self.values[chanVal.name]?.value
if prevChanValue != chanVal.value {
self.changedChannelNames.append(chanVal.name)
} else {
self.updatedChannelNames.append(chanVal.name)
}
self.values[chanVal.name] = chanVal
self.tableView.reloadData()
}
}
@objc func refresh() {
updatedChannelNames.removeAll()
changedChannelNames.removeAll()
SVProgressHUD.show()
firstly {
getChannels(deviceTypeId: thisDevice!.deviceTypeId, baseURL: baseURL, authToken: (user?.authToken)!)
}.then { _ in
getChannelValues(deviceId: self.thisDevice!.id, baseURL: self.baseURL, authToken: (self.user?.authToken)!)
}.done { _ in
self.tableView.reloadData()
SVProgressHUD.dismiss()
self.refreshControl?.endRefreshing()
}.catch { error in
print("Error fetching data in DeviceDetailViewController: \(error)")
}
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// return (thisDevice?.parentDeviceType.first?.channels.count)!
return values.count
}
// MARK: - Table View Delegate Method
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "deviceDetailCell", for: indexPath) as! DeviceDetailChannelCell
cell.channelNameLabel?.text = thisDevice?.parentDeviceType.first?.channels[indexPath.row].subTitle
let chanName = thisDevice?.parentDeviceType.first?.channels[indexPath.row].name
let chanVal = values[chanName!]
if let i = changedChannelNames.index(of: chanName!) {
changedChannelNames.remove(at: i)
cell.backgroundColor = UIColor.flatLime()
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
UIView.animate(withDuration: 1, animations: {
cell.backgroundColor = UIColor.white
})
}
}
if let i = updatedChannelNames.index(of: chanName!) {
updatedChannelNames.remove(at: i)
cell.backgroundColor = UIColor.flatYellow()
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
UIView.animate(withDuration: 1, animations: {
cell.backgroundColor = UIColor.white
})
}
}
cell.accessoryType = .disclosureIndicator
cell.channelValueLabel?.text = chanVal?.value
return cell
}
//MARK : - Table Cell Selected
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedChannel = thisDevice?.parentDeviceType.first?.channels[indexPath.row]
performSegue(withIdentifier: "goToChannelView", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToChannelView" {
let destinationVC = segue.destination as! ChannelDetailViewController
destinationVC.thisDevice = thisDevice!
destinationVC.thisChannel = selectedChannel!
}
}
func loadData() -> Promise<Void> {
return Promise { promise in
deviceTypes = realm.objects(DeviceType.self)
thisDevice = realm.objects(Device.self).filter("id == %d", thisDevice!.id).first!
promise.fulfill(())
}
}
}