Skip to content

Commit 6952af2

Browse files
authored
Fix "button" domain not working on CarPlay quick access (#3342)
1 parent 73ca010 commit 6952af2

File tree

3 files changed

+54
-50
lines changed

3 files changed

+54
-50
lines changed

Sources/CarPlay/Templates/HAEntity+CarPlay.swift

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -32,41 +32,10 @@ extension HAEntity {
3232
}
3333

3434
func onPress(for api: HomeAssistantAPI) -> Promise<Void> {
35-
var request: HATypedRequest<HAResponseVoid>?
36-
switch Domain(rawValue: domain) {
37-
case .button:
38-
request = .pressButton(domain: .button, entityId: entityId)
39-
case .cover:
40-
request = .toggleDomain(domain: .cover, entityId: entityId)
41-
case .inputBoolean:
42-
request = .toggleDomain(domain: .inputBoolean, entityId: entityId)
43-
case .inputButton:
44-
request = .pressButton(domain: .inputButton, entityId: entityId)
45-
case .light:
46-
request = .toggleDomain(domain: .light, entityId: entityId)
47-
case .scene:
48-
request = .applyScene(entityId: entityId)
49-
case .script:
50-
request = .runScript(entityId: entityId)
51-
case .switch:
52-
request = .toggleDomain(domain: .switch, entityId: entityId)
53-
case .lock:
54-
guard let state = Domain.State(rawValue: state) else { return .value }
55-
switch state {
56-
case .unlocking, .unlocked, .opening:
57-
request = .lockLock(entityId: entityId)
58-
case .locked, .locking:
59-
request = .unlockLock(entityId: entityId)
60-
default:
61-
break
62-
}
63-
case .none, .sensor, .binarySensor, .zone, .person:
64-
break
65-
}
66-
if let request {
67-
return api.connection.send(request).promise
68-
.map { _ in () }
35+
if let domain = Domain(rawValue: domain) {
36+
return api.executeActionForDomainType(domain: domain, entityId: entityId, state: state)
6937
} else {
38+
Current.Log.error("Failed to parse domain for entity \(entityId)")
7039
return .value
7140
}
7241
}

Sources/CarPlay/Templates/QuickAccess/CarPlayQuickAccessTemplate.swift

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,16 @@ final class CarPlayQuickAccessTemplate: CarPlayTemplateProvider {
110110
let entityProvider = CarPlayEntityListItem(serverId: magicItem.serverId, entity: placeholderItem)
111111
let listItem = entityProvider.template
112112
listItem.handler = { [weak self] _, _ in
113-
self?.itemTap(magicItem: magicItem, info: info, item: listItem)
113+
self?.itemTap(
114+
magicItem: magicItem,
115+
info: info,
116+
item: listItem,
117+
currentItemState: placeholderItem.state
118+
)
114119
}
115120
entityProviders.append(entityProvider)
116121
return listItem
117122
default:
118-
119123
let icon = magicItem.icon(info: info).carPlayIcon(color: .init(hex: info.customization?.iconColor))
120124
let item = CPListItem(
121125
text: info.name,
@@ -146,26 +150,27 @@ final class CarPlayQuickAccessTemplate: CarPlayTemplateProvider {
146150
private func itemTap(
147151
magicItem: MagicItem,
148152
info: MagicItem.Info,
149-
item: CPListItem
153+
item: CPListItem,
154+
currentItemState: String = ""
150155
) {
151156
if info.customization?.requiresConfirmation ?? false {
152157
showConfirmationForRunningMagicItem(item: magicItem, info: info) { [weak self] in
153-
self?.executeMagicItem(magicItem, item: item)
158+
self?.executeMagicItem(magicItem, item: item, currentItemState: currentItemState)
154159
}
155160
} else {
156-
executeMagicItem(magicItem, item: item)
161+
executeMagicItem(magicItem, item: item, currentItemState: currentItemState)
157162
}
158163
}
159164

160-
private func executeMagicItem(_ magicItem: MagicItem, item: CPListItem) {
165+
private func executeMagicItem(_ magicItem: MagicItem, item: CPListItem, currentItemState: String = "") {
161166
guard let server = Current.servers.all.first(where: { server in
162167
server.identifier.rawValue == magicItem.serverId
163168
}), let api = Current.api(for: server) else {
164169
Current.Log.error("Failed to get server for magic item id: \(magicItem.id)")
165170
displayItemResultIcon(on: item, success: false)
166171
return
167172
}
168-
api.executeMagicItem(item: magicItem) { success in
173+
api.executeMagicItem(item: magicItem, currentItemState: currentItemState) { success in
169174
self.displayItemResultIcon(on: item, success: success)
170175
}
171176
}

Sources/Shared/API/HAAPI.swift

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,8 @@ public class HomeAssistantAPI {
778778
}
779779
}
780780

781-
public func executeMagicItem(item: MagicItem, completion: @escaping (Bool) -> Void) {
781+
// currentItemState is used only for lock domain since it can't be toggled
782+
public func executeMagicItem(item: MagicItem, currentItemState: String = "", completion: @escaping (Bool) -> Void) {
782783
Current.Log.verbose("Selected magic item id: \(item.id)")
783784
firstly { () -> Promise<Void> in
784785
switch item.type {
@@ -807,14 +808,11 @@ public class HomeAssistantAPI {
807808
guard let domain = item.domain else {
808809
throw MagicItemError.unknownDomain
809810
}
810-
return Current.api(for: server)?.CallService(
811-
domain: domain.rawValue,
812-
service: "toggle",
813-
serviceData: [
814-
"entity_id": item.id,
815-
],
816-
shouldLog: true
817-
) ?? .init(error: HomeAssistantAPI.APIError.noAPIAvailable)
811+
return executeActionForDomainType(
812+
domain: domain,
813+
entityId: item.id,
814+
state: currentItemState
815+
)
818816
}
819817
}.done {
820818
completion(true)
@@ -824,6 +822,38 @@ public class HomeAssistantAPI {
824822
}
825823
}
826824

825+
public func executeActionForDomainType(domain: Domain, entityId: String, state: String) -> Promise<Void> {
826+
var request: HATypedRequest<HAResponseVoid>?
827+
switch domain {
828+
case .button, .inputButton:
829+
request = .pressButton(domain: domain, entityId: entityId)
830+
case .cover, .inputBoolean, .light, .switch:
831+
request = .toggleDomain(domain: domain, entityId: entityId)
832+
case .scene:
833+
request = .applyScene(entityId: entityId)
834+
case .script:
835+
request = .runScript(entityId: entityId)
836+
case .lock:
837+
guard let state = Domain.State(rawValue: state) else { return .value }
838+
switch state {
839+
case .unlocking, .unlocked, .opening:
840+
request = .lockLock(entityId: entityId)
841+
case .locked, .locking:
842+
request = .unlockLock(entityId: entityId)
843+
default:
844+
break
845+
}
846+
case .sensor, .binarySensor, .zone, .person:
847+
break
848+
}
849+
if let request {
850+
return connection.send(request).promise
851+
.map { _ in () }
852+
} else {
853+
return .value
854+
}
855+
}
856+
827857
public func registerSensors() -> Promise<Void> {
828858
firstly {
829859
Current.sensors.sensors(reason: .registration, server: server).map(\.sensors)

0 commit comments

Comments
 (0)