From 42c5ca87bfd940d219dceb7ca8160f8ab3ccc4d3 Mon Sep 17 00:00:00 2001 From: Eugene Abramov Date: Fri, 13 May 2022 00:19:11 +0300 Subject: [PATCH] Change state object creation logic Also added object compare function `objectEquals` --- lib/utils.js | 34 +++++++++++++++++++++++++++++++++- main.js | 16 ++++++++++------ 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index ee5643d..128120b 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -41,10 +41,42 @@ function fetchHashOfString(string) { return string.split('').map(v=>v.charCodeAt(0)).reduce((a,v)=>a+((a<<7)+(a<<3))^v).toString(16); }; +/* */ +function objectEquals(x, y) { + 'use strict'; + + if (x === null || x === undefined || y === null || y === undefined) return x === y; + + // after this just checking type of one would be enough + if (x.constructor !== y.constructor) return false; + + // if they are functions, they should exactly refer to same one (because of closures) + if (x instanceof Function) return x === y; + + // if they are regexps, they should exactly refer to same one (it is hard to better equality check on current ES) + if (x instanceof RegExp) return x === y; + + if (x === y || x.valueOf() === y.valueOf()) return true; + if (Array.isArray(x) && x.length !== y.length) return false; + + // if they are dates, they must had equal valueOf + if (x instanceof Date) return false; + + // if they are strictly equal, they both need to be object at least + if (!(x instanceof Object)) return false; + if (!(y instanceof Object)) return false; + + // recursive object equality check + var p = Object.keys(x); + return Object.keys(y).every(i => p.indexOf(i) !== -1) && + p.every(i => objectEquals(x[i], y[i])); +} + /* */ module.exports = { sleep, reverseMac, decodeMiioJson, - fetchHashOfString + fetchHashOfString, + objectEquals }; \ No newline at end of file diff --git a/main.js b/main.js index 7d3fc08..f41abb3 100644 --- a/main.js +++ b/main.js @@ -12,7 +12,7 @@ const format = require('date-fns/format'); /* */ const yaml = require('js-yaml'); /* */ -const {fetchHashOfString} = require('./lib/utils'); +const {fetchHashOfString, objectEquals} = require('./lib/utils'); /* */ const {MiioHelper, Gateway3Helper} = require('./lib/helpers'); const XiaomiCloud = require('./lib/xiaomiCloud'); @@ -606,11 +606,15 @@ class XiaomiGateway3 extends utils.Adapter { } } - /* set state object */ - await this.setObjectAsync(_id, Object.assign({}, - {'_id': `${this.namespace}.${_id}`}, - stateObject - )); + /* set state object if it is not exist or `custom` changed */ + if (_stateObject == undefined + || !objectEquals(stateObject.common.custom[this.namespace], _stateObject.common.custom[this.namespace]) + ) { + await this.setObjectAsync(_id, Object.assign({}, + {'_id': `${this.namespace}.${_id}`}, + stateObject + )); + } /* set init state value if it is exist */ const val = init[stateName];