예제 #1
0
    async def _ws_conn_handler(self, ws):
        try:
            if hasattr(ws.remote, 'address'): ip = ws.remote.address
            else: ip = ws.remote
            log.info("New ws connection to {} from {}", ws.path, ip)
            log.debug("Children objects refs: {}", list(self._child_obj.keys()))
            log.debug("Clients connected: {}", self._subscr)

            refv = ws.path.split('/')[1]
            # if anything is in the path
            if len(refv)>0:
                async for msg in self._handle_obj_ref(ws, refv):
                    yield msg

            else:
                # return link to root element
                log.info("Sending root {}", ref(self.vars))
                yield json.dumps({'root': ref(self.vars)})
        except ConnectionClosed as e:
            code = e.reason.code
            if code == 1000:
                log.info('Client {} goes away from {}', ip, ws.path)
            else:
                log.warning('Connection from {} to {} closed: {}.',
                                             ip, ws.path,     e)
        except Exception as e:
            log.error("Handling {} error: {}", type(e), e)
예제 #2
0
def test_simple_var_poll():
    responses = Queue()

    app = App(addr=addr, port=port)
    client = LeClient('value')
    try:
        app.run()
        time.sleep(.05)

        class List(list):
            pass

        object = List()
        app.watch_obj(object)
        app.vars.value = ref(object)
        _ = client.start(f'ws://{addr}:{port}')
        for i in range(5):
            object.append(i)
            time.sleep(.1)

        time.sleep(.1)
        assert client.updates_count() > 0
        responses = client.get_all_updates()
        assert responses[-1] == str(object)

    finally:
        app.stop()
예제 #3
0
    def _register_child(self, o):
        if isinstance(o, Object):

            def put_updates(name, value):
                """ Put the updates to temp dictionary """
                name, value = o._prepare_send(name, value)
                # Determines what to send to ws clients
                self._children_updates[ref(o)].update({name:value})

            o.subscribe_set(put_updates)
            o.subscribe_set(self._register_new)

            # Determines where to put received updates
            self._child_obj[ref(o)] = o
            log.debug("Added child object {} with ref {}", o, ref(o))
            # returning none makes mapper
            # traverse the whole dict tree 
            return None
예제 #4
0
    async def _child_updating_loop(self, ws, child):
        """ Listen for incomming updates from websocket
        and update the relevant child

        This coroutine works N times, where N is number of
        requested existing objects (from `self._child_obj`)
        """
        log.debug("Listening for updates for {}", ref(child))
        while True:
            msg = await ws.get_message()
            try:
                updates = json.loads(msg)
                log.debug("Updates for {} : {}", ref(child), updates)
                for key, value in updates.items():
                    try:
                        child._commit_update(key, value)
                    except Exception as e:
                        log.error(f"{e}. While commiting update to {child}.  "
                                  f"{key} : {value}")
            except TypeError:
                log.error("JSON decode error: {}", msg)
예제 #5
0
def test_object_poll():
    responses = Queue()

    app = App(addr=addr, port=port)
    client = LeClient('rapid_updated')

    try:
        app.run()
        time.sleep(.05)
        _ = client.start(f'ws://{addr}:{port}')

        class Rollin(Object):
            def __init__(self):
                super().__init__()
                self.x = []

        rapid = Rollin()
        app.watch_obj(rapid)
        app.vars.rapid_updated = ref(rapid)

        dt = 1e-4
        T = 0.5
        # Put data in bursts, use N appends between sleeps
        N = int(0.005 / dt)
        app._watch_poll_delay = 0.1
        for i in range(int(T // dt)):
            rapid.x += [i]
            if i % N == 0:
                #print('put',i, time.time())
                # Don't try to do μs delays, need Real-Time OS for this
                time.sleep(N * dt)

        #Wait for finish update
        time.sleep(app._watch_poll_delay)

        responses = [json.loads(x) for x in client.get_all_updates()]
        assert responses
        xlens = [len(x['x']) for x in responses]
        assert xlens[-1] == int(T // dt)
        print("Lengths of rapid updates of growing list", xlens)
        assert len(responses) >= T // app._watch_poll_delay
        dlens = [x1 - x0 for x0, x1 in zip(xlens[:-1], xlens[1:])]
        incrs = app._watch_poll_delay / dt
        print(f"Lengths increments: should be near {incrs}", dlens)
        assert all(x <= incrs for x in dlens)

    finally:
        app.stop()
예제 #6
0
 def put_updates(name, value):
     """ Put the updates to temp dictionary """
     name, value = o._prepare_send(name, value)
     # Determines what to send to ws clients
     self._children_updates[ref(o)].update({name:value})
예제 #7
0
 def watch_obj(self, obj):
     self._watched_children[ref(obj)] = obj
     self._child_obj[ref(obj)] = obj