Skip to content

Commit

Permalink
Cache config/entity_registry/list_for_display
Browse files Browse the repository at this point in the history
  • Loading branch information
bgoncal committed Dec 12, 2024
1 parent 9eb6f4f commit 88764ce
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 0 deletions.
8 changes: 8 additions & 0 deletions HomeAssistant.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,9 @@
422E25EE2C80019D00256D87 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 420B100B2B1D204400D383D8 /* Assets.xcassets */; };
422E626C2CDCF00A00987BD0 /* AreaProvider.test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 422E626B2CDCF00A00987BD0 /* AreaProvider.test.swift */; };
422F951F2CFDF7C5003B7514 /* HAApplicationShortcutItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 422F951E2CFDF7C5003B7514 /* HAApplicationShortcutItem.swift */; };
42333ADB2D0B1771001E8408 /* EntityRegistryListForDisplay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42333ADA2D0B1771001E8408 /* EntityRegistryListForDisplay.swift */; };
42333ADC2D0B1771001E8408 /* EntityRegistryListForDisplay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42333ADA2D0B1771001E8408 /* EntityRegistryListForDisplay.swift */; };
42333ADD2D0B1771001E8408 /* EntityRegistryListForDisplay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42333ADA2D0B1771001E8408 /* EntityRegistryListForDisplay.swift */; };
4235075D2CDB756800A19902 /* HAServices.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4235075C2CDB756800A19902 /* HAServices.swift */; };
4235075E2CDB756800A19902 /* HAServices.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4235075C2CDB756800A19902 /* HAServices.swift */; };
4239D1832C4FFCCE003497FC /* WatchUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4239D1802C4FFB75003497FC /* WatchUserDefaults.swift */; };
Expand Down Expand Up @@ -1855,6 +1858,7 @@
422E25EC2C7FF28900256D87 /* ControlScriptsValueProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlScriptsValueProvider.swift; sourceTree = "<group>"; };
422E626B2CDCF00A00987BD0 /* AreaProvider.test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AreaProvider.test.swift; sourceTree = "<group>"; };
422F951E2CFDF7C5003B7514 /* HAApplicationShortcutItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HAApplicationShortcutItem.swift; sourceTree = "<group>"; };
42333ADA2D0B1771001E8408 /* EntityRegistryListForDisplay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntityRegistryListForDisplay.swift; sourceTree = "<group>"; };
4235075C2CDB756800A19902 /* HAServices.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HAServices.swift; sourceTree = "<group>"; };
4239D1802C4FFB75003497FC /* WatchUserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchUserDefaults.swift; sourceTree = "<group>"; };
423F44EF2C17238200766A99 /* ChatBubbleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatBubbleView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4929,6 +4933,7 @@
4278CB822D01F09400CFAAC9 /* HAGesture.swift */,
424D2D0F2C89DACE00C610F1 /* HAAppEntity.swift */,
42BB4C362CD26490003E47FD /* HATypedRequest+App.swift */,
42333ADA2D0B1771001E8408 /* EntityRegistryListForDisplay.swift */,
42F1DA6F2B4EE2E8002729BC /* HAAreaResponse.swift */,
426D9C722C9C582F00F278AF /* ControlEntityProvider.swift */,
42A47D4A2C9AEF10003C597D /* DataWidgetsUpdater.swift */,
Expand Down Expand Up @@ -6977,6 +6982,7 @@
1185DFAE271FF53800ED7D9A /* OnboardingAuthStepConfig.swift in Sources */,
425573CE2B5574F100145217 /* CarPlayAreasViewModel.swift in Sources */,
42BA1BC92C8864C200A2FC36 /* OpenPageAppIntent.swift in Sources */,
42333ADD2D0B1771001E8408 /* EntityRegistryListForDisplay.swift in Sources */,
B661FB7A226C197900E541DD /* OnboardingManualURLViewController.swift in Sources */,
119A827C252A3C4700D7000D /* NFCNDEFPayload+Additions.swift in Sources */,
42AC94A52CF872520050A62C /* TileCardStyleModifier.swift in Sources */,
Expand Down Expand Up @@ -7203,6 +7209,7 @@
113D29DF24946EDA0014067C /* CLLocationManager+OneShotLocation.swift in Sources */,
11CFD78227364F450082D557 /* Identifier.swift in Sources */,
11AF4D17249C8083006C74C0 /* With.swift in Sources */,
42333ADB2D0B1771001E8408 /* EntityRegistryListForDisplay.swift in Sources */,
11B38EF7275C54A300205C7B /* UpdateSensorsIntentHandler.swift in Sources */,
1141182B24AFA10900E6525C /* WebhookResponseHandler.swift in Sources */,
426266462C11B02C0081A818 /* InteractiveImmediateMessages.swift in Sources */,
Expand Down Expand Up @@ -7449,6 +7456,7 @@
4251AAC12C6CE9C4004CCC9D /* WatchConfig.swift in Sources */,
D03D893620E0AEFA00D4F28D /* Environment.swift in Sources */,
D0EEF2CE214D8AE200D1D360 /* RealmZone.swift in Sources */,
42333ADC2D0B1771001E8408 /* EntityRegistryListForDisplay.swift in Sources */,
11C65CC0249838EB00D07FC7 /* StreamCameraResponse.swift in Sources */,
B6A258452232485300ADD202 /* Alamofire+EncryptedResponses.swift in Sources */,
1182620424F9C453000795C6 /* HACoreMediaObjectSystem.swift in Sources */,
Expand Down
30 changes: 30 additions & 0 deletions Sources/Shared/Common/Extensions/GRDB+Initialization.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public enum GRDBDatabaseTable: String {
case assistPipelines
case carPlayConfig
case clientEvent
case appEntityRegistryListForDisplay
}

