From 572aad546bb8ee9ccd095a2098e1b292176c53da Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sat, 8 Apr 2017 16:16:51 -0400 Subject: re-implement polling using "devicer" library --- dexcom_reader/devicer.py | 72 ++++++++++++++++++++++++++++++++++++++++++ dexcom_reader/dexcom_dumper.py | 61 ++++++++++++++++++++++++++++++++++- 2 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 dexcom_reader/devicer.py diff --git a/dexcom_reader/devicer.py b/dexcom_reader/devicer.py new file mode 100644 index 0000000..79a0a72 --- /dev/null +++ b/dexcom_reader/devicer.py @@ -0,0 +1,72 @@ +import pyudev +import threading + +class DevicePoller: + def __init__(self, dev): + self.device_added = threading.Event() + self.device_removed = threading.Event() + self.device = dev + self.wait_add = self.device_added.wait + self.wait_remove = self.device_removed.wait + self.have = self.device_added.is_set + + if dev: + self.device_added.set() + + def launch_observer(self, monitor, device_match): + + if not monitor: + monitor = pyudev.Monitor.from_netlink(pyudev.Context()) + + def handle_event(action, device): + if action == 'add' and device_match(device): + self.device = device + self.device_removed.clear() + self.device_added.set() + elif action == 'remove' and device == self.device: + self.device = None + self.device_added.clear() + self.device_removed.set() + + self.observer = pyudev.MonitorObserver(monitor, handle_event) + self.observer.start() + + def stop_observer(): + self.observer.stop() + +def simple_devicer(subsystem, predicate): + dev = None + context = pyudev.Context() + for try_dev in context.list_devices(subsystem=subsystem): + if predicate(try_dev): + dev = try_dev + break + + monitor = pyudev.Monitor.from_netlink(context) + monitor.filter_by(subsystem) + + devicer = DevicePoller(dev) + devicer.launch_observer(monitor, predicate) + + return devicer + +if __name__ == '__main__': + + dexcom_g5_product = '22a3/47/100' + + def is_dexcom_g5(dev): + try: return dev.parent.get('PRODUCT') == dexcom_g5_product + except: return False + + devicer = simple_devicer('tty', is_dexcom_g5) + + while True: + print("waiting for device") + devicer.wait_add() + while devicer.have(): + print("poll device {0}".format(devicer.device)) + print("sleep(5)") + if devicer.wait_remove(5): + print("device removed") + + devicer.stop_observer() diff --git a/dexcom_reader/dexcom_dumper.py b/dexcom_reader/dexcom_dumper.py index be5b0d8..e7db00e 100755 --- a/dexcom_reader/dexcom_dumper.py +++ b/dexcom_reader/dexcom_dumper.py @@ -4,6 +4,7 @@ import readdata import sys import json import traceback +from devicer import simple_devicer # import requests # As this takes SEVEN SECONDS, it's delayed until needed from sys import stdout, stderr from datetime import timedelta, datetime @@ -206,6 +207,64 @@ def poll_remote(): else: sleep_verbose(10) +def poll_remote_redux(): + (n, r) = remote_update('EGV_DATA') + if n is None: + return 10 + else: + now = dr.ReadSystemTime() + if n == 0: + send_ping(now) + if r: + for t in ['METER_DATA', 'INSERTION_TIME', 'USER_EVENT_DATA']: + # TODO: track how long this takes & adjust sleep accordingly + try: + remote_update(t) + except: + traceback.print_exc() + next_reading = (r.system_time - now + timedelta(minutes=5, seconds=2)).total_seconds() + return max(10, next_reading) + else: + return 10 + +def poll_redux(): + poll = poll_remote_redux + + dexcom_g5_product = '22a3/47/100' + + def is_dexcom_g5(dev): + try: return dev.parent.get('PRODUCT') == dexcom_g5_product + except: return False + + devicer = simple_devicer('tty', is_dexcom_g5) + + while True: + try: + print_verbose("Waiting for device.") + if not devicer.wait_add(600): + continue + print_verbose("Device found.") + + global dr + if dr: + dr.Disconnect() + dr = readdata.DexcomG5(devicer.device.device_node) + + print("Device opened.") + while devicer.have(): + print_verbose("Polling device.") + try: + sleeptime = poll() + except: + sleeptime = 10 + + if devicer.wait_remove(sleeptime): + print_verbose("Device unplugged.") + dr.Disconnect() + dr = None + except KeyboardInterrupt: + break + def poll_stdout(): (r, now) = read_recent_egv_data() connected(True) @@ -343,5 +402,5 @@ def toJSON(o): {"dump_everything": dump_everything, "dump_cgm": dump_cgm, "poll": poll, - "test": test, + "test": poll_redux, }[command]() -- cgit v1.2.3