hap-controller
Version:
Library to implement a HAP (HomeKit) controller
152 lines • 4.88 kB
JavaScript
;
/**
* Zeroconf wrappers for finding HAP devices.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.DiscoveryPairingFeatureFlags = exports.DiscoveryPairingStatusFlags = void 0;
const events_1 = require("events");
const dnssd_1 = require("dnssd");
const pairing_protocol_1 = require("../../protocol/pairing-protocol");
/**
* See Table 6-8
*/
const DiscoveryPairingStatusFlags = {
AccessoryNotPaired: 0x01,
AccessoryNotConfiguredToJoinWifi: 0x02,
AccessoryHasProblems: 0x04,
};
exports.DiscoveryPairingStatusFlags = DiscoveryPairingStatusFlags;
/**
* See Table 5-4
*/
const DiscoveryPairingFeatureFlags = {
SupportsAppleAuthenticationCoprocessor: 0x01, // MFi HW
SupportsSoftwareAuthentication: 0x02, // MFi SW
};
exports.DiscoveryPairingFeatureFlags = DiscoveryPairingFeatureFlags;
/**
* Handle discovery of IP devices
*
* @fires IPDiscovery#serviceUp
* @fires IPDiscovery#serviceDown
* @fires IPDiscovery#serviceChanged
*/
class IPDiscovery extends events_1.EventEmitter {
/**
* Initialize the IPDiscovery object.
*
* @param {string?} iface - Optional interface to bind to
*/
constructor(iface) {
super();
this.browser = null;
if (iface) {
this.iface = iface;
}
this.services = new Map();
}
/**
* Convert a DNS-SD service record to a HAP service object.
*
* See Table 5-7
*
* @param {Object} service - Service record to convert
*/
static _serviceToHapService(service) {
const sf = parseInt(service.txt.sf, 10);
return {
name: service.name,
address: service.addresses[0],
allAddresses: service.addresses,
port: service.port,
'c#': parseInt(service.txt['c#']),
ff: parseInt(service.txt.ff || '0', 10),
id: service.txt.id,
md: service.txt.md,
pv: service.txt.pv || '1.0',
's#': parseInt(service.txt['s#'], 10),
sf,
ci: parseInt(service.txt.ci, 10),
// sh: service.txt.sh,
availableToPair: !!(sf & DiscoveryPairingStatusFlags.AccessoryNotPaired),
};
}
/**
* Get PairMethod to use for pairing from the data received during discovery
*
* @param {HapServiceIp} service Discovered service object to check
* @returns {Promise<number>} Promise which resolves with the PairMethod to use
*/
async getPairMethod(service) {
// async to be compatible with the BLE variant
return service.ff & DiscoveryPairingFeatureFlags.SupportsAppleAuthenticationCoprocessor
? pairing_protocol_1.PairMethods.PairSetupWithAuth
: pairing_protocol_1.PairMethods.PairSetup;
}
/**
* Start searching for HAP devices on the network.
*/
start() {
if (this.browser) {
this.browser.stop();
}
const options = {};
if (this.iface) {
options.interface = this.iface;
}
this.browser = new dnssd_1.Browser(new dnssd_1.ServiceType('_hap._tcp'), options);
this.browser.on('serviceUp', (service) => {
const hapService = IPDiscovery._serviceToHapService(service);
this.services.set(hapService.id, hapService);
/**
* New device discovered event
*
* @event IPDiscovery#serviceUp
* @type HapServiceIp
*/
this.emit('serviceUp', hapService);
});
this.browser.on('serviceDown', (service) => {
const hapService = IPDiscovery._serviceToHapService(service);
this.services.delete(hapService.id);
/**
* Device offline event
*
* @event IPDiscovery#serviceDown
* @type HapServiceIp
*/
this.emit('serviceDown', hapService);
});
this.browser.on('serviceChanged', (service) => {
const hapService = IPDiscovery._serviceToHapService(service);
this.services.set(hapService.id, hapService);
/**
* Device data changed event
*
* @event IPDiscovery#serviceChanged
* @type HapServiceIp
*/
this.emit('serviceChanged', hapService);
});
this.browser.start();
}
/**
* List the currently known services.
*
* @returns {HapServiceIp[]} Array of services
*/
list() {
return Array.from(this.services.values());
}
/**
* Stop an ongoing discovery process.
*/
stop() {
if (this.browser) {
this.browser.stop();
this.browser = null;
}
}
}
exports.default = IPDiscovery;
//# sourceMappingURL=ip-discovery.js.map