Ejemplo n.º 1
0
async def do_usec(minutes):
    global gps
    tick = Message()
    print('Setting up GPS.')
    await us_setup(tick)
    print('Waiting for time data.')
    await gps.ready()
    max_us = 0
    min_us = 0
    sd = 0
    nsamples = 0
    count = 0
    terminate = Event()
    asyncio.create_task(killer(terminate, minutes))
    while not terminate.is_set():
        await tick
        usecs = tick.value()
        tick.clear()
        err = 1000000 - usecs
        count += 1
        print('Timing discrepancy is {:4d}μs {}'.format(
            err, '(skipped)' if count < 3 else ''))
        if count < 3:  # Discard 1st two samples from statistics
            continue  # as these can be unrepresentative
        max_us = max(max_us, err)
        min_us = min(min_us, err)
        sd += err * err
        nsamples += 1
    # SD: apply Bessel's correction for infinite population
    sd = int(math.sqrt(sd / (nsamples - 1)))
    print(
        'Timing discrepancy is: {:5d}μs max {:5d}μs min.  Standard deviation {:4d}μs'
        .format(max_us, min_us, sd))
Ejemplo n.º 2
0
class RunInThread(Thread):
    """
    """
    def __init__(self, action, *args, **kwargs):
        """Инициализация потока"""
        log.info("Init:")
        # print("Thread Init")
        Thread.__init__(self)
        self.result = None
        self.event = Event()
        self.action = action
        self._args = args
        self._kwargs = kwargs


    def run(self):
        """Запуск потока"""
        # print("Thread Act Run")
        log.info("Act Run")
        try:
            self.result = self.action(*self._args, **self._kwargs)
        except Exception as e:
            # print("Err: thread Act: {}".format(e))
            log.info("Act: ERROR {}".format(e))
            pass

        self.event.set()
        # print("Thread Act Done")
        log.info("Act: Done")
Ejemplo n.º 3
0
async def main():
    event = Event()
    asyncio.create_task(waiter(event))
    await asyncio.sleep(2)
    print('Setting event')
    event.set()
    await asyncio.sleep(1)
    # Caller can check if event has been cleared
    print('Event is {}'.format('set' if event.is_set() else 'clear'))
Ejemplo n.º 4
0
 def __init__(self, action, *args, **kwargs):
     """Инициализация потока"""
     log.info("Init:")
     # print("Thread Init")
     Thread.__init__(self)
     self.result = None
     self.event = Event()
     self.action = action
     self._args = args
     self._kwargs = kwargs
Ejemplo n.º 5
0
class Pending:
    def __init__(self):
        self._ev = Event()
        self._res = None

    async def get(self):
        await self._ev.wait()
        self._ev.clear()  # TODO: race condition?
        if isinstance(self._res, OSError):
            raise self._res
        else:
            return self._res

    def signal(self, result):
        self._res = result
        self._ev.set()
Ejemplo n.º 6
0
async def do_time(minutes):
    global gps
    fstr = '{}ms Time: {:02d}:{:02d}:{:02d}:{:06d}'
    print('Setting up GPS.')
    gps = await setup()
    print('Waiting for time data.')
    await gps.ready()
    print('Setting RTC.')
    await gps.set_rtc()
    print('RTC is set.')
    terminate = Event()
    asyncio.create_task(killer(terminate, minutes))
    while not terminate.is_set():
        await asyncio.sleep(1)
        # In a precision app, get the time list without allocation:
        t = gps.get_t_split()
        print(fstr.format(gps.get_ms(), t[0], t[1], t[2], t[3]))
Ejemplo n.º 7
0
async def do_drift(minutes):
    global gps
    print('Setting up GPS.')
    gps = await setup()
    print('Waiting for time data.')
    await gps.ready()
    print('Setting RTC.')
    await gps.set_rtc()
    print('Measuring drift.')
    terminate = Event()
    asyncio.create_task(killer(terminate, minutes))
    change = await drift_test(terminate, gps)
    ush = int(60 * change / minutes)
    spa = int(ush * 365 * 24 / 1000000)
    print('Rate of change {}μs/hr {}secs/year'.format(ush, spa))
