111 lines
3.1 KiB
Swift
111 lines
3.1 KiB
Swift
//
|
|
// ServerMultiplex.swift
|
|
// XIONControlPanel
|
|
//
|
|
// Created by James Magahern on 3/14/20.
|
|
// Copyright © 2020 XION. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
protocol ServerMultiplexDelegate
|
|
{
|
|
func serverMultiplex(_ multiplex: ServerMultiplex, didAddDevices devices: [AnyDevice])
|
|
func serverMultiplex(_ multiplex: ServerMultiplex, devicesStateChanged devices: [AnyDevice])
|
|
func serverMultiplex(_ multiplex: ServerMultiplex, didEncounterError error: Error)
|
|
}
|
|
|
|
enum ServerMultiplexError : Error
|
|
{
|
|
case unknownDevice
|
|
}
|
|
|
|
class ServerMultiplex
|
|
{
|
|
public var delegate: ServerMultiplexDelegate?
|
|
public private(set) var devices = Set<AnyDevice>()
|
|
|
|
private var servers: [Server] = []
|
|
public var numServers: Int { return servers.count }
|
|
|
|
public func addServer(_ server: Server)
|
|
{
|
|
servers.append(server)
|
|
}
|
|
|
|
public func numberOfConnectedServers() -> Int
|
|
{
|
|
return servers.filter { $0.connected == true }.count
|
|
}
|
|
|
|
public func toggleDeviceState(_ device: AnyDevice, state: DeviceState, completion: @escaping (Error?) -> Void)
|
|
{
|
|
if let server = (servers.first { $0.responsibleForDevice(device) }) {
|
|
server.toggleDevice(device, state: state, completion: completion)
|
|
|
|
// Update internal state
|
|
if let index = devices.firstIndex(of: device) {
|
|
devices[index].state = state
|
|
}
|
|
} else {
|
|
completion(ServerMultiplexError.unknownDevice)
|
|
}
|
|
}
|
|
|
|
public func refreshDevices()
|
|
{
|
|
self.servers.forEach { (server: Server) in
|
|
server.fetchDevices { (result: Result<[AnyDevice], Error>) in
|
|
self.handleServerFetchResult(result)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extension ServerMultiplex
|
|
{
|
|
private func handleServerFetchResult(_ result: Result<[AnyDevice], Error>)
|
|
{
|
|
switch result {
|
|
case .success(let devices):
|
|
handleDevicesChanged(devices)
|
|
case .failure(let error):
|
|
handleError(error)
|
|
}
|
|
}
|
|
|
|
private func handleDevicesChanged(_ devicesChanged: [AnyDevice])
|
|
{
|
|
let newDevicesSet = Set<AnyDevice>(devicesChanged)
|
|
let additions = newDevicesSet.subtracting(self.devices)
|
|
let changed = newDevicesSet.filter { (device: AnyDevice) in
|
|
if let existing = (devices.first { $0.hashValue == device.hashValue }) {
|
|
return existing.state != device.state
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
self.devices = self.devices.union(newDevicesSet)
|
|
|
|
if additions.count > 0 {
|
|
DispatchQueue.main.async {
|
|
self.delegate?.serverMultiplex(self, didAddDevices: Array(additions))
|
|
}
|
|
}
|
|
|
|
if changed.count > 0 {
|
|
DispatchQueue.main.async {
|
|
self.delegate?.serverMultiplex(self, devicesStateChanged: Array(changed))
|
|
}
|
|
}
|
|
}
|
|
|
|
private func handleError(_ error: Error)
|
|
{
|
|
DispatchQueue.main.async {
|
|
self.delegate?.serverMultiplex(self, didEncounterError: error)
|
|
}
|
|
}
|
|
}
|