Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subscribe only to domains that the app has usage for #3154

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Sources/App/AppEntitiesObserver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ enum AppEntitiesObserver {
func start() {
container = .init { server in
.init(
Current.api(for: server).connection.caches.states.subscribe({ [weak self] _, states in
Current.api(for: server).connection.caches.states().subscribe({ [weak self] _, states in
guard let self, UIApplication.shared.applicationState == .active else { return }
let appRelatedEntities = states.all.filter { self.domainsAppUse.contains($0.domain) }
handle(appRelatedEntities: appRelatedEntities, server: server)
Expand Down
2 changes: 1 addition & 1 deletion Sources/App/Scenes/CarPlaySceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class CarPlaySceneDelegate: UIResponder {
let server = Current.servers.server(forServerIdentifier: preferredServerId) ?? Current.servers.all.first

guard let server, entitiesSubscriptionToken == nil else { return }
entities = Current.api(for: server).connection.caches.states
entities = Current.api(for: server).connection.caches.states()
entitiesSubscriptionToken?.cancel()
entitiesSubscriptionToken = entities?.subscribe { [weak self] _, states in
self?.allTemplates.forEach {
Expand Down
2 changes: 1 addition & 1 deletion Sources/App/Settings/Eureka/AccountRow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ final class HomeAssistantAccountRow: Row<AccountCell>, RowType {
}
}

avatarSubscription = connection.caches.states.subscribe { [weak self] _, states in
avatarSubscription = connection.caches.states().subscribe { [weak self] _, states in
firstly { () -> Guarantee<Set<HAEntity>> in
Guarantee.value(states.all)
}.map { states throws -> HAEntity in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ final class CarPlayAreasViewModel {
// swiftlint:enable cyclomatic_complexity

private func listItemHandler(area: HAAreaResponse, entityIdsForAreaId: [String], server: Server) {
guard let entitiesCachedStates = Current.api(for: server).connection.caches.states.value else { return }
guard let entitiesCachedStates = Current.api(for: server).connection.caches.states().value else { return }
entitiesListTemplate = CarPlayEntitiesListTemplate.build(
title: area.name,
filterType: .areaId(entityIds: entityIdsForAreaId),
Expand Down
8 changes: 6 additions & 2 deletions Sources/CarPlay/Templates/HAEntity+CarPlay.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ extension HAEntity {
default:
break
}
case .none, .sensor:
case .none, .sensor, .binarySensor, .zone:
break
}
if let request {
Expand Down Expand Up @@ -98,7 +98,11 @@ extension HAEntity {
case .switch:
image = getSwitchIcon()
case .sensor:
image = MaterialDesignIcons.thermometerIcon
image = MaterialDesignIcons.eyeIcon
case .binarySensor:
image = MaterialDesignIcons.eyeIcon
case .zone:
image = MaterialDesignIcons.mapIcon
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ final class CarPlayQuickAccessTemplate: CarPlayTemplateProvider {
case .entity:
guard let server = Current.servers.server(forServerIdentifier: preferredServerId) ?? Current.servers.all
.first,
let item = Current.api(for: server).connection.caches.states.value?.all.first(where: {
let item = Current.api(for: server).connection.caches.states().value?.all.first(where: {
$0.entityId == magicItem.id
}) else { return .init(text: "", detailText: "") }

Expand Down
41 changes: 40 additions & 1 deletion Sources/Shared/API/Models/ModelManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,37 @@ public class ModelManager: ServerObserver {
private var subscribedSubscriptions = [SubscribeDefinition]()
private var cleanupDefinitions = [CleanupDefinition]()

private static var includedDomains: [Domain] = {
// Mac does not need all domains given it does not have all features as iOS (CarPlay, Watch)
#if targetEnvironment(macCatalyst)
[
.cover,
.light,
.scene,
.script,
.switch,
.sensor,
.binarySensor,
.zone,
]
#else
[
.button,
.cover,
.inputBoolean,
.inputButton,
.light,
.lock,
.scene,
.script,
.switch,
.sensor,
.binarySensor,
.zone,
]
#endif
}()

public var workQueue: DispatchQueue = .global(qos: .userInitiated)

deinit {
Expand Down Expand Up @@ -211,7 +242,15 @@ public class ModelManager: ServerObserver {
var lastEntities = Set<HAEntity>()

return [
connection.caches.states.subscribe { [weak someManager] token, value in
// Since here is where the app first initializes the cache, we need to make sure
// we define the correct domains to include in the subscription
connection.caches.states(
[
"include": [
"domains": ModelManager.includedDomains.map(\.rawValue),
],
]
).subscribe { [weak someManager] token, value in
queue.async {
guard let manager = someManager else {
token.cancel()
Expand Down
2 changes: 1 addition & 1 deletion Sources/Shared/API/WebSocket/HAPanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@
}
}

private struct HAPanelsCacheKey: HACacheKey {

Check failure on line 120 in Sources/Shared/API/WebSocket/HAPanel.swift

View workflow job for this annotation

GitHub Actions / test

type 'HAPanelsCacheKey' does not conform to protocol 'HACacheKey'

Check failure on line 120 in Sources/Shared/API/WebSocket/HAPanel.swift

View workflow job for this annotation

GitHub Actions / test

type 'HAPanelsCacheKey' does not conform to protocol 'HACacheKey'
static func create(connection: HAConnection) -> HACache<HAPanels> {
static func create(connection: HAConnection, data: [String: Any]) -> HACache<HAPanels> {
HACache(
connection: connection,
populate: .init(
Expand Down
20 changes: 8 additions & 12 deletions Sources/Shared/Domain/Domain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public enum Domain: String, CaseIterable {
case script
case `switch`
case sensor
case binarySensor = "binary_sensor"
case zone
// TODO: Map more domains

public enum State: String {
Expand All @@ -36,25 +38,15 @@ public enum Domain: String, CaseIterable {
public var states: [State] {
var states: [State] = []
switch self {
case .button:
states = []
case .cover:
states = [.open, .closed, .opening, .closing]
case .inputBoolean:
states = []
case .inputButton:
states = []
case .light:
states = [.on, .off]
case .lock:
states = [.locked, .unlocked, .jammed, .locking, .unlocking]
case .scene:
states = []
case .script:
states = []
case .switch:
states = [.on, .off]
case .sensor:
default:
states = []
}

Expand Down Expand Up @@ -84,7 +76,11 @@ public enum Domain: String, CaseIterable {
case .switch:
image = MaterialDesignIcons.lightSwitchIcon
case .sensor:
image = MaterialDesignIcons.thermometerIcon
image = MaterialDesignIcons.eyeIcon
case .binarySensor:
image = MaterialDesignIcons.eyeIcon
case .zone:
image = MaterialDesignIcons.mapIcon
}
return image
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Shared/Intents/GetCameraImageIntentHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class GetCameraImageIntentHandler: NSObject, GetCameraImageIntentHandling {
return
}

Current.api(for: server).connection.caches.states.once().promise.map(\.all)
Current.api(for: server).connection.caches.states().once().promise.map(\.all)
.filterValues { $0.domain == "camera" }
.mapValues(\.entityId)
.sortedValues()
Expand Down
Loading