Automatically update devices on an interval
This commit is contained in:
@@ -13,6 +13,7 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate {
|
|||||||
private var _visualizationController: VisualizationViewController = VisualizationViewController()
|
private var _visualizationController: VisualizationViewController = VisualizationViewController()
|
||||||
private var _switchesController: SwitchesViewController = SwitchesViewController()
|
private var _switchesController: SwitchesViewController = SwitchesViewController()
|
||||||
private var _headerView: HeaderView = HeaderView()
|
private var _headerView: HeaderView = HeaderView()
|
||||||
|
private var _updateDevices: Bool = false
|
||||||
|
|
||||||
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)
|
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)
|
||||||
{
|
{
|
||||||
@@ -92,6 +93,7 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate {
|
|||||||
_server.connect { (error: NSError?) -> Void in
|
_server.connect { (error: NSError?) -> Void in
|
||||||
if (error == nil) {
|
if (error == nil) {
|
||||||
self._reloadDevices()
|
self._reloadDevices()
|
||||||
|
self._startUpdatingDevices()
|
||||||
} else {
|
} else {
|
||||||
self._updateConnectivityStatus(.Error)
|
self._updateConnectivityStatus(.Error)
|
||||||
}
|
}
|
||||||
@@ -164,8 +166,27 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate {
|
|||||||
} else {
|
} else {
|
||||||
self.devices = []
|
self.devices = []
|
||||||
self._updateConnectivityStatus(.Error)
|
self._updateConnectivityStatus(.Error)
|
||||||
|
self._stopUpdatingDevices()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal func _startUpdatingDevices()
|
||||||
|
{
|
||||||
|
_updateDevices = true
|
||||||
|
|
||||||
|
let interval = dispatch_time(DISPATCH_TIME_NOW, Int64(10 * Double(NSEC_PER_SEC)))
|
||||||
|
dispatch_after(interval, dispatch_get_main_queue()) { () -> Void in
|
||||||
|
if (self._updateDevices) {
|
||||||
|
self._reloadDevices()
|
||||||
|
self._startUpdatingDevices()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal func _stopUpdatingDevices()
|
||||||
|
{
|
||||||
|
_updateDevices = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ class SwitchesViewController: UIViewController,
|
|||||||
weak var delegate: SwitchesViewControllerDelegate?
|
weak var delegate: SwitchesViewControllerDelegate?
|
||||||
private var _collectionView: UICollectionView = UICollectionView(frame: CGRectZero,
|
private var _collectionView: UICollectionView = UICollectionView(frame: CGRectZero,
|
||||||
collectionViewLayout: UICollectionViewFlowLayout())
|
collectionViewLayout: UICollectionViewFlowLayout())
|
||||||
|
private var _currentDevicesHash: Int = 0
|
||||||
|
|
||||||
static private let collectionViewDeviceSwitchCellReuseIdentifier = "DeviceSwitchReuseID"
|
static private let collectionViewDeviceSwitchCellReuseIdentifier = "DeviceSwitchReuseID"
|
||||||
static private let collectionViewActionCellReuseIdentifier = "ActionCellReuseID"
|
static private let collectionViewActionCellReuseIdentifier = "ActionCellReuseID"
|
||||||
@@ -87,7 +88,69 @@ class SwitchesViewController: UIViewController,
|
|||||||
{
|
{
|
||||||
didSet
|
didSet
|
||||||
{
|
{
|
||||||
_collectionView.reloadData()
|
let hash = self.devices.reduce(0, combine: {$0 ^ $1.hashValue})
|
||||||
|
if (hash != _currentDevicesHash) {
|
||||||
|
// sort by name
|
||||||
|
self.devices.sortInPlace({ (d1: WemoDevice, d2: WemoDevice) -> Bool in
|
||||||
|
return (d1.name.compare(d2.name) == .OrderedAscending)
|
||||||
|
})
|
||||||
|
|
||||||
|
// replace "Dance Dance Revolution" names with "DDR" to save space
|
||||||
|
for device in self.devices {
|
||||||
|
if let range = device.name.rangeOfString("Dance Dance Revolution") {
|
||||||
|
device.name.replaceRange(range, with: "DDR")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let previousSet = NSOrderedSet(array: oldValue)
|
||||||
|
let newSet = NSOrderedSet(array: self.devices)
|
||||||
|
var insertedIndexPaths: [NSIndexPath] = []
|
||||||
|
var updatedIndexPaths: [NSIndexPath] = []
|
||||||
|
var deletedIndexPaths: [NSIndexPath] = []
|
||||||
|
|
||||||
|
// if we have devices now and we didn't before, or vice versa,
|
||||||
|
// we need to update the action cells
|
||||||
|
if ((oldValue.count == 0 && self.devices.count != 0) || (self.devices.count == 0 && oldValue.count != 0)) {
|
||||||
|
for var actionCellIdx = 0; actionCellIdx < ActionCell.count; ++actionCellIdx {
|
||||||
|
let actionCellIndexPath = NSIndexPath(forItem: actionCellIdx, inSection: 0)
|
||||||
|
updatedIndexPaths.append(actionCellIndexPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// find deletes and updates
|
||||||
|
for (idx, device) in previousSet.enumerate() {
|
||||||
|
let itemIndex = idx + ActionCell.count
|
||||||
|
let curIndexPath = NSIndexPath(forItem: itemIndex, inSection: 0)
|
||||||
|
|
||||||
|
if (!newSet.containsObject(device)) {
|
||||||
|
deletedIndexPaths.append(curIndexPath)
|
||||||
|
} else if (idx < newSet.count) {
|
||||||
|
let deviceInNewSet = newSet.objectAtIndex(idx) as! WemoDevice
|
||||||
|
if (deviceInNewSet != (device as! WemoDevice)) {
|
||||||
|
updatedIndexPaths.append(curIndexPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// find insertions
|
||||||
|
for (idx, device) in newSet.enumerate() {
|
||||||
|
if (!previousSet.containsObject(device)) {
|
||||||
|
let itemIndex = idx + ActionCell.count
|
||||||
|
let insertedIndexPath = NSIndexPath(forItem: itemIndex, inSection: 0)
|
||||||
|
insertedIndexPaths.append(insertedIndexPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UIView.performWithoutAnimation { () -> Void in
|
||||||
|
self._collectionView.performBatchUpdates({ () -> Void in
|
||||||
|
self._collectionView.deleteItemsAtIndexPaths(deletedIndexPaths)
|
||||||
|
self._collectionView.reloadItemsAtIndexPaths(updatedIndexPaths)
|
||||||
|
self._collectionView.insertItemsAtIndexPaths(insertedIndexPaths)
|
||||||
|
}, completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
_currentDevicesHash = hash
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,6 +177,7 @@ class SwitchesViewController: UIViewController,
|
|||||||
let deviceIdx = indexPath.item - ActionCell.count
|
let deviceIdx = indexPath.item - ActionCell.count
|
||||||
let device = self.devices[deviceIdx]
|
let device = self.devices[deviceIdx]
|
||||||
cell.device = device
|
cell.device = device
|
||||||
|
cell.toggled = (device.state == .On)
|
||||||
cell.ordinal = deviceIdx + 1
|
cell.ordinal = deviceIdx + 1
|
||||||
|
|
||||||
return cell
|
return cell
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class WemoDevice {
|
class WemoDevice: Hashable {
|
||||||
enum State {
|
enum State {
|
||||||
case Off
|
case Off
|
||||||
case On
|
case On
|
||||||
@@ -57,4 +57,22 @@ class WemoDevice {
|
|||||||
self.serial = String(serial)
|
self.serial = String(serial)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hashValue: Int
|
||||||
|
{
|
||||||
|
var hash: Int = 0x0
|
||||||
|
hash ^= self.name.hash
|
||||||
|
hash ^= self.host.hash
|
||||||
|
hash ^= self.model.hash
|
||||||
|
hash ^= self.state.hashValue
|
||||||
|
hash ^= self.type.hashValue
|
||||||
|
hash ^= self.serial.hashValue
|
||||||
|
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ==(lhs: WemoDevice, rhs: WemoDevice) -> Bool
|
||||||
|
{
|
||||||
|
return (lhs.serial == rhs.serial)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ public class WemoDeviceCellView: WemoCellView {
|
|||||||
{
|
{
|
||||||
_device = device
|
_device = device
|
||||||
_nameLabel.text = _device?.name.uppercaseString
|
_nameLabel.text = _device?.name.uppercaseString
|
||||||
|
self.setNeedsLayout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,6 +147,7 @@ public class WemoDeviceCellView: WemoCellView {
|
|||||||
{
|
{
|
||||||
_ordinal = ordinal
|
_ordinal = ordinal
|
||||||
_ordinalLabel.text = String(format: "%.2d", _ordinal)
|
_ordinalLabel.text = String(format: "%.2d", _ordinal)
|
||||||
|
self.setNeedsLayout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user