Ejemplo n.º 8
0
class MQTTLog:
    _minlevel = ERROR
    _qmax = 1400
    _q = []
    _qlen = 0
    _ev = Event()

    @classmethod
    def init(cls, minlevel=ERROR, maxsize=1400):
        global _dup
        _dup = cls
        cls._minlevel = minlevel
        cls.resize(maxsize)

    @classmethod
    def resize(cls, maxsize):
        cls._qmax = maxsize
        # first try to eliminate messages below warning level
        i = 0
        while cls._qlen > maxsize and i < len(cls._q):
            if cls._q[i][0] < WARNING:
                cls._qlen -= len(cls._q[i][1])
                del cls._q[i]
            i += 1
        # if not there yet, eliminate other messages too
        while cls._qlen > maxsize:
            cls._qlen -= len(cls._q[0][1])
            del cls._q[0]

    @classmethod
    def log(cls, level, msg):
        if level < cls._minlevel:
            return
        if len(msg) > MAX_LINE:
            msg = msg[:MAX_LINE]
        ll = len(msg)
        cls._q.append((level, msg))
        cls._qlen += ll
        if cls._qlen > cls._qmax:
            cls.resize(cls._qmax)
        cls._ev.set()

    @classmethod
    async def push(cls, mqclient, topic):
        msg = cls._q[0][1]
        try:
            await mqclient.publish(topic, msg, qos=1, sync=False)
        except Exception as e:
            print("Exception", e)
            await sleep_ms(1000)
        cls._qlen -= len(msg)
        del cls._q[0]

    @classmethod
    async def run(cls, mqclient, topic):
        while True:
            while len(cls._q) > 0:
                await cls.push(mqclient, topic)
            cls._ev.clear()
            await cls._ev.wait()

    # connected is called when the first bropker connection is established, it flushes excess
    # saved messages while blocking further inits by other modules, then resizes the log storage,
    # and starts the regular runner/flusher
    @classmethod
    async def connected(cls, mqtt, config):
        topic = config["topic"]
        getLogger("main").info("Logging to %s", topic)
        # flush what we'd need cut due to resize
        maxsize = config.get("loop_sz", 1400)
        getLogger("main").info("Log buf: %d/%d bytes", cls._qlen, cls._qmax)
        while cls._qlen > maxsize*3//4:
            await cls.push(mqtt.client, topic)
        # re-init including resize
        MQTTLog.init(
            minlevel=config.get("loop_level", WARNING), maxsize=maxsize,
        )
        getLogger("main").info("Log buf: %d/%d bytes", cls._qlen, cls._qmax)
        # launch regular flusher
        loop.create_task(MQTTLog.run(mqtt.client, topic))
Ejemplo n.º 9
0
async def set_after_timeout(event: uasyncio.Event, timeout: float):
    await uasyncio.sleep(timeout)
    event.set()
Ejemplo n.º 10
0
 def __init__(self):
     self._ev = Event()
     self._res = None
