class DataToTbHandler { constructor(index) { this.index = index; // time, after new value for the given key will be resend to tb (e.g. {status: "OK"}) this.timeToHoldTbValue = 30 * 60; //30 minutes this.previousValues = {}; this.debug = false; this.messageCounter = 0; this.itIsNodeReadout = false; this.sender = ""; // if attribute change difference is less than limit value, we do not send to tb. this.attributeChangeLimit = { temperature: 0.5, Phase_1_voltage: 2, Phase_2_voltage: 2, Phase_3_voltage: 2, Phase_1_current: 0.1, Phase_2_current: 0.1, Phase_3_current: 0.1, Phase_1_power: 2, Phase_2_power: 2, Phase_3_power: 2, total_power: 2, total_energy: 1, Phase_1_pow_factor: 0.1, Phase_2_pow_factor: 0.1, Phase_3_pow_factor: 0.1, power_factor: 0.1, lifetime: 2, voltage: 2, power: 2, frequency: 3, energy: 0.1, current: 2, inclination_x: 10, inclination_y: 10, inclination_z: 10 }; } dump() { console.log("----------------------------"); console.log("previousValues", this.previousValues); console.log("----------------------------"); } setSender(sender) { this.sender = sender; } isEmptyObject(obj) { for (var _ in obj) { return false; } return true; } sendToTb(data, instance) { //not to modify data object, we do deep copy: let dataCopy = JSON.parse(JSON.stringify(data)); let keys = Object.keys(dataCopy); if (keys.length == 0) { if (this.debug) console.log("sendToTb received empty object", dataCopy); return; } let tbname = keys[0]; let ts; let arrayOfValues = dataCopy[tbname]; let arrayOfValuesToSend = []; for (let i = 0; i < arrayOfValues.length; i++) { ts = arrayOfValues[i].ts; let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); if (!this.isEmptyObject(values)) { arrayOfValuesToSend.push({ ts: ts, values: values }); } } if (arrayOfValuesToSend.length == 0) { //if(this.debug) console.log("data not sent - empty array"); return; } this.messageCounter++; let dataToTbModified = { [tbname]: arrayOfValuesToSend } //console.log(this.sender + " DATA SEND TO TB ", tbname, this.messageCounter, new Date(ts), dataToTbModified[tbname][0].values, this.instance); //if(this.debug) console.log(this.sender + " DATA SEND TO TB ", this.index, tbname, arrayOfValuesToSend); instance.send(this.index, dataToTbModified); } getDiffTimestamp(key) { //TODO set different value for given key!!! //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h return this.timeToHoldTbValue * 1000; } prepareValuesForTb(tbname, timestamp, values) { let keys = Object.keys(values); if (keys.includes("lifetime")) this.itIsNodeReadout = true; if (!this.previousValues.hasOwnProperty(tbname)) { this.previousValues[tbname] = {}; } //if(this.debug) console.log("prepareValuesForTb", tbname, timestamp, values); for (let i = 0; i < keys.length; i++) { let key = keys[i]; let value = values[key]; if (!this.previousValues[tbname].hasOwnProperty(key)) { this.previousValues[tbname][key] = { ts: timestamp, value: value }; continue; } // attributeData ==> {voltage: {ts:333333, value:5}} let attributeData = this.previousValues[tbname][key]; let attributeToChange = false; if (key in this.attributeChangeLimit) attributeToChange = true; let limit = this.attributeChangeLimit[key]; let timestampDiffToRemoveKey; //this will ensure "node statecode" will be sent just once an hour if (this.itIsNodeReadout && key === "statecode") { attributeData.value = value; this.itIsNodeReadout = false; timestampDiffToRemoveKey = 1 * 60 * 60 * 1000; // 1 hour } if (key === "twilight_sensor" && value > 100) { attributeData.value = value; } //if edge, master or node version do not change, send just once a day: if (["edge_fw_version", "master_node_version", "fw_version"].includes(key)) { timestampDiffToRemoveKey = 24 * 60 * 60 * 1000; } if (attributeData.value === value || attributeToChange && Math.abs(attributeData.value - value) < limit) { let diff = timestamp - attributeData.ts; if (!timestampDiffToRemoveKey) timestampDiffToRemoveKey = this.getDiffTimestamp(key); if (diff > timestampDiffToRemoveKey) { attributeData.ts = Date.now(); //if(this.debug) console.log(this.sender + ": update ts for key", key, "diff is", diff, "messageCounter", this.messageCounter); } else { delete values[key]; //if(this.debug) console.log(this.sender + ": delete key", key, "diff is", diff, "messageCounter", this.messageCounter, timestampDiffToRemoveKey); } } else { attributeData.value = value; attributeData.ts = timestamp; } } return values; } } module.exports = DataToTbHandler;