homebridge-lutron-caseta-leap-fast
Version:
Support for the Lutron Caseta Smart Bridge 2
104 lines • 5.01 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OccupancySensorRouter = void 0;
const debug_1 = __importDefault(require("debug"));
const util_1 = __importDefault(require("util"));
const logDebug = (0, debug_1.default)('leap:bridge');
class OccupancySensorRouter {
constructor() {
this.cbMap = new Map();
this.subMap = new Map();
this.stateMap = new Map();
}
makeKey(bridgeID, ocg) {
return bridgeID + '_' + ocg.href;
}
updateState(bridgeID, update) {
logDebug('update state');
logDebug(util_1.default.inspect(update, { depth: null }));
for (const grpStat of update.OccupancyGroupStatuses) {
const key = this.makeKey(bridgeID, grpStat.OccupancyGroup);
logDebug(`handling update for ${util_1.default.inspect(key, { depth: null })} to ${grpStat.OccupancyStatus}`);
this.stateMap.set(key, grpStat.OccupancyStatus);
}
}
callRegistered(bridgeID, update) {
for (const grpStat of update.OccupancyGroupStatuses) {
const key = this.makeKey(bridgeID, grpStat.OccupancyGroup);
logDebug(`calling cb for ${util_1.default.inspect(key, { depth: null })} to ${grpStat.OccupancyStatus}`);
const cb = this.cbMap.get(key);
if (cb) {
cb(grpStat.OccupancyStatus);
}
}
}
static getInstance() {
if (!OccupancySensorRouter.instance) {
OccupancySensorRouter.instance = new OccupancySensorRouter();
}
return OccupancySensorRouter.instance;
}
async subscribeToBridge(bridge) {
// Subscribe to occupancy updates for the provided bridge.
this.subMap.set(bridge.bridgeID, new Promise((resolve, reject) => {
// update state and call all registered callbacks when we get an update
const _handleOccupancyUpdate = (r) => {
logDebug('subscription cb called');
this.updateState(bridge.bridgeID, r.Body);
this.callRegistered(bridge.bridgeID, r.Body);
};
// we get a complete listing of occupancy groups and their
// statuses when we subscribe, so update our internal state
// while we've got the info handy
const _handleGlobalUpdate = (initial) => {
logDebug(`response from subscription call recd: ${util_1.default.inspect(initial, { depth: null })}`);
this.updateState(bridge.bridgeID, initial);
};
// subscribe to occupancy updates for this bridge, and...
bridge
.subscribeToOccupancy(_handleOccupancyUpdate.bind(this))
.then(_handleGlobalUpdate.bind(this))
// resolve the promise that we'll subscribe to the bridge
.then(() => resolve())
.catch((e) => reject(e));
// when the bridge is disconnected, subscriptions are lost. re-establish them.
bridge.on('disconnected', () => {
bridge.subscribeToOccupancy(_handleOccupancyUpdate.bind(this)).then(_handleGlobalUpdate.bind(this));
// WARNING: uncaught throw here will crash the program, but
// there's nothing to be done if re-subscribing fails.
// better to just blow it all up.
});
}));
}
async register(bridge, occupancyGroup, cb) {
// Register the specified bridge's occupancy group to have cb called
// when there's an update. This function will subscribe to the bridge if
// it hasn't already been done.
// Create the key used for looking into the three state maps we're about to use
const key = this.makeKey(bridge.bridgeID, occupancyGroup);
// If we're not already subscribed to this bridge's updates, let's do that.
if (!this.subMap.has(bridge.bridgeID)) {
logDebug(`bridge ${bridge.bridgeID} is a new bridge`);
this.subscribeToBridge(bridge);
}
await this.subMap.get(bridge.bridgeID);
// Store this registration's callback
this.cbMap.set(key, cb);
// get stored state information for the occupancygroup that's
// registering itself, and immediately call its callback to update it.
// n.b. that this may not be this bridge's first registration request,
// so the above nonsense about initial status might have happened on a
// prior registration, and is async anyway. that's why we look in the
// cache.
const state = this.stateMap.get(key);
if (state) {
logDebug(`calling callback for ${key}`);
cb(state);
}
}
}
exports.OccupancySensorRouter = OccupancySensorRouter;
//# sourceMappingURL=OccupancySensorRouter.js.map