181 lines
5.2 KiB
Python
181 lines
5.2 KiB
Python
'''
|
|
Devices
|
|
|
|
Created on 23 août 2022
|
|
|
|
@author: denis@e-educ.fr
|
|
|
|
Flow and Frequency output of the YF-S201
|
|
|
|
Flow(L/H) Frequency(Hz)
|
|
120 16
|
|
240 32.5
|
|
360 49.3
|
|
480 65.5
|
|
600 82
|
|
720 90.2
|
|
|
|
F = 7.5 Q Q: l/mn
|
|
'''
|
|
import logging, threading, random
|
|
from modules import sensors as dev, utils, gpiolib as gpio
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
logging.basicConfig(level=logging.INFO)
|
|
|
|
|
|
class YF_S201(dev.InputDevice):
|
|
waterflow_timeout = 2
|
|
pulse_counter = 0
|
|
start_counter = False
|
|
stop_counter = None
|
|
|
|
def __init__(self, pin, register=None, publish=None):
|
|
super().__init__(pin, register=register, callback=self.on_count_pulse, pull_up_down=gpio.IO_PULL_UP,)
|
|
self.publish = publish
|
|
threading.Thread(target=self.waterflow_process, args=()).start()
|
|
|
|
def waterflow_publish(self, flow=None):
|
|
if self.publish is not None:
|
|
self.publish(dict(
|
|
uuid=self.key,
|
|
topic="waterflow",
|
|
ts=utils.ts_now(),
|
|
flow=flow,
|
|
)
|
|
)
|
|
|
|
def on_count_pulse(self, channel):
|
|
if self.start_counter:
|
|
self.pulse_counter += 1
|
|
|
|
def wait_for_counts(self, timeout):
|
|
self.pulse_counter = 0
|
|
self.start_counter = True
|
|
threading.Event().wait(timeout)
|
|
self.start_counter = False
|
|
|
|
def waterflow_process(self):
|
|
self.stop_counter = threading.Event()
|
|
while not self.stop_counter.is_set():
|
|
self.wait_for_counts(self.waterflow_timeout)
|
|
flow = self.pulse_counter / 7.5
|
|
if flow:
|
|
logger.info(f'\nwaterflow_process flow = {flow}')
|
|
self.waterflow_publish(flow)
|
|
|
|
def stop(self):
|
|
self.stop_counter.set()
|
|
|
|
|
|
class Relay(dev.RelayFromShiftOut):
|
|
|
|
def __init__(self, shift_out_register, register=None, publish=None):
|
|
super().__init__(shift_out_register, register, relay_timeout=1.0)
|
|
self.publish = publish
|
|
self.start_time, self.end_time = 0, 0
|
|
self.started = False
|
|
self.duration_timer = threading.Event()
|
|
self.water_flow_timer = threading.Event()
|
|
|
|
self.flow, self.rate = 0.00, 0.00
|
|
self.flow_meter_start()
|
|
self.relay_publish('init', index=self.index, label=self.label, dev_type=self.dev_type)
|
|
|
|
def now(self):
|
|
return utils.ts_now_s()
|
|
|
|
def relay_publish(self, topic, **kwargs):
|
|
if self.publish is not None:
|
|
self.publish(topic, **dict(
|
|
uuid=self.key,
|
|
ts=utils.ts_now_s(),
|
|
relay_state=self.is_on(),
|
|
elapsed=self.time_elapsed(),
|
|
remaining=self.time_remaining(),
|
|
flow=self.flow,
|
|
rate=self.rate,
|
|
**kwargs
|
|
)
|
|
)
|
|
|
|
def time_elapsed(self):
|
|
elapsed = self.now() - self.start_time
|
|
if self.start_time <= 0 or elapsed <= 0:
|
|
elapsed = 0
|
|
return elapsed
|
|
|
|
def time_remaining(self):
|
|
remaining = self.end_time - self.now()
|
|
if remaining < 0:
|
|
remaining = 0
|
|
return remaining
|
|
|
|
def is_it_over(self, timeout):
|
|
elapsed = self.now() - self.start_time
|
|
if elapsed > timeout:
|
|
self.duration_timer.set()
|
|
|
|
def _open(self, timeout):
|
|
self.duration_timer = threading.Event()
|
|
self.started = True
|
|
while not self.duration_timer.is_set():
|
|
try:
|
|
if self.started:
|
|
self.is_it_over(timeout)
|
|
threading.Event().wait(1.0)
|
|
except Exception as e:
|
|
logger.error(f'run error {e}')
|
|
self.start_time = 0
|
|
self.relay_stop()
|
|
|
|
def relay_start(self, duration=0):
|
|
self.start_time = self.now()
|
|
self.end_time = self.start_time + duration
|
|
self.open()
|
|
if duration > 0:
|
|
threading.Thread(target=self._open, args=(duration, )).start()
|
|
self.rate, self.flow = 0.00, 0.00
|
|
self.begin = self.now()
|
|
self.water_flow_timer.set()
|
|
self.relay_publish('start')
|
|
|
|
def relay_stop(self):
|
|
self.duration_timer.set()
|
|
self.close()
|
|
self.started = False
|
|
self.water_flow_timer.clear()
|
|
self.relay_publish('stop')
|
|
|
|
def relay_halt(self):
|
|
if self.is_on():
|
|
self.started = False
|
|
|
|
def relay_restart(self):
|
|
if self.is_on():
|
|
self.started = True
|
|
|
|
def relay_status(self):
|
|
self.relay_publish('status')
|
|
|
|
def _flow_meter(self):
|
|
while True:
|
|
try:
|
|
self.water_flow_timer.wait()
|
|
elapsed = (self.now() - self.begin)/60
|
|
self.flow = random.randint(1050, 1065)/100 * elapsed
|
|
self.rate = self.flow / elapsed if elapsed > 0 else 0.00
|
|
threading.Event().wait(1.0)
|
|
except Exception as e:
|
|
logger.error(f'flow_meter_process error {e}')
|
|
threading.Event().wait(1.0)
|
|
|
|
def flow_meter_start(self):
|
|
self.begin = self.now()
|
|
threading.Thread(target=self._flow_meter).start()
|
|
|
|
|
|
|
|
|