import logging import threading from typing import Optional from time import sleep from ..util import stringify, send_datagram, Addr from pyA20.gpio import gpio from pyA20.gpio import port as gpioport logger = logging.getLogger(__name__) class SoundSensorNode: def __init__(self, name: str, pinname: str, server_addr: Optional[Addr], threshold: int = 1, delay=0.005): if not hasattr(gpioport, pinname): raise ValueError(f'invalid pin {pinname}') self.pin = getattr(gpioport, pinname) self.name = name self.delay = delay self.threshold = threshold self.server_addr = server_addr self.hits = 0 self.hitlock = threading.Lock() self.interrupted = False def run(self): try: t = threading.Thread(target=self.sensor_reader) t.daemon = True t.start() while True: with self.hitlock: hits = self.hits self.hits = 0 if hits >= self.threshold: try: if self.server_addr is not None: send_datagram(stringify([self.name, hits]), self.server_addr) else: logger.debug(f'server reporting disabled, skipping reporting {hits} hits') except OSError as exc: logger.exception(exc) sleep(1) except (KeyboardInterrupt, SystemExit) as e: self.interrupted = True logger.info(str(e)) def sensor_reader(self): gpio.init() gpio.setcfg(self.pin, gpio.INPUT) gpio.pullup(self.pin, gpio.PULLUP) while not self.interrupted: state = gpio.input(self.pin) sleep(self.delay) if not state: with self.hitlock: logger.debug('got a hit') self.hits += 1