homebridge-blaq
Version:
Control and view your garage door(s) remotely with real-time updates using Konnected's BlaQ hardware
100 lines • 4.21 kB
JavaScript
import { EventSource } from 'eventsource';
const ONE_SECOND_IN_MS = 1000;
const ONE_MINUTE_IN_MS = 60 * ONE_SECOND_IN_MS;
export class AutoReconnectingEventSource {
protocol;
host;
port;
user;
pass;
path;
logger;
onLog;
onStateUpdate;
onPing;
eventSource;
lastEventSourceEventDate;
maxIdleBeforeReconnect;
idleCheckInterval;
constructor({ protocol = 'http', host, port = 80, user, pass, path = 'events', maxIdleBeforeReconnect = ONE_MINUTE_IN_MS, logger, onLog = (log) => logger.warn('No onLog handler provided to AutoReconnectingEventsource. Got log:', log), onStateUpdate = (state) => logger.warn('No onStateUpdate handler provided to AutoReconnectingEventsource. Got state:', state), onPing = (ping) => logger.warn('No onPing handler provided to AutoReconnectingEventsource. Got ping:', ping), }) {
this.logger = logger;
this.logger.debug('Initializing AutoReconnectingEventSource...');
const correctedProtocol = protocol.split('://').shift();
this.protocol = correctedProtocol;
this.host = host;
this.port = port;
this.user = user;
this.pass = pass;
const correctedPath = path.startsWith('/') ? path.slice(1) : path;
this.path = correctedPath;
this.onLog = onLog;
this.onStateUpdate = onStateUpdate;
this.onPing = onPing;
this.maxIdleBeforeReconnect = maxIdleBeforeReconnect;
this.connectEventSource();
this.logger.debug('Initialized AutoReconnectingEventSource!');
}
connectEventSource() {
if (!this.eventSource) {
const basicCreds = `${this.user}:${this.pass}`;
const eventSourceOptions = {
fetch: (url, options) => {
this.logger.debug(`Fetching EventSource URL: ${url} with options:`, options);
return fetch(url, {
...options,
headers: {
...options.headers,
...(this.user && this.pass ? {
'Authorization': `Basic ${Buffer.from(basicCreds).toString('base64')}`,
} : {}),
},
});
},
};
this.eventSource = new EventSource(`${this.protocol}://${this.host}:${this.port}/${this.path}`, eventSourceOptions);
this.eventSource.addEventListener('error', error => {
this.logger.error('EventSource got error', error);
this.logger.error('Reinitializing EventSource...');
this.close();
if (error.code === 401) {
this.logger.error('Please configure valid credentials for this device!');
}
else {
this.connectEventSource();
}
});
this.eventSource.addEventListener('log', log => {
this.lastEventSourceEventDate = new Date();
this.onLog(log);
});
this.eventSource.addEventListener('state', state => {
this.lastEventSourceEventDate = new Date();
this.onStateUpdate(state);
});
this.eventSource.addEventListener('ping', ping => {
this.lastEventSourceEventDate = new Date();
this.onPing(ping);
});
}
if (!this.idleCheckInterval) {
this.idleCheckInterval = setInterval(() => this.checkIdleTooLong(), ONE_SECOND_IN_MS);
}
}
checkIdleTooLong() {
if (this.lastEventSourceEventDate &&
this.lastEventSourceEventDate.valueOf() < Date.now() - this.maxIdleBeforeReconnect) {
this.close();
this.connectEventSource();
}
}
close() {
if (this.eventSource) {
clearInterval(this.idleCheckInterval);
this.idleCheckInterval = undefined;
this.eventSource.close();
this.eventSource = undefined;
this.lastEventSourceEventDate = undefined;
}
}
}
//# sourceMappingURL=eventsource.js.map