Skip to content

Commit 4524e98

Browse files
committed
Add ability to average measurements in Redundancy Function
1 parent 2a489b4 commit 4524e98

File tree

2 files changed

+48
-13
lines changed

2 files changed

+48
-13
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This release introduces the ability to override MYCODO_DB_PATH, SQLALCHEMY_DATAB
1919

2020
- Add ability to use alternate mysql server using config_override.py
2121
- Add Output: PWM Raspberry Pi GPIO (RPi.GPIO) (for Pi <= 4, since pigpiod is deprecated)
22+
- Add ability to average measurements in Redundancy Function
2223

2324
### Miscellaneous
2425

mycodo/functions/redundancy.py

+47-13
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
'measurements_dict': measurements_dict,
4747
'enable_channel_unit_select': True,
4848

49-
'message': "This function stores the first available measurement. This is useful if you have multiple sensors that you want to serve as backups in case one stops working, you can set them up in the order of importance. This function will check if a measurement exits, starting with the first measurement. If it doesn't, the next is checked, until a measurement is found. Once a measurement is found, it is stored in the database with the user-set measurement and unit. The output of this function can be used as an input throughout Mycodo. If you need more than 3 measurements to be checked, you can string multiple Redundancy Functions by creating a second Function and setting the first Function's output as the second Function's input.",
49+
'message': "This function stores the first available measurement. This is useful if you have multiple sensors that you want to serve as backups in case one stops working, you can set them up in the order of importance. This function will check if a measurement exits, starting with the first measurement. If it doesn't, the next is checked, until a measurement is found. Once a measurement is found, it is stored in the database with the user-set measurement and unit. The output of this function can be used as an input throughout Mycodo. If you need more than 3 measurements to be checked, you can string multiple Redundancy Functions by creating a second Function and setting the first Function's output as the second Function's input. If Average Measurements is enabled, the output will be the average of any valid values that are available from the selected measurements.",
5050

5151
'options_enabled': [
5252
'measurements_select_measurement_unit',
@@ -63,6 +63,14 @@
6363
'name': "{} ({})".format(lazy_gettext('Period'), lazy_gettext('Seconds')),
6464
'phrase': lazy_gettext('The duration between measurements or actions')
6565
},
66+
{
67+
'id': 'average_measurements',
68+
'type': 'bool',
69+
'default_value': False,
70+
'required': True,
71+
'name': 'Average Measurements',
72+
'phrase': 'Store the average of multiple valid measurements'
73+
},
6674
{
6775
'id': 'select_measurement_a',
6876
'type': 'select_measurement',
@@ -137,6 +145,7 @@ def __init__(self, function, testing=False):
137145

138146
# Initialize custom options
139147
self.period = None
148+
self.average_measurements = None
140149
self.select_measurement_a_device_id = None
141150
self.select_measurement_a_measurement_id = None
142151
self.measurement_a_max_age = None
@@ -236,19 +245,44 @@ def loop(self):
236245
self.measurement_c_max_age))
237246

238247
if last_measurement_a or last_measurement_b or last_measurement_c:
239-
if last_measurement_a:
240-
self.logger.debug("Using Measurement A")
241-
measurement_store = last_measurement_a[1]
242-
elif last_measurement_b:
243-
self.logger.debug("Using Measurement B")
244-
measurement_store = last_measurement_b[1]
245-
elif last_measurement_c:
246-
self.logger.debug("Using Measurement C")
247-
measurement_store = last_measurement_c[1]
248+
if self.average_measurements:
249+
count = 0
250+
measurement_store = 0
251+
if last_measurement_a and len(last_measurement_a) == 2 and last_measurement_a[1] is not None:
252+
count += 1
253+
self.logger.debug(f"Using Measurement A: {last_measurement_a[1]}")
254+
measurement_store += last_measurement_a[1]
255+
if last_measurement_b and len(last_measurement_b) == 2 and last_measurement_b[1] is not None:
256+
count += 1
257+
self.logger.debug(f"Using Measurement B: {last_measurement_b[1]}")
258+
measurement_store += last_measurement_b[1]
259+
if last_measurement_c and len(last_measurement_c) == 2 and last_measurement_c[1] is not None:
260+
count += 1
261+
self.logger.debug(f"Using Measurement C: {last_measurement_c[1]}")
262+
measurement_store += last_measurement_c[1]
263+
264+
if count:
265+
self.logger.debug(
266+
f"Storing Measurement: {measurement_store} / {count} = {measurement_store / count}")
267+
measurement_store = measurement_store / count
268+
else:
269+
self.logger.debug(
270+
"Could not find a measurement in the specified time frames for Measurements A, B, or C")
271+
return
248272
else:
249-
self.logger.debug(
250-
"Could not find a measurement in the specified time frames for Measurements A, B, or C")
251-
return
273+
if last_measurement_a and len(last_measurement_a) == 2 and last_measurement_a[1] is not None:
274+
self.logger.debug(f"Using Measurement A: {last_measurement_a[1]}")
275+
measurement_store = last_measurement_a[1]
276+
elif last_measurement_b and len(last_measurement_b) == 2 and last_measurement_b[1] is not None:
277+
self.logger.debug(f"Using Measurement B: {last_measurement_b[1]}")
278+
measurement_store = last_measurement_b[1]
279+
elif last_measurement_c and len(last_measurement_c) == 2 and last_measurement_c[1] is not None:
280+
self.logger.debug(f"Using Measurement C: {last_measurement_c[1]}")
281+
measurement_store = last_measurement_c[1]
282+
else:
283+
self.logger.debug(
284+
"Could not find a measurement in the specified time frames for Measurements A, B, or C")
285+
return
252286

253287
write_influxdb_value(
254288
self.unique_id,

0 commit comments

Comments
 (0)