public enum DatabaseTables {
Expand Down Expand Up @@ -47,6 +48,13 @@ public enum DatabaseTables {
case jsonPayload
case date
}

public enum AppEntityRegistryListForDisplay: String {
case id
case serverId
case entityId
case registry
}
}

public extension DatabaseQueue {
Expand Down Expand Up @@ -85,13 +93,17 @@ public extension DatabaseQueue {
var shouldCreateWatchConfig = false
var shouldCreateCarPlayConfig = false
var shouldCreateClientEvent = false
var shouldCreateAppEntityRegistryListForDisplay = false

do {
try database.read { db in
shouldCreateHAppEntity = try !db.tableExists(GRDBDatabaseTable.HAAppEntity.rawValue)
shouldCreateWatchConfig = try !db.tableExists(GRDBDatabaseTable.watchConfig.rawValue)
shouldCreateCarPlayConfig = try !db.tableExists(GRDBDatabaseTable.carPlayConfig.rawValue)
shouldCreateAssistPipelines = try !db.tableExists(GRDBDatabaseTable.assistPipelines.rawValue)
shouldCreateClientEvent = try !db.tableExists(GRDBDatabaseTable.clientEvent.rawValue)
shouldCreateAppEntityRegistryListForDisplay = try !db
.tableExists(GRDBDatabaseTable.appEntityRegistryListForDisplay.rawValue)
}
} catch {
let errorMessage = "Failed to check if GRDB tables exist, error: \(error.localizedDescription)"
Expand Down Expand Up @@ -180,5 +192,23 @@ public extension DatabaseQueue {
Current.Log.error(errorMessage)
}
}

// AppEntityRegistryListForDisplay
if shouldCreateAppEntityRegistryListForDisplay {
do {
try database.write { db in
try db.create(table: GRDBDatabaseTable.appEntityRegistryListForDisplay.rawValue) { t in
t.primaryKey(DatabaseTables.AppEntityRegistryListForDisplay.id.rawValue, .text).notNull()
t.column(DatabaseTables.AppEntityRegistryListForDisplay.serverId.rawValue, .text).notNull()
t.column(DatabaseTables.AppEntityRegistryListForDisplay.entityId.rawValue, .text).notNull()
t.column(DatabaseTables.AppEntityRegistryListForDisplay.registry.rawValue, .jsonText).notNull()
}
}
} catch {
let errorMessage =
"Failed to create AppEntityRegistryListForDisplay GRDB table, error: \(error.localizedDescription)"
Current.Log.error(errorMessage)
}
}
}
}
33 changes: 33 additions & 0 deletions Sources/Shared/EntityRegistryListForDisplay.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Foundation
import GRDB
import HAKit

public struct EntityRegistryListForDisplay: HADataDecodable {
public let entityCategories: [String: String]
public let entities: [Entity]

public init(data: HAData) throws {
self.entityCategories = try data.decode("entity_categories")
self.entities = try data.decode("entities")
}

public struct Entity: HADataDecodable, Codable, FetchableRecord, PersistableRecord {
public let entityId: String
public let entityCategory: Int?
public let decimalPlaces: Int?

public init(data: HAData) throws {
self.entityId = try data.decode("ei")
self.entityCategory = try? data.decode("ec")
self.decimalPlaces = try? data.decode("dp")
}
}
}

public struct AppEntityRegistryListForDisplay: Codable, FetchableRecord, PersistableRecord {
/// serverId-entityId
let id: String
let serverId: String
let entityId: String
let registry: EntityRegistryListForDisplay.Entity
}
42 changes: 42 additions & 0 deletions Sources/Shared/Environment/PeriodicAppEntitiesModelUpdater.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Foundation
import GRDB
import HAKit

public protocol PeriodicAppEntitiesModelUpdaterProtocol {
Expand Down Expand Up @@ -26,6 +27,8 @@ final class PeriodicAppEntitiesModelUpdater: PeriodicAppEntitiesModelUpdaterProt
cancelOnGoingRequests()
Current.servers.all.forEach { server in
guard server.info.connection.activeURL() != nil else { return }

// Cache entities
let requestToken = Current.api(for: server)?.connection.send(
HATypedRequest<[HAEntity]>.fetchStates(),
completion: { result in
Expand All @@ -38,6 +41,45 @@ final class PeriodicAppEntitiesModelUpdater: PeriodicAppEntitiesModelUpdaterProt
}
)
requestTokens.append(requestToken)

// Cache entities registry list for display
let requestToken2 = Current.api(for: server)?.connection.send(
HATypedRequest<EntityRegistryListForDisplay>.fetchEntityRegistryListForDisplay(),
completion: { [weak self] result in
switch result {
case let .success(response):
self?.saveEntityRegistryListForDisplay(response, serverId: server.identifier.rawValue)
case let .failure(error):
Current.Log.error("Failed to fetch states: \(error)")
}
}
)
requestTokens.append(requestToken2)
}
}

private func saveEntityRegistryListForDisplay(_ response: EntityRegistryListForDisplay, serverId: String) {
let entitiesListForDisplay = response.entities.filter({ $0.decimalPlaces != nil || $0.entityCategory != nil })
.map { registry in
AppEntityRegistryListForDisplay(
id: ServerEntity.uniqueId(serverId: serverId, entityId: registry.entityId),
serverId: serverId,
entityId: registry.entityId,
registry: registry
)
}
do {
try Current.database.write { db in
try AppEntityRegistryListForDisplay
.filter(Column(DatabaseTables.AppEntityRegistryListForDisplay.serverId.rawValue) == serverId)
.deleteAll(db)
for record in entitiesListForDisplay {
try record.save(db)
}
}
} catch {
Current.Log
.error("Failed to save EntityRegistryListForDisplay in database, error: \(error.localizedDescription)")
}
}

Expand Down
6 changes: 6 additions & 0 deletions Sources/Shared/HATypedRequest+App.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,10 @@ public extension HATypedRequest {
type: .rest(.get, "states")
))
}

static func fetchEntityRegistryListForDisplay() -> HATypedRequest<EntityRegistryListForDisplay> {
HATypedRequest<EntityRegistryListForDisplay>(request: .init(
type: .webSocket("config/entity_registry/list_for_display")
))
}
}

0 comments on commit 88764ce

Please sign in to comment.