2022-11-07 20:49:11 +01:00
|
|
|
import type { HapDiscover } from './api'
|
2022-11-14 01:20:53 +01:00
|
|
|
import { HAPNodeJSClient, type HAPNodeJSClientConfig } from 'hap-node-client'
|
2022-11-13 13:34:09 +01:00
|
|
|
import { type Device, DeviceBoundary, checkBoundary } from '../../boundaries'
|
2022-11-10 13:00:45 +01:00
|
|
|
import type { Logger } from 'homebridge'
|
2022-11-08 19:13:34 +01:00
|
|
|
import z from 'zod'
|
2022-11-06 13:50:39 +01:00
|
|
|
|
2022-11-08 19:13:34 +01:00
|
|
|
const MaybeDevices = z.array(z.unknown())
|
2022-11-06 13:50:39 +01:00
|
|
|
|
2022-11-07 19:30:55 +01:00
|
|
|
type ResolveFunc = (devices: Device[]) => void
|
|
|
|
type RejectFunc = (error: unknown) => void
|
|
|
|
|
2022-11-08 19:13:34 +01:00
|
|
|
const clientMap: Record<string, HAPNodeJSClient> = {}
|
2022-11-07 20:49:11 +01:00
|
|
|
const promiseMap: Record<string, [ResolveFunc, RejectFunc]> = {}
|
2022-11-07 19:30:55 +01:00
|
|
|
|
2022-11-14 01:20:53 +01:00
|
|
|
function startDiscovery(logger: Logger, config: HAPNodeJSClientConfig, resolve: ResolveFunc, reject: RejectFunc) {
|
2022-11-07 19:30:55 +01:00
|
|
|
const key = JSON.stringify(config)
|
|
|
|
|
|
|
|
if (!clientMap[key]) {
|
|
|
|
logger.debug('Creating new HAP client')
|
|
|
|
const client = new HAPNodeJSClient(config)
|
|
|
|
client.on('Ready', (deviceData: unknown) => {
|
|
|
|
try {
|
|
|
|
const devices: Device[] = []
|
|
|
|
|
2022-11-09 21:36:23 +01:00
|
|
|
for (const device of checkBoundary(MaybeDevices, deviceData)) {
|
2022-11-07 19:30:55 +01:00
|
|
|
try {
|
2022-11-09 21:36:23 +01:00
|
|
|
devices.push(checkBoundary(DeviceBoundary, device))
|
2022-11-07 19:30:55 +01:00
|
|
|
} catch (e) {
|
2022-11-07 20:49:11 +01:00
|
|
|
logger.error('Boundary check for device data failed %o %s', e, JSON.stringify(device, null, 4))
|
2022-11-07 19:30:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (promiseMap[key]) promiseMap[key][0](devices)
|
|
|
|
} catch (e) {
|
|
|
|
if (promiseMap[key]) promiseMap[key][1](e)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
clientMap[key] = client
|
|
|
|
} else {
|
|
|
|
logger.debug('Reusing existing HAP client')
|
|
|
|
}
|
|
|
|
promiseMap[key] = [resolve, reject]
|
|
|
|
}
|
|
|
|
|
2022-11-14 01:20:53 +01:00
|
|
|
export const hapNodeJsClientDiscover: HapDiscover = ({ config, log }) => {
|
2022-11-06 13:50:39 +01:00
|
|
|
return new Promise((resolve, reject) => {
|
2022-11-07 19:30:55 +01:00
|
|
|
startDiscovery(
|
2022-11-14 01:20:53 +01:00
|
|
|
log,
|
2022-11-07 19:30:55 +01:00
|
|
|
{
|
2022-11-14 01:20:53 +01:00
|
|
|
debug: config.debug,
|
|
|
|
refresh: config.refresh_interval,
|
|
|
|
timeout: config.discovery_timeout,
|
|
|
|
reqTimeout: config.request_timeout,
|
|
|
|
pin: config.pin,
|
2022-11-07 19:30:55 +01:00
|
|
|
},
|
|
|
|
resolve,
|
2022-11-07 20:49:11 +01:00
|
|
|
reject,
|
2022-11-07 19:30:55 +01:00
|
|
|
)
|
2022-11-06 13:50:39 +01:00
|
|
|
})
|
|
|
|
}
|