Server code to fetch and toggle devices
This commit is contained in:
@@ -9,10 +9,24 @@
|
||||
import UIKit
|
||||
|
||||
class MainViewController: UIViewController, SwitchesViewControllerDelegate {
|
||||
private var _server: WemoServer
|
||||
private var _visualizationController: VisualizationViewController = VisualizationViewController()
|
||||
private var _switchesController: SwitchesViewController = SwitchesViewController()
|
||||
private var _headerView: HeaderView = HeaderView()
|
||||
|
||||
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)
|
||||
{
|
||||
let url = NSURL(string: "http://10.0.1.4:8000")
|
||||
_server = WemoServer(url!)
|
||||
|
||||
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder)
|
||||
{
|
||||
fatalError("unsupported")
|
||||
}
|
||||
|
||||
// MARK: Overrides
|
||||
|
||||
override func viewDidLoad()
|
||||
@@ -30,12 +44,7 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate {
|
||||
|
||||
self.view.addSubview(_headerView)
|
||||
|
||||
// DEBUG
|
||||
for _ in 0 ..< 10 {
|
||||
let device = WemoDevice()
|
||||
device.name = "beatmania IIDX"
|
||||
self.devices.append(device)
|
||||
}
|
||||
_updateConnectivityStatus(.Disconnected)
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews()
|
||||
@@ -78,6 +87,15 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate {
|
||||
override func viewDidAppear(animated: Bool)
|
||||
{
|
||||
_headerView.xionLogoView.beginAnimating()
|
||||
|
||||
_updateConnectivityStatus(.Connecting)
|
||||
_server.connect { (error: NSError?) -> Void in
|
||||
if (error == nil) {
|
||||
self._reloadDevices()
|
||||
} else {
|
||||
self._updateConnectivityStatus(.Error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidDisappear(animated: Bool)
|
||||
@@ -106,6 +124,10 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate {
|
||||
func switchesViewControllerDidToggleDevices(controller: SwitchesViewController, devices: [WemoDevice])
|
||||
{
|
||||
_updateVisualization(true)
|
||||
|
||||
for device in devices {
|
||||
_server.toggleDevice(device, state: device.state, completion: { (error: NSError?) -> Void in })
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Internal
|
||||
@@ -124,4 +146,26 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate {
|
||||
_visualizationController.setPercentActivated(percentageActivated, animated: animated)
|
||||
}
|
||||
}
|
||||
|
||||
internal func _updateConnectivityStatus(status: ConnectionStatus)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue()) { () -> Void in
|
||||
self._headerView.connectionStatusView.connectivityStatus = status
|
||||
}
|
||||
}
|
||||
|
||||
internal func _reloadDevices()
|
||||
{
|
||||
_server.fetchDevices({ (devices: [WemoDevice], error: NSError?) -> Void in
|
||||
dispatch_async(dispatch_get_main_queue()) { () -> Void in
|
||||
if (error == nil) {
|
||||
self.devices = devices
|
||||
self._updateConnectivityStatus(.Connected)
|
||||
} else {
|
||||
self.devices = []
|
||||
self._updateConnectivityStatus(.Error)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,8 @@ class SwitchesViewController: UIViewController,
|
||||
_collectionView.registerClass(WemoDeviceCellView.self, forCellWithReuseIdentifier: deviceCellReuseID)
|
||||
_collectionView.registerClass(WemoActionCellView.self, forCellWithReuseIdentifier: actionCellReuseID)
|
||||
self.view.addSubview(_collectionView)
|
||||
|
||||
self.devices = []
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews()
|
||||
@@ -102,6 +104,7 @@ class SwitchesViewController: UIViewController,
|
||||
let reuseID = SwitchesViewController.collectionViewActionCellReuseIdentifier
|
||||
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseID, forIndexPath: indexPath) as! WemoActionCellView
|
||||
cell.textLabel.text = ActionCell(rawValue: indexPath.item)?.name().uppercaseString
|
||||
cell.enabled = (self.devices.count > 0)
|
||||
|
||||
return cell
|
||||
} else {
|
||||
@@ -136,8 +139,8 @@ class SwitchesViewController: UIViewController,
|
||||
{
|
||||
if (indexPath.item < ActionCell.count) {
|
||||
let tappedActionCell = ActionCell(rawValue: indexPath.item)
|
||||
|
||||
var currentDelay: NSTimeInterval = 0.0
|
||||
|
||||
for var i = ActionCell.count; i < collectionView.numberOfItemsInSection(indexPath.section); ++i {
|
||||
let cell = collectionView.cellForItemAtIndexPath(NSIndexPath(forItem: i, inSection: indexPath.section)) as! WemoDeviceCellView
|
||||
|
||||
@@ -164,4 +167,22 @@ class SwitchesViewController: UIViewController,
|
||||
self.delegate?.switchesViewControllerDidToggleDevices(self, devices: [device])
|
||||
}
|
||||
}
|
||||
|
||||
func collectionView(collectionView: UICollectionView, shouldHighlightItemAtIndexPath indexPath: NSIndexPath) -> Bool
|
||||
{
|
||||
if (indexPath.item < ActionCell.count) {
|
||||
return (self.devices.count > 0)
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool
|
||||
{
|
||||
if (indexPath.item < ActionCell.count) {
|
||||
return (self.devices.count > 0)
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
134
XIONControlPanel/Controllers/WemoServer.swift
Normal file
134
XIONControlPanel/Controllers/WemoServer.swift
Normal file
@@ -0,0 +1,134 @@
|
||||
//
|
||||
// WemoServer.swift
|
||||
// XIONControlPanel
|
||||
//
|
||||
// Created by Charles Magahern on 12/31/15.
|
||||
// Copyright © 2015 XION. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum ConnectionStatus {
|
||||
case Disconnected
|
||||
case Connecting
|
||||
case Connected
|
||||
case Error
|
||||
}
|
||||
|
||||
class WemoServer {
|
||||
private(set) var baseURL: NSURL
|
||||
private(set) var connected: Bool = false
|
||||
|
||||
private var _urlSession: NSURLSession
|
||||
private var _errorStream: StandardErrorOutputStream = StandardErrorOutputStream()
|
||||
|
||||
init(_ url: NSURL)
|
||||
{
|
||||
self.baseURL = url
|
||||
|
||||
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
|
||||
_urlSession = NSURLSession(configuration: config)
|
||||
}
|
||||
|
||||
func connect(completion: (NSError?) -> Void)
|
||||
{
|
||||
if (!self.connected) {
|
||||
let url = self.baseURL.URLByAppendingPathComponent("api/environment")
|
||||
let request = NSMutableURLRequest(URL: url)
|
||||
request.HTTPMethod = "POST"
|
||||
|
||||
let task = _urlSession.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
|
||||
var clientError: NSError? = nil
|
||||
|
||||
if (error != nil) {
|
||||
clientError = NSError.xionError(.ConnectionError, underlying: error!)
|
||||
self._logError("Error connecting to server", error: clientError!)
|
||||
} else {
|
||||
self.connected = true
|
||||
}
|
||||
|
||||
completion(clientError)
|
||||
}
|
||||
task.resume()
|
||||
} else {
|
||||
completion(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func disconnect(completion: (NSError?) -> Void)
|
||||
{
|
||||
self.connected = false
|
||||
completion(nil)
|
||||
}
|
||||
|
||||
func fetchDevices(completion: ([WemoDevice], NSError?) -> Void)
|
||||
{
|
||||
if (self.connected) {
|
||||
let url = self.baseURL.URLByAppendingPathComponent("api/environment")
|
||||
let task = _urlSession.dataTaskWithURL(url) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
|
||||
var devices: [WemoDevice] = []
|
||||
var clientError: NSError? = nil
|
||||
|
||||
if (data != nil) {
|
||||
devices = self._parseDevices(data!)
|
||||
} else {
|
||||
clientError = NSError.xionError(.ConnectionError, underlying: error)
|
||||
self._logError("Error fetching devices", error: clientError!)
|
||||
}
|
||||
|
||||
completion(devices, clientError)
|
||||
}
|
||||
task.resume()
|
||||
} else {
|
||||
let err = NSError.xionError(.ConnectionError)
|
||||
completion([], err)
|
||||
}
|
||||
}
|
||||
|
||||
func toggleDevice(device: WemoDevice, state: WemoDevice.State, completion: (NSError?) -> Void)
|
||||
{
|
||||
if (self.connected) {
|
||||
let stateArg = (state == .On ? "on" : "off")
|
||||
let url = self.baseURL.URLByAppendingPathComponent("api/device/\(device.name)").URLByAppendingRequestParameters(["state" : stateArg])
|
||||
let request = NSMutableURLRequest(URL: url!)
|
||||
request.HTTPMethod = "POST"
|
||||
|
||||
let task = _urlSession.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
|
||||
var clientError: NSError? = nil
|
||||
|
||||
if (error != nil) {
|
||||
clientError = NSError.xionError(.ConnectionError, underlying: error)
|
||||
}
|
||||
|
||||
completion(clientError)
|
||||
}
|
||||
task.resume()
|
||||
} else {
|
||||
let err = NSError.xionError(.ConnectionError)
|
||||
completion(err)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal func _logError(description: String, error: NSError)
|
||||
{
|
||||
print("ERROR: \(description) \(error)", toStream: &_errorStream)
|
||||
}
|
||||
|
||||
internal func _parseDevices(data: NSData) -> [WemoDevice]
|
||||
{
|
||||
var devices: [WemoDevice] = []
|
||||
|
||||
if let responseDict = (try? NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions()) as? NSDictionary) {
|
||||
for responseObj in (responseDict?.allValues)! {
|
||||
if let responseDict = responseObj as? NSDictionary {
|
||||
let device = WemoDevice(responseDict)
|
||||
devices.append(device)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return devices
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user