Ejemplo n.º 11
0
class Screen:
    current_screen = None
    tft = None
    objtouch = None
    is_shutdown = Event()

    @classmethod
    def setup(cls, tft, objtouch=None):
        cls.objtouch = objtouch if objtouch is not None else tft
        cls.tft = tft

    @classmethod
    def _get_tft(cls, greyed_out=False):
        cls.tft.usegrey(greyed_out)
        return cls.tft

    @classmethod
    def set_grey_style(cls, *, desaturate=True, factor=2):
        cls.tft.dim(factor)
        cls.tft.desaturate(desaturate)
        if Screen.current_screen is not None: # Can call before instantiated
            for obj in Screen.current_screen.displaylist:
                if obj.visible and obj.greyed_out():
                    obj.redraw = True # Redraw static content
                    obj.draw_border()
                    obj.show()

    @classmethod
    def show(cls):
        for obj in cls.current_screen.displaylist:
            if obj.visible: # In a buttonlist only show visible button
                obj.redraw = True # Redraw static content
                obj.draw_border()
                obj.show()

    @classmethod
    def change(cls, cls_new_screen, *, forward=True, args=[], kwargs={}):
        init = cls.current_screen is None
        if init:
            Screen() # Instantiate a blank starting screen
        else:  # About to erase an existing screen
            for entry in cls.current_screen.tasklist:
                if entry[1]:  # To be cancelled on screen change
                    entry[0].cancel()
        cs_old = cls.current_screen
        cs_old.on_hide() # Optional method in subclass
        if forward:
            if isinstance(cls_new_screen, type):
                new_screen = cls_new_screen(*args, **kwargs) # Instantiate new screen
            else:
                raise ValueError('Must pass Screen class or subclass (not instance)')
            new_screen.parent = cs_old
            cs_new = new_screen
        else:
            cs_new = cls_new_screen # An object, not a class
        cls.current_screen = cs_new
        cs_new.on_open() # Optional subclass method
        cs_new._do_open(cs_old) # Clear and redraw
        cs_new.after_open() # Optional subclass method
        if init:
            try:
                asyncio.run(Screen.monitor())  # Starts and ends uasyncio
            finally:
                asyncio.new_event_loop()

    @classmethod
    async def monitor(cls):
        await cls.is_shutdown.wait()
        cls.is_shutdown.clear()
        for entry in cls.current_screen.tasklist:
            entry[0].cancel()
        await asyncio.sleep_ms(0)  # Allow subclass to cancel tasks
        cls.tft.clr_scr()
        cls.current_screen = None  # Ensure another demo can run

    @classmethod
    def back(cls):
        parent = cls.current_screen.parent
        if parent is not None:
            cls.change(parent, forward = False)

    @classmethod
    def addobject(cls, obj):
        if cls.current_screen is None:
            raise OSError('You must create a Screen instance')
        if isinstance(obj, Touchable):
            cls.current_screen.touchlist.append(obj)
        cls.current_screen.displaylist.append(obj)

    @classmethod
    def shutdown(cls):
        cls.is_shutdown.set()  # Tell monitor() to shutdown

    def __init__(self):
        self.touchlist = []
        self.displaylist = []
        self.tasklist = []  # Allow instance to register tasks for shutdown
        self.modal = False
        if Screen.current_screen is None: # Initialising class and task
            asyncio.create_task(Screen.objtouch.touchtest()) # One task only
            asyncio.create_task(self._garbage_collect())
        Screen.current_screen = self
        self.parent = None

    def _do_open(self, old_screen): # Aperture overrides
        show_all = True
        tft = Screen._get_tft()
# If opening a Screen from an Aperture just blank and redraw covered area
        if old_screen.modal:
            show_all = False
            x0, y0, x1, y1 = old_screen._list_dims()
            tft.fill_rectangle(x0, y0, x1, y1, SYS_BGCOLOR) # Blank to screen BG
            for obj in [z for z in self.displaylist if z.overlaps(x0, y0, x1, y1)]:
                if obj.visible:
                    obj.redraw = True # Redraw static content
                    obj.draw_border()
                    obj.show()
# Normally clear the screen and redraw everything
        else:
            tft.clr_scr()
            Screen.show()

    def on_open(self): # Optionally implemented in subclass
        return

    def after_open(self): # Optionally implemented in subclass
        return

    def on_hide(self): # Optionally implemented in subclass
        return

    def reg_task(self, task, on_change=False):  # May be passed a coro or a Task
        if isinstance(task, type_coro):
            task = asyncio.create_task(task)
        self.tasklist.append([task, on_change])

    async def _garbage_collect(self):
        while True:
            await asyncio.sleep_ms(100)
            gc.collect()
            gc.threshold(gc.mem_free() // 4 + gc.mem_alloc())