UNPKG

homebridge-virtual-accessories

Version:
111 lines 4.52 kB
/* eslint-disable brace-style */ import { Trigger } from './trigger.js'; import { Sensor } from '../sensor.js'; import dns from 'dns'; import net from 'net'; import ping from 'net-ping'; /** * Private helper classes to pass values by reference */ class Counter { value; constructor(value) { this.value = value; } } /** * PingTrigger - Trigger implementation */ export class PingTrigger extends Trigger { NOT_IP = 0; IPv4 = 4; IPv6 = 6; failureCount = new Counter(0); constructor(sensor, name) { super(sensor, name); const triggerConfig = this.sensorConfig.pingTrigger; if (triggerConfig.isDisabled) { this.log.info(`[${this.sensorConfig.accessoryName}] Ping trigger is disabled`); return; } this.setup(triggerConfig); } async setup(triggerConfig) { let ipProtocolVersion = net.isIP(triggerConfig.host); if (ipProtocolVersion === this.NOT_IP) { const ip = await this.getIP(triggerConfig.host); if (ip) { ipProtocolVersion = net.isIP(ip); triggerConfig.host = ip; } } let protocol; switch (ipProtocolVersion) { case this.IPv4: protocol = ping.NetworkProtocol.IPv4; break; case this.IPv6: protocol = ping.NetworkProtocol.IPv6; break; default: this.log.error(`[${this.sensorConfig.accessoryName}] Unkown or invalid IP protocol version: ${ipProtocolVersion}`); return; } this.log.debug(`[${this.sensorConfig.accessoryName}] Protocol: ${ping.NetworkProtocol[protocol]}`); const pingTimeoutMillis = 10 * 1000; // trigger.pingTimeout: 10 seconds const intervalBetweenPingsMillis = 60 * 1000; // trigger.intervalBetweenPings: 60 seconds setInterval(this.ping, intervalBetweenPingsMillis, this, triggerConfig, protocol, pingTimeoutMillis); } /** * Private methods */ async ping(trigger, triggerConfig, protocol, pingTimeoutMillis) { // If protocol === None, do a DNS lookup // const host = await getIP(hostname: string); // protocol = ping.NetworkProtocol.IPv4; // Create a helper class for protocol, so the value can be updated const options = { networkProtocol: protocol, packetSize: 16, retries: 3, sessionId: (process.pid % 65535), timeout: pingTimeoutMillis, ttl: 128, }; const sensorConfig = trigger.sensor.accessoryConfiguration; const session = ping.createSession(options); session.pingHost(triggerConfig.host, (error, target, sent, rcvd) => { const millis = rcvd - sent; if (error) { trigger.log.error(`[${sensorConfig.accessoryName}] Ping ${target}: ${error.toString()}`); if (trigger.failureCount.value < Number.MAX_VALUE) { trigger.failureCount.value++; } trigger.log.info(`[${sensorConfig.accessoryName}] Failure count: ${trigger.failureCount.value}`); if (trigger.failureCount.value === triggerConfig.failureRetryCount) { trigger.log.debug(`[${sensorConfig.accessoryName}] Reached failure retry count of ${triggerConfig.failureRetryCount}. Triggering sensor`); trigger.sensor.triggerSensorState(Sensor.TRIGGERED, trigger); } } else { trigger.log.debug(`[${sensorConfig.accessoryName}] Ping ${target}: Alive (latency: ${millis}ms)`); trigger.failureCount.value = 0; trigger.sensor.triggerSensorState(Sensor.NORMAL, trigger); } session.close(); }); } async getIP(hostname) { const response = await dns.promises.lookup(hostname) .then((result) => { this.sensor.platform.log.info(`[${this.sensorConfig.accessoryName}] IP address retrieved for '${hostname}' is '${result.address}'`); return result.address; }) .catch((error) => { this.sensor.platform.log.error(`[${this.sensorConfig.accessoryName}] Error retrieving IP address for '${hostname}': ${error.message}`); }); return response; } } export const dynamicTrigger = PingTrigger; //# sourceMappingURL=triggerPing.js.map