UNPKG

homebridge-ikettle

Version:

Simple HomeKit control for your iKettle. Easy access without faffing with Siri Shortcuts/IFTTT.

159 lines 6.3 kB
import { initializeApp } from 'firebase/app'; import { getAuth, signInWithEmailAndPassword } from 'firebase/auth'; import { getDatabase, ref, get, child, push, onValue } from 'firebase/database'; import { Observable } from 'rxjs'; import { SUPPORTED_DEVICES } from './models/constants.js'; export class iKettleService { log; app; static instance; userCredential; constructor(log) { this.log = log; const firebaseConfig = { apiKey: 'AIzaSyD0IOPaFj2zkMs5_rStrSRQ-m02bLwj88c', authDomain: 'smarter-live.firebaseapp.com', databaseURL: 'https://smarter-live.firebaseio.com', projectId: 'smarter-live', storageBucket: 'smarter-live.appspot.com', messagingSenderId: '41919779740' }; this.app = initializeApp(firebaseConfig); } // TODO: Unsure if this is the best way to got about things static getInstance(log) { if (!iKettleService.instance) { iKettleService.instance = new iKettleService(log); } return iKettleService.instance; } connect(config) { return new Observable((subscriber) => { (async () => { try { const auth = getAuth(this.app); this.userCredential = await signInWithEmailAndPassword(auth, config.email, config.password); const userId = this.userCredential.user.uid; const user = await this.getUser(userId); for (const networkId in user.networks_index) { const network = await this.getNetwork(networkId); for (const [deviceId, deviceName] of Object.entries(network.associated_devices)) { const deviceModel = await this.getDevice(deviceId); if (SUPPORTED_DEVICES.includes(deviceModel.status.device_model)) { deviceModel.id = deviceId; deviceModel.userId = userId; deviceModel.name = deviceName; subscriber.next(deviceModel); } } } subscriber.complete(); } catch (error) { subscriber.error(error); } })(); }); } async getUser(userId) { const dbRef = ref(getDatabase()); try { const userSnapshot = await get(child(dbRef, `users/${userId}`)); if (userSnapshot.exists()) { return userSnapshot.val(); } } catch (error) { this.log.error(JSON.stringify(error)); } throw new Error("Couldn't find user details"); } async getNetwork(networkId) { const dbRef = ref(getDatabase()); try { const networkSnapshot = await get(child(dbRef, `networks/${networkId}`)); if (networkSnapshot.exists()) { return networkSnapshot.val(); } } catch (error) { this.log.error(JSON.stringify(error)); } throw new Error("Couldn't find network details"); } async getDevice(deviceId) { const dbRef = ref(getDatabase()); try { const networkSnapshot = await get(child(dbRef, `devices/${deviceId}`)); if (networkSnapshot.exists()) { return networkSnapshot.val(); } } catch (error) { this.log.error(JSON.stringify(error)); } throw new Error("Couldn't find device details"); } watchDevice(deviceId) { const dbRef = ref(getDatabase(), `devices/${deviceId}`); return new Observable((observer) => { const unsubscribe = onValue(dbRef, (snapshot) => { const data = snapshot.val(); observer.next(data); }, (error) => { observer.error(error); }); return () => unsubscribe(); }); } async startBoil(userId, deviceId) { const data = { user_id: userId, value: true }; await this.sendCommand(deviceId, 'start_boil', data); } async stopBoil(userId, deviceId) { const data = { user_id: userId, value: true }; await this.sendCommand(deviceId, 'stop_boil', data); } async setBoilTemp(userId, deviceId, temp) { const data = { user_id: userId, value: temp }; await this.sendCommand(deviceId, 'set_boil_temperature', data); } async setManualBoilTemp(userId, deviceId, temp) { const data = { user_id: userId, value: temp }; await this.sendCommand(deviceId, 'set_manual_boil_temperature', data); } async setFormulaMode(userId, deviceId, value) { const data = { user_id: userId, value: value }; await this.sendCommand(deviceId, 'set_formula_mode_enable', data); } async setFormulaModeTemperature(userId, deviceId, temp) { const data = { user_id: userId, value: temp }; await this.sendCommand(deviceId, 'set_formula_mode_temperature', data); } async setKeepWarmTime(userId, deviceId, minutes) { const data = { user_id: userId, value: minutes }; await this.sendCommand(deviceId, 'set_keep_warm_time', data); } async sendCommand(deviceId, command, commandData) { this.authenticate(); const db = getDatabase(this.app); this.log.debug(`Sending command: ${JSON.stringify(commandData)}`); try { const commandRef = ref(db, `devices/${deviceId}/commands/${command}`); await push(commandRef, commandData); } catch (error) { this.log.error('Error sending command:', error); } } async authenticate() { // I think this will handle it for me? await this.userCredential?.user.getIdToken(); return; const tokenExpiry = new Date(this.userCredential.user.stsTokenManager.expirationTime); if (tokenExpiry <= new Date()) { await this.userCredential?.user.getIdToken(true); } } } //# sourceMappingURL=iKettleService.js.map