def _incoming(self, headers: dict, body: any): """ This function handles incoming messages from the websocket connection with the Mercury language connector. It must be invoked using events. It should not be called directly to guarantee proper event sequencing. :param headers: type is open, close, text or bytes :param body: string or bytes :return: None """ if self.ws and 'type' in headers: if headers['type'] == 'open': self.ready = False self.log.info("Login to language connector") self.send_payload({'type': 'login', 'api_key': self.api_key}) if headers['type'] == 'close': self.ready = False self.log.info("Closed") if headers['type'] == 'text': self.log.debug(body) if headers['type'] == 'bytes': event = msgpack.unpackb(body, raw=False) if 'type' in event: event_type = event['type'] if event_type == 'block' and 'block' in event: envelope = EventEnvelope() inner_event = envelope.from_map(event['block']) inner_headers = inner_event.get_headers() if 'id' in inner_headers and 'count' in inner_headers and 'total' in inner_headers: msg_id = inner_headers['id'] msg_count = inner_headers['count'] msg_total = inner_headers['total'] data = inner_event.get_body() if isinstance(data, bytes): buffer = self.cache.get(msg_id) if buffer is None: buffer = io.BytesIO() buffer.write(data) self.cache.put(msg_id, buffer) if msg_count == msg_total: buffer.seek(0) # reconstruct event for processing event = msgpack.unpackb(buffer.read(), raw=False) event_type = 'event' self.cache.remove(msg_id) if event_type == 'event' and 'event' in event: envelope = EventEnvelope() inner_event = envelope.from_map(event['event']) if self.platform.has_route(inner_event.get_to()): self.platform.send_event(inner_event) else: self.log.warn('Incoming event dropped because ' + str(inner_event.get_to()) + ' not found')
def _incoming(self, headers: dict, body: any): """ This function handles incoming messages from the websocket connection with the Mercury language connector. It must be invoked using events. It should not be called directly to guarantee proper event sequencing. Args: headers: type is open, close, text or bytes body: string or bytes Returns: None """ if self.ws and 'type' in headers: if headers['type'] == 'open': self.ready = False self.log.info("Login to language connector") self.send_payload({'type': 'login', 'api_key': self.api_key}) self._send_life_cycle_event(headers) if headers['type'] == 'close': self.ready = False self.log.info("Closed") self._send_life_cycle_event(headers) if headers['type'] == 'text': self.log.debug(body) if headers['type'] == 'bytes': event = msgpack.unpackb(body, raw=False) if 'type' in event: event_type = event['type'] if event_type == 'block' and 'block' in event: envelope = EventEnvelope() inner_event = envelope.from_map(event['block']) inner_headers = inner_event.get_headers() if self.MSG_ID in inner_headers and self.COUNT in inner_headers and self.TOTAL in inner_headers: msg_id = inner_headers[self.MSG_ID] msg_count = inner_headers[self.COUNT] msg_total = inner_headers[self.TOTAL] data = inner_event.get_body() if isinstance(data, bytes): buffer = self.cache.get(msg_id) if buffer is None: buffer = io.BytesIO() buffer.write(data) if msg_count == msg_total: self.cache.remove(msg_id) # reconstruct event for processing buffer.seek(0) envelope = EventEnvelope() unpacked = msgpack.unpackb(buffer.read(), raw=False) restored = envelope.from_map(unpacked) target = restored.get_to() if self.platform.has_route(target): self.platform.send_event(restored) else: self.log.warn( f'Incoming event dropped because {target} not found' ) else: self.cache.put(msg_id, buffer) if event_type == 'event' and 'event' in event: unpacked = msgpack.unpackb(event['event'], raw=False) envelope = EventEnvelope() inner_event = envelope.from_map(unpacked) if self.platform.has_route(inner_event.get_to()): self.platform.send_event(inner_event) else: self.log.warn( f'Incoming event dropped because {inner_event.get_to()} not found' )