### Populate Cache with GetStates Source: https://github.com/home-assistant/hakit/blob/main/README.md Define a cache population strategy to request all states and transform the result into a set of entity IDs. This example demonstrates using a convenience helper for the request. ```swift let populate = HACachePopulateInfo>( request: .getStates(), transform: { info in return Set(info.incoming.map(\.entityId)) } ) ``` -------------------------------- ### Subscribe to State Changes with HACacheSubscribeInfo Source: https://github.com/home-assistant/hakit/blob/main/README.md Use HACacheSubscribeInfo to define how to subscribe to events and transform them for cache updates. This example shows how to track entity IDs based on state changes. ```swift let subscribe = HACacheSubscribeInfo>( subscription: .stateChanged(), transform: { info in var entityIds = info.current if info.incoming.newState == nil { entityIds.remove(info.incoming.entityId) } else { entityIds.insert(info.incoming.entityId) } return .replace(entityIds) } ) ``` -------------------------------- ### Create and Connect to Home Assistant Source: https://github.com/home-assistant/hakit/blob/main/README.md Initializes a connection to a Home Assistant instance. Requires server URL and an access token, which are re-queried on each connection attempt. The connection attempts to stay connected automatically. ```swift let connection = HAKit.connection(configuration: .init( connectionInfo: { // Connection is required to be returned synchronously. // In a real implementation, handle both URL/connection info without crashing. try! .init(url: URL(string: "http://homeassistant.local:8123")!) }, fetchAuthToken: { completion in // Access tokens are retrieved asynchronously, but be aware that Home Assistant // has a timeout of 10 seconds for sending your access token. completion(.success("API_Token_Here")) } )) ``` -------------------------------- ### Combine Client Identity with Certificate Evaluation Source: https://github.com/home-assistant/hakit/blob/main/README.md Initialize connection configuration with custom certificate evaluation logic and client identity loading. Useful for self-signed certificates. ```swift try .init( url: URL(string: "https://homeassistant.example.com")!, evaluateCertificate: { secTrust, completion in // Custom certificate validation logic // Call completion(.success(())) to accept or completion(.failure(error)) to reject completion(.success(())) }, clientIdentity: { return loadClientIdentityFromKeychain() } ) ``` -------------------------------- ### Create a Cache with Populate and Subscribe Source: https://github.com/home-assistant/hakit/blob/main/README.md Instantiate a HACache object by providing a connection, a populate strategy, and subscription information. This cache will maintain the current known entity IDs. ```swift let entityIds = HACache(connection: connection, populate: populate, subscribe: subscribe) ``` -------------------------------- ### Configure Global Logging Source: https://github.com/home-assistant/hakit/blob/main/README.md Enable library logging by assigning a closure to HAGlobal.log. This closure will receive log messages as strings. ```swift HAGlobal.log = { text in // just straight to the console print($0) // or something like XCGLogger log.info("WebSocket: \(text)") } ``` -------------------------------- ### Subscribe to RenderTemplate Event Source: https://github.com/home-assistant/hakit/blob/main/README.md Use the convenience helper to subscribe to template rendering events. Provides callbacks for initiation results and ongoing responses. ```swift connection.subscribe( to: .renderTemplate("{{ states('sun.sun') }} {{ states.device_tracker | count }}"), initiated: { result in // when the initiated method is provided, this is the result of the subscription }, handler: { [textView] cancelToken, response in // the overall response is parsed for type, but native template rendering means // the rendered type will be a Dictionary, Array, etc. textView.text = String(describing: response.result) // you could call `cancelToken.cancel()` to end the subscription here if desired } ) ``` -------------------------------- ### Load Client Identity from PKCS12 Source: https://github.com/home-assistant/hakit/blob/main/README.md Function to load a client identity from PKCS12 data using a password. Returns nil if import fails or no identity is found. ```swift func loadClientIdentity(from p12Data: Data, password: String) -> SecIdentity? { var importResult: CFArray? let options = [kSecImportExportPassphrase: password] as CFDictionary let status = SecPKCS12Import(p12Data as CFData, options, &importResult) guard status == errSecSuccess, let items = importResult as? [[String: Any]], let firstItem = items.first, let identity = firstItem[kSecImportItemIdentity as String] as? SecIdentity else { return nil } return identity } ``` -------------------------------- ### Send CurrentUser Request Source: https://github.com/home-assistant/hakit/blob/main/README.md Use the convenience helper to send a request for the current user's information. Handles success and failure cases. ```swift connection.send(.currentUser()) { result in switch result { case let .success(user): // e.g. user.id or user.name are available on the result object case let .failure(error): // an error occurred with the request } } ``` -------------------------------- ### Implement mTLS for REST API Source: https://github.com/home-assistant/hakit/blob/main/README.md Implement the HACertificateProvider protocol to provide custom client certificates and evaluate server trust for REST API calls. Requires loading client identity and configuring URLSession. ```swift struct MyCertificateProvider: HACertificateProvider { func provideClientCertificate( for challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void ) { // Load and provide your client certificate if let identity = loadClientIdentityFromKeychain() { let credential = URLCredential( identity: identity, certificates: nil, persistence: .none ) completionHandler(.useCredential, credential) } else { completionHandler(.cancelAuthenticationChallenge, nil) } } func evaluateServerTrust( _ serverTrust: SecTrust, forHost host: String, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void ) { // Optionally validate self-signed or custom CA certificates // For standard certificates, you can use default handling: completionHandler(.performDefaultHandling, nil) } } // 2. Create a URLSession with the certificate provider let provider = MyCertificateProvider() let delegate = HAURLSessionDelegate(certificateProvider: provider) let urlSession = URLSession( configuration: .ephemeral, delegate: delegate, delegateQueue: nil ) // 3. Pass the URLSession when creating the connection let connection = HAKit.connection( configuration: .init( connectionInfo: { try! .init(url: URL(string: "https://homeassistant.example.com")!) }, fetchAuthToken: { completion in completion(.success("API_Token_Here")) } ), urlSession: urlSession ) ``` -------------------------------- ### Subscribe to Raw RenderTemplate Event Source: https://github.com/home-assistant/hakit/blob/main/README.md Subscribe directly to template rendering events and receive raw HAData. Requires manual decoding of the response. ```swift connection.subscribe( to: .init(type: .renderTemplate, data: [ "template": "{{ states('sun.sun') }} {{ states.device_tracker | count }}" ]), initiated: { result in // when the initiated method is provided, this is the result of the subscription }, handler: { [textView] cancelToken, data in // data is an `HAData` which wraps possible responses and provides decoding // the decode methods infer which type you're asking for and attempt to convert textView.text = try? data.decode("result") // you could call `cancelToken.cancel()` to end the subscription here if desired } ) ``` -------------------------------- ### WebSocket mTLS Connection to Home Assistant Source: https://github.com/home-assistant/hakit/blob/main/README.md Establishes a WebSocket connection using mutual TLS (mTLS) authentication. This is useful for connecting to Home Assistant instances behind reverse proxies that require client certificate authentication. Ensure your client identity is loaded securely, typically from a .p12 file. ```swift let connection = HAKit.connection(configuration: .init( connectionInfo: { try! .init( url: URL(string: "https://homeassistant.example.com")!, clientIdentity: { // Return your SecIdentity containing the client certificate and private key // This is typically loaded from a .p12 file stored in the Keychain return loadClientIdentityFromKeychain() } ) }, fetchAuthToken: { completion(.success("API_Token_Here")) } )) ``` -------------------------------- ### Send REST API Request Source: https://github.com/home-assistant/hakit/blob/main/README.md Make a REST API call, such as a POST request to the template endpoint, with data provided as the body. The result is handled similarly to WebSocket requests. ```swift Current.apiConnection.send(.init( // this will POST to `/api/template` with the data as the body type: .rest(.post, "template"), data: ["template": "{{ now() }}"] )) { result in // same result type as sending a WebSocket request } ``` -------------------------------- ### CocoaPods Dependency Source: https://github.com/home-assistant/hakit/blob/main/README.md Add Hakit to your project using CocoaPods by including the 'Hakit' pod in your Podfile. Specify the Starscream fork if needed. ```ruby pod "Hakit", "~> 0.4.14" pod 'Starscream', git: 'https://github.com/bgoncal/starscream', branch: 'ha-URLSession-fix' ``` -------------------------------- ### Send Raw CurrentUser Request Source: https://github.com/home-assistant/hakit/blob/main/README.md Issue a request directly for the current user and receive the raw HAData response. Requires manual decoding. ```swift connection.send(.init(type: .currentUser, data: [:])) { result in switch result { case let .success(data): // data is an `HAData` which wraps possible responses and provides decoding case let .failure(error): // an error occurred with the request } } ``` -------------------------------- ### Swift Package Manager Dependency Source: https://github.com/home-assistant/hakit/blob/main/README.md Add Hakit as a dependency to your Swift Package Manager project by specifying the URL and version in your Package.swift file. ```swift .package(url: "https://github.com/home-assistant/HAKit", from: Version(0, 4, 5)) ``` -------------------------------- ### Subscribe to Cache Changes Source: https://github.com/home-assistant/hakit/blob/main/README.md Subscribe to changes in the cache to receive updates on its value. The closure will be called with a token and the current value whenever the cache is updated. ```swift entityIds.subscribe { token, value in print("current entity ids are: \(value)") } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.