Last active
November 9, 2021 14:52
-
-
Save prohazko2/16e36d200e8fd458fe649d4a95a4855d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const DAY_START = [0, 0, 0, 0]; | |
const DAY_END = [23, 59, 59, 999]; | |
const TZ_OFFSET = 3 * 60 * 60 * 1000; | |
const INIT_WITH = 230; | |
const TICK_VALUE = 10; | |
function startOfMinute(date) { | |
date = new Date(date || Date.now()); | |
date.setSeconds(0); | |
return date; | |
} | |
function startOfHour(date) { | |
const start = DAY_START.concat([]); | |
date = new Date(date || Date.now()); | |
start[0] = date.getHours(); | |
date.setHours(...start); | |
return date; | |
} | |
function startOfDay(date) { | |
date = new Date(date || Date.now()); | |
date.setHours(...DAY_START); | |
return date; | |
} | |
function startOfMonth(date) { | |
date = new Date(date || Date.now()); | |
date = new Date(date.getFullYear(), date.getMonth(), 1); | |
return startOfDay(date); | |
} | |
function endOfMinute(date) { | |
date = new Date(date || Date.now()); | |
date.setSeconds(59, 999); | |
return date; | |
} | |
function endOfHour(date) { | |
const end = DAY_END.concat([]); | |
date = new Date(date || Date.now()); | |
end[0] = date.getHours(); | |
date.setHours(...end); | |
return date; | |
} | |
function endOfDay(date) { | |
date = new Date(date || Date.now()); | |
date.setHours(...DAY_END); | |
return date; | |
} | |
function endOfMonth(date) { | |
date = new Date(date || Date.now()); | |
date = new Date(date.getFullYear(), date.getMonth() + 1, 0); | |
return endOfDay(date); | |
} | |
class Period { | |
constructor(name, base = new Date(), baseValue = 0, currentValue = 0) { | |
this.name = name; | |
this.baseDate = new Date(+base); | |
const { from, to } = this.at(this.baseDate); | |
this.from = new Date(from); | |
this.to = new Date(to); | |
this.baseValue = baseValue; | |
this.currentValue = baseValue || currentValue; | |
} | |
at(date = new Date()) { | |
switch (this.name) { | |
case "month": | |
return { | |
from: new Date(startOfMonth(date) - TZ_OFFSET), | |
to: new Date(endOfMonth(date) - TZ_OFFSET), | |
}; | |
case "day": | |
return { | |
from: new Date(startOfDay(date) - TZ_OFFSET), | |
to: new Date(endOfDay(date) - TZ_OFFSET), | |
}; | |
case "hour": | |
return { | |
from: startOfHour(+date), | |
to: endOfHour(+date), | |
}; | |
case "minute": | |
return { | |
from: startOfMinute(+date), | |
to: endOfMinute(+date), | |
}; | |
} | |
} | |
contains(date) { | |
date = new Date(date || Date.now()); | |
return +this.from <= +date && +date <= +this.to; | |
} | |
get value() { | |
return this.currentValue - this.baseValue; | |
} | |
toJSON() { | |
return { | |
name: this.name, | |
baseDate: +this.baseDate, | |
baseValue: this.baseValue, | |
currentValue: this.currentValue, | |
value: this.value, | |
from: +this.from, | |
to: +this.to, | |
}; | |
} | |
} | |
const PERIODS = [ | |
new Period("month"), | |
new Period("day"), | |
new Period("hour"), | |
new Period("minute"), | |
]; | |
function process(tick) { | |
if (!tick) { | |
return {}; | |
} | |
const stored = ric.localStore.forObject.get() || {}; | |
if (!stored.counter) { | |
stored.counter = INIT_WITH; | |
} | |
stored.counter += 1; | |
stored.value = stored.counter * TICK_VALUE; | |
const now = new Date(); | |
for (const p of PERIODS) { | |
const current = new Period(p.name, now, stored.value); | |
let prev = current; | |
if (stored[p.name]) { | |
prev = new Period( | |
stored[p.name].name, | |
stored[p.name].baseDate, | |
stored[p.name].baseValue, | |
stored[p.name].currentValue | |
); | |
if (prev.contains(now)) { | |
current.baseValue = prev.baseValue; | |
} | |
} | |
stored[p.name] = current; | |
} | |
ric.localStore.forObject.set(stored); | |
return { | |
counter: stored.counter, | |
value: stored.value, | |
month: stored.month, | |
day: stored.day, | |
hour: stored.hour, | |
minute: stored.minute, | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"id": "root", | |
"name": "m-01", | |
"base": "mqtt", | |
"active": true, | |
"type": "subsystem", | |
"children": [ | |
{ | |
"id": "external-software-modules", | |
"active": true, | |
"copy": true, | |
"type": "subsystem", | |
"children": [] | |
}, | |
{ | |
"id": "params", | |
"name": "Params", | |
"active": true, | |
"type": "subsystem", | |
"children": [ | |
{ | |
"id": "server-info", | |
"name": "Server information", | |
"active": true, | |
"type": "subsystem", | |
"children": [ | |
{ | |
"id": "online", | |
"name": "Online", | |
"active": true, | |
"type": "argument", | |
"dataType": "boolean", | |
"reference": "online" | |
}, | |
{ | |
"id": "_ts", | |
"name": "Time", | |
"active": true, | |
"type": "argument", | |
"dataType": "number", | |
"unit": "duration-microsecond", | |
"reference": "_ts" | |
} | |
] | |
}, | |
{ | |
"id": "_counter", | |
"name": "i18n:object_current_state", | |
"active": true, | |
"type": "subsystem", | |
"children": [ | |
{ | |
"id": "tick", | |
"name": "tick", | |
"active": true, | |
"type": "argument", | |
"dataType": "number", | |
"linear": true, | |
"reference": "tick" | |
}, | |
{ | |
"id": "counter", | |
"name": "counter", | |
"active": true, | |
"type": "argument", | |
"dataType": "number", | |
"linear": true | |
}, | |
{ | |
"id": "value", | |
"name": "value", | |
"active": true, | |
"type": "argument", | |
"dataType": "number", | |
"linear": true, | |
"unit": "volume-liter" | |
} | |
] | |
}, | |
{ | |
"id": "_month", | |
"name": "i18n:month", | |
"active": true, | |
"type": "subsystem", | |
"children": [ | |
{ | |
"id": "month.from", | |
"name": "i18n:begin", | |
"active": true, | |
"type": "argument", | |
"dataType": "number", | |
"unit": "duration-millisecond" | |
}, | |
{ | |
"id": "month.to", | |
"name": "i18n:end", | |
"active": true, | |
"type": "argument", | |
"dataType": "number", | |
"unit": "duration-millisecond", | |
"children": [] | |
}, | |
{ | |
"id": "month.value", | |
"name": "i18n:now", | |
"active": true, | |
"type": "argument", | |
"dataType": "number", | |
"unit": "volume-liter" | |
} | |
] | |
}, | |
{ | |
"id": "_day", | |
"name": "i18n:day", | |
"active": true, | |
"type": "subsystem", | |
"children": [ | |
{ | |
"id": "day.from", | |
"name": "i18n:begin", | |
"active": true, | |
"type": "argument", | |
"dataType": "number", | |
"unit": "duration-millisecond" | |
}, | |
{ | |
"id": "day.to", | |
"name": "i18n:end", | |
"active": true, | |
"type": "argument", | |
"dataType": "number", | |
"unit": "duration-millisecond" | |
}, | |
{ | |
"id": "day.value", | |
"name": "i18n:now", | |
"active": true, | |
"type": "argument", | |
"dataType": "number", | |
"unit": "volume-liter" | |
} | |
] | |
}, | |
{ | |
"id": "_hour", | |
"name": "i18n:hour", | |
"active": true, | |
"type": "subsystem", | |
"children": [ | |
{ | |
"id": "hour.from", | |
"name": "i18n:begin", | |
"active": true, | |
"type": "argument", | |
"dataType": "number", | |
"unit": "duration-millisecond" | |
}, | |
{ | |
"id": "hour.to", | |
"name": "i18n:end", | |
"active": true, | |
"type": "argument", | |
"dataType": "number", | |
"unit": "duration-millisecond" | |
}, | |
{ | |
"id": "hour.value", | |
"name": "i18n:now", | |
"active": true, | |
"type": "argument", | |
"dataType": "number", | |
"unit": "volume-liter" | |
} | |
] | |
}, | |
{ | |
"id": "_minute", | |
"name": "i18n:minute", | |
"active": true, | |
"type": "subsystem", | |
"children": [ | |
{ | |
"id": "minute.from", | |
"name": "i18n:begin", | |
"active": true, | |
"type": "argument", | |
"dataType": "number", | |
"unit": "duration-millisecond" | |
}, | |
{ | |
"id": "minute.to", | |
"name": "i18n:end", | |
"active": true, | |
"type": "argument", | |
"dataType": "number", | |
"unit": "duration-millisecond" | |
}, | |
{ | |
"id": "minute.value", | |
"name": "i18n:now", | |
"active": true, | |
"type": "argument", | |
"dataType": "number", | |
"unit": "volume-liter" | |
} | |
] | |
}, | |
{ | |
"id": "mqtt-last", | |
"name": "Last MQTT Publish", | |
"active": true, | |
"type": "subsystem", | |
"children": [ | |
{ | |
"id": "topic", | |
"name": "Topic", | |
"active": true, | |
"type": "argument", | |
"source": "state", | |
"dataType": "string", | |
"reference": "topic" | |
}, | |
{ | |
"id": "payload", | |
"name": "Payload", | |
"active": true, | |
"type": "argument", | |
"source": "state", | |
"dataType": "string", | |
"reference": "payload" | |
} | |
] | |
} | |
] | |
} | |
] | |
} |
Author
prohazko2
commented
Nov 9, 2021
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment