homebridge-econet-rheem
Version:
Homebridge plugin for control of Rheem and Ruud thermostats and water heaters
89 lines • 3.31 kB
JavaScript
import crypto from 'crypto';
import storage from 'node-persist';
import { Mutex } from './mutex.js';
import { PLATFORM_NAME } from '../homebridge/settings.js';
const VERSION = 2;
const STORAGE_KEY = `${PLATFORM_NAME}_V${VERSION}`;
const PROPERTIES = new Map();
const MUTEX = new Mutex();
export class Properties {
static async initStorage(persistPath) {
await storage.init({ dir: persistPath, forgiveParseErrors: true });
const storageJson = await storage.get(STORAGE_KEY);
if (storageJson === undefined) {
Properties.save();
return;
}
try {
const storageArray = JSON.parse(storageJson);
for (const [identifier, itemsArray] of storageArray) {
const itemsMap = new Map(itemsArray);
PROPERTIES.set(identifier, itemsMap);
}
}
catch {
// ignore
}
}
static get(identifier, key, encryptionKey) {
let value = PROPERTIES.get(identifier)?.get(key);
if (value !== undefined && encryptionKey !== undefined && typeof value === 'string') {
value = Properties.decrypt(value, encryptionKey);
}
return value;
}
static async set(identifier, key, item, encryptionKey) {
if (encryptionKey !== undefined && typeof item === 'string') {
item = Properties.encrypt(item, encryptionKey);
}
const items = PROPERTIES.get(identifier) || new Map();
if (items.get(key) === item) {
return;
}
if (item !== undefined) {
items.set(key, item);
}
else {
items.delete(key);
}
PROPERTIES.set(identifier, items);
Properties.save();
}
static async save() {
await MUTEX.lock(async () => {
await Properties._save();
});
}
static async _save() {
const storageArray = Array.from(PROPERTIES.entries()).map(([key, value]) => {
return [key, Array.from(value.entries())];
});
const storageJson = JSON.stringify(storageArray);
await storage.set(STORAGE_KEY, storageJson);
}
static digest(encryptionKey) {
return crypto.createHash('sha256').update(encryptionKey).digest();
}
static encrypt(serialized, encryptionKey) {
const digest = Properties.digest(encryptionKey);
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-cbc', digest, iv);
const encrypted = Buffer.concat([cipher.update(serialized, 'utf8'), cipher.final()]);
return iv.toString('hex') + ':' + encrypted.toString('hex');
}
static decrypt(final, encryptionKey) {
try {
const digest = Properties.digest(encryptionKey);
const [ivHex, encryptedHex] = final.split(':');
const iv = Buffer.from(ivHex, 'hex');
const encrypted = Buffer.from(encryptedHex, 'hex');
const decipher = crypto.createDecipheriv('aes-256-cbc', digest, iv);
const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]).toString('utf8');
return decrypted;
}
catch {
// nothing
}
}
}
//# sourceMappingURL=properties.js.map