node-red-contrib-smartnora
Version:
Google Smart Home integration via Smart Nora https://smart-nora.eu/
113 lines (112 loc) • 4.32 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSafeUpdate = getSafeUpdate;
const skipRoundingStatePaths = new Set([
'color.spectrumHsv.hue',
'color.spectrumHsv.saturation',
'color.spectrumHsv.value',
]);
const roundTo = new Map([
['thermostatHumidityAmbient', 1],
['humidityAmbientPercent', 1],
['currentFanSpeedPercent', 1],
]);
const keepPathsIfSameValue = [
/^openState\.\d+\.openDirection$/,
/^currentSensorStateData\.\d+\.name$/,
/^(?:capacityRemaining|capacityUntilFull)\..*$/,
];
const arrayItemKeyMap = new Map([
['openState', 'openDirection'],
['currentSensorStateData', 'name'],
]);
function getSafeUpdate({ update, currentState, safeUpdateObject, isValid, mapping, path = 'msg.payload.', statePath, warn, }) {
var _a, _b, _c;
for (const [key, v] of Object.entries(update)) {
if (typeof key !== 'string') {
continue;
}
if (typeof v === 'undefined') {
continue;
}
let updateValue = v;
const updateKey = (_b = (_a = mapping === null || mapping === void 0 ? void 0 : mapping.find(m => m.from === key)) === null || _a === void 0 ? void 0 : _a.to) !== null && _b !== void 0 ? _b : key;
const currentStatePath = statePath ? `${statePath}.${String(updateKey)}` : String(updateKey);
let previousValue;
const keyName = statePath && arrayItemKeyMap.get(statePath);
if (keyName && Array.isArray(currentState)) {
const keyValue = v[keyName];
previousValue = currentState.find(pv => pv[keyName] === keyValue);
if (!previousValue) {
warn === null || warn === void 0 ? void 0 : warn(`${path}${key}.${keyName}[${keyValue}]`);
continue;
}
}
else {
previousValue = currentState[updateKey];
}
if (typeof previousValue !== typeof updateValue) {
if (typeof previousValue === 'number') {
updateValue = +updateValue;
}
if (typeof previousValue === 'boolean') {
updateValue = !!updateValue;
}
}
if (typeof updateValue === 'number') {
const skipRoundingNumbers = skipRoundingStatePaths.has(currentStatePath);
if (!skipRoundingNumbers) {
const roundToDigits = (_c = roundTo.get(currentStatePath)) !== null && _c !== void 0 ? _c : 10;
updateValue = Math.round(updateValue * roundToDigits) / roundToDigits;
}
}
if (typeof updateValue === 'object' && typeof previousValue === 'object') {
const updateChild = Array.isArray(updateValue) ? [] : {};
const remove = append(safeUpdateObject, updateKey, updateChild);
getSafeUpdate({
update: updateValue,
currentState: previousValue,
safeUpdateObject: updateChild,
isValid,
mapping,
path: `${path}${key}.`,
statePath: currentStatePath,
warn,
});
remove();
updateValue = updateChild;
}
const skipRemove = keepPathsIfSameValue.some(t => t.test(currentStatePath));
if (!skipRemove && updateValue === previousValue) {
updateValue = undefined;
}
if (statePath && updateValue && arrayItemKeyMap.has(statePath) && Object.keys(updateValue).length === 1) {
updateValue = undefined;
}
if (Array.isArray(updateValue) && updateValue.length === 0) {
updateValue = undefined;
}
if (updateValue !== undefined) {
const remove = append(safeUpdateObject, updateKey, updateValue);
if (!isValid()) {
remove();
warn === null || warn === void 0 ? void 0 : warn(`${path}${key}`);
}
}
}
}
function append(parent, key, child) {
if (Array.isArray(parent)) {
parent.push(child);
return () => {
const index = parent.indexOf(child);
parent.splice(index, 1);
};
}
else {
parent[key] = child;
return () => {
delete parent[key];
};
}
}