summaryrefslogtreecommitdiff
path: root/include/py/homekit/soundsensor/node.py
diff options
context:
space:
mode:
Diffstat (limited to 'include/py/homekit/soundsensor/node.py')
-rw-r--r--include/py/homekit/soundsensor/node.py75
1 files changed, 75 insertions, 0 deletions
diff --git a/include/py/homekit/soundsensor/node.py b/include/py/homekit/soundsensor/node.py
new file mode 100644
index 0000000..292452f
--- /dev/null
+++ b/include/py/homekit/soundsensor/node.py
@@ -0,0 +1,75 @@
+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