majordomo
majordomo copied to clipboard
Расширение getHistoryAvg возможностью интегрального рассчета среднего значения
Описание проблемы:
Исходная реализация getHistoryAvg
занимается простым подсчётом среднего значения всех сохраненных значений в запрашиваемом интервале. При таком подходе есть два проблемных сценария:
- Если данные поступают нерегулярно
- Если из-за встроенной в majordomo дедупликации данных, повторяющиеся значения не сохраняются в БД.
Пример:
На данном графике имеется свойство, в которое поступало нулевое значение до 3:34, а в 3:35 и далее начало поступать значение 10000.
Если вызвать
getHistoryAvg
для интервала 3:30 - 4:30, то базовая имплементация обнаружит в БД только два значения: 3:34 - 0, и 3:35 - 10000. Соответсвенно результат среднего будет 5000. Значение верно математически для сохранённых данных, но неверно в прикладном смысле: среднее потребление электроустановкой за прошедший час не равно 5000Вт, а близко к 9000Вт.
Решение:
Данный пуллреквест расширяет системную функцию getHistoryAvg дополнительным опциональным параметром integral
:
function getHistoryAvg($varname, $start_time, $stop_time = 0, $integral = false)
При передаче параметра integral: true
, функция находит значения для моментов времени start_time
и stop_time
методом интерполяции между ближайшими сохранёнными точками вокруг них, после чего рассчитывается среднее значение интегрированием методом трапеций.
Изменения обратно-совместимы, т.е. если не менять пользовательский код, то поведение не меняется.
Примеры использования:
Пример 1:
getHistoryAvg('OTest.power', strtotime('2024-01-27 03:30:00'), strtotime('2024-01-27 04:30:00'))
= 5000
getHistoryAvg('OTest.power', strtotime('2024-01-27 03:30:00'), strtotime('2024-01-27 04:30:00'), true)
= 9105
Пример 2:
getHistoryAvg('OTest.power', strtotime('2024-01-27 03:30:00'), strtotime('2024-01-27 03:40:00'))
= 5000
getHistoryAvg('OTest.power', strtotime('2024-01-27 03:30:00'), strtotime('2024-01-27 03:40:00'), true)
= 4633
Пример 3:
Когда данные поступают регулярно и без дублирующих значений, результаты одинаковы.
getHistoryAvg('OElectricity.gridValueIn', strtotime('2024-01-28 07:00:00'), strtotime('2024-01-28 08:00:00'))
= 301
getHistoryAvg('OElectricity.gridValueIn', strtotime('2024-01-28 07:00:00'), strtotime('2024-01-28 08:00:00'), true)
= 301
Пример 4:
Данные поступают регулярно, но некоторые дублирующие значения были не сохранены majordomo:
getHistoryAvg('OElectricity.gridValueIn', strtotime('2024-01-28 06:00:00'), strtotime('2024-01-28 07:00:00'))
= 314
getHistoryAvg('OElectricity.gridValueIn', strtotime('2024-01-28 06:00:00'), strtotime('2024-01-28 07:00:00'), true)
= 316
TODO: после мерджа, необходимо обновить документацию:
- https://mdminfo.ru/wiki/GetHistoryAvg
- https://kb.mjdm.ru/vstroennie-v-majordomo-funkcii/3
- https://mjdm.ru/forum/viewtopic.php?t=2997