Improve Home Assistant connection reliability
This commit is contained in:
@@ -13,7 +13,9 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate, Serv
|
||||
fileprivate var _serverMultiplex: ServerMultiplex = ServerMultiplex()
|
||||
fileprivate var _visualizationController: VisualizationViewController = VisualizationViewController()
|
||||
fileprivate var _headerView: HeaderView = HeaderView()
|
||||
fileprivate var _updateDevices: Bool = false
|
||||
fileprivate var _refreshTimer: Timer?
|
||||
fileprivate var _isApplicationActive: Bool = false
|
||||
fileprivate var _isViewVisible: Bool = false
|
||||
|
||||
fileprivate var _switchesController: SwitchesViewController = SwitchesViewController()
|
||||
fileprivate var _lightsController: SwitchesViewController = SwitchesViewController()
|
||||
@@ -58,6 +60,7 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate, Serv
|
||||
self.view.addSubview(_headerView)
|
||||
|
||||
_updateConnectivityStatus(.disconnected)
|
||||
_updateSizeClassPresentation()
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews()
|
||||
@@ -80,61 +83,68 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate, Serv
|
||||
|
||||
_headerView.frame = headerBounds
|
||||
|
||||
let visualizationFrame = CGRect(
|
||||
x: bodyBounds.origin.x,
|
||||
y: bodyBounds.origin.y,
|
||||
width: rint(0.5 * bodyBounds.size.width),
|
||||
height: bodyBounds.size.height / 1.5
|
||||
)
|
||||
_visualizationController.view.frame = visualizationFrame
|
||||
|
||||
let lightsControllerFrame = CGRect(
|
||||
x: bodyBounds.origin.x,
|
||||
y: visualizationFrame.maxY,
|
||||
width: visualizationFrame.width,
|
||||
height: bodyBounds.height - visualizationFrame.height
|
||||
)
|
||||
_lightsController.view.frame = lightsControllerFrame.insetBy(dx: 18.0, dy: 0.0)
|
||||
|
||||
var switchesOriginX: CGFloat = 0.0
|
||||
var switchesWidth: CGFloat = 0.0
|
||||
if (_visualizationShouldBeVisible()) {
|
||||
switchesOriginX = visualizationFrame.maxX
|
||||
switchesWidth = bodyBounds.size.width - visualizationFrame.size.width
|
||||
if _visualizationShouldBeVisible() {
|
||||
let visualizationFrame = CGRect(
|
||||
x: bodyBounds.origin.x,
|
||||
y: bodyBounds.origin.y,
|
||||
width: rint(0.5 * bodyBounds.size.width),
|
||||
height: bodyBounds.size.height / 1.5
|
||||
)
|
||||
_visualizationController.view.frame = visualizationFrame
|
||||
|
||||
let lightsControllerFrame = CGRect(
|
||||
x: bodyBounds.origin.x,
|
||||
y: visualizationFrame.maxY,
|
||||
width: visualizationFrame.width,
|
||||
height: bodyBounds.height - visualizationFrame.height
|
||||
)
|
||||
_lightsController.view.frame = lightsControllerFrame.insetBy(
|
||||
dx: 18.0,
|
||||
dy: 0.0
|
||||
)
|
||||
|
||||
_switchesController.view.frame = CGRect(
|
||||
x: visualizationFrame.maxX,
|
||||
y: bodyBounds.origin.y,
|
||||
width: bodyBounds.width - visualizationFrame.width,
|
||||
height: bodyBounds.height
|
||||
)
|
||||
} else {
|
||||
switchesOriginX = 0.0
|
||||
switchesWidth = bodyBounds.size.width
|
||||
let sectionSpacing: CGFloat = 8
|
||||
let switchesHeight = rint(bodyBounds.height * 0.68)
|
||||
|
||||
_visualizationController.view.frame = .zero
|
||||
_switchesController.view.frame = CGRect(
|
||||
x: bodyBounds.minX,
|
||||
y: bodyBounds.minY,
|
||||
width: bodyBounds.width,
|
||||
height: switchesHeight
|
||||
)
|
||||
_lightsController.view.frame = CGRect(
|
||||
x: bodyBounds.minX + sectionSpacing,
|
||||
y: bodyBounds.minY + switchesHeight + sectionSpacing,
|
||||
width: bodyBounds.width - (sectionSpacing * 2),
|
||||
height: bodyBounds.height - switchesHeight - sectionSpacing
|
||||
)
|
||||
}
|
||||
|
||||
let switchesControllerFrame = CGRect(
|
||||
x: switchesOriginX,
|
||||
y: bodyBounds.origin.y,
|
||||
width: switchesWidth,
|
||||
height: bodyBounds.size.height
|
||||
)
|
||||
_switchesController.view.frame = switchesControllerFrame
|
||||
|
||||
_updateSizeClassPresentation()
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool)
|
||||
{
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
UIApplication.shared.isIdleTimerDisabled = true
|
||||
|
||||
_headerView.xionLogoView.beginAnimating()
|
||||
|
||||
if _serverMultiplex.devices.count == 0 {
|
||||
// Do initial refresh
|
||||
_updateConnectivityStatus(.connecting)
|
||||
_serverMultiplex.refreshDevices()
|
||||
_startUpdatingDevices()
|
||||
}
|
||||
|
||||
_isViewVisible = true
|
||||
_updateActiveState()
|
||||
}
|
||||
|
||||
override func viewDidDisappear(_ animated: Bool)
|
||||
{
|
||||
super.viewDidDisappear(animated)
|
||||
UIApplication.shared.isIdleTimerDisabled = false
|
||||
|
||||
_isViewVisible = false
|
||||
_updateActiveState()
|
||||
}
|
||||
|
||||
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
|
||||
@@ -155,7 +165,21 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate, Serv
|
||||
_updateVisualization(true)
|
||||
|
||||
for device in devices {
|
||||
_serverMultiplex.toggleDeviceState(device, state: device.state, completion: { (error: Error?) -> Void in })
|
||||
_serverMultiplex.toggleDeviceState(
|
||||
device,
|
||||
state: device.state
|
||||
) { [weak self] error in
|
||||
guard let error else { return }
|
||||
|
||||
DispatchQueue.main.async {
|
||||
guard let self else { return }
|
||||
self._updateConnectivityStatus(.error)
|
||||
self._serverMultiplex.refreshDevices()
|
||||
|
||||
var stderr = StandardErrorOutputStream()
|
||||
print(error.localizedDescription, to: &stderr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,22 +224,41 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate, Serv
|
||||
}
|
||||
}
|
||||
|
||||
internal func _startUpdatingDevices()
|
||||
internal func applicationDidBecomeActive()
|
||||
{
|
||||
_updateDevices = true
|
||||
|
||||
let interval = DispatchTime.now() + Double(Int64(10 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
|
||||
DispatchQueue.main.asyncAfter(deadline: interval) { () -> Void in
|
||||
if (self._updateDevices) {
|
||||
self._serverMultiplex.refreshDevices()
|
||||
self._startUpdatingDevices()
|
||||
}
|
||||
}
|
||||
_isApplicationActive = true
|
||||
_updateActiveState()
|
||||
}
|
||||
|
||||
internal func _stopUpdatingDevices()
|
||||
|
||||
internal func applicationWillResignActive()
|
||||
{
|
||||
_updateDevices = false
|
||||
_isApplicationActive = false
|
||||
_updateActiveState()
|
||||
}
|
||||
|
||||
private func _updateActiveState()
|
||||
{
|
||||
let shouldBeActive = _isApplicationActive && _isViewVisible
|
||||
|
||||
if shouldBeActive, _refreshTimer == nil {
|
||||
UIApplication.shared.isIdleTimerDisabled = true
|
||||
_headerView.xionLogoView.beginAnimating()
|
||||
_updateConnectivityStatus(.connecting)
|
||||
_serverMultiplex.refreshDevices()
|
||||
|
||||
let timer = Timer(timeInterval: 10, repeats: true) { [weak self] _ in
|
||||
self?._serverMultiplex.refreshDevices()
|
||||
}
|
||||
RunLoop.main.add(timer, forMode: .common)
|
||||
_refreshTimer = timer
|
||||
} else if !shouldBeActive, _refreshTimer != nil {
|
||||
_refreshTimer?.invalidate()
|
||||
_refreshTimer = nil
|
||||
_serverMultiplex.disconnect()
|
||||
_updateConnectivityStatus(.disconnected)
|
||||
_headerView.xionLogoView.stopAnimating()
|
||||
UIApplication.shared.isIdleTimerDisabled = false
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Server Multiplex Delegate
|
||||
@@ -232,6 +275,7 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate, Serv
|
||||
{
|
||||
_switchesController.devicesStateChanged(devices.switches)
|
||||
_lightsController.devicesStateChanged(devices.lights)
|
||||
_updateVisualization(true)
|
||||
}
|
||||
|
||||
func serverMultiplex(_ multiplex: ServerMultiplex, didReceiveAcknowledgementFromServer server: Server)
|
||||
@@ -240,6 +284,11 @@ class MainViewController: UIViewController, SwitchesViewControllerDelegate, Serv
|
||||
let groupConnectionStatus = multiplex.groupConnectionStatus()
|
||||
_updateConnectivityStatus(groupConnectionStatus)
|
||||
}
|
||||
|
||||
func serverMultiplexConnectionStatusDidChange(_ multiplex: ServerMultiplex)
|
||||
{
|
||||
_updateConnectivityStatus(multiplex.groupConnectionStatus())
|
||||
}
|
||||
|
||||
func serverMultiplex(_ multiplex: ServerMultiplex, didEncounterError error: Error)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user