def __on_receive_rpc_request(self, ch, method, props, body): self._logger.debug("received RPC req from exchange '%s' with routing key %s and correlation_id %s", method.exchange, method.routing_key, props.correlation_id) # the following frames are handled here: # • RPC request messages # - sent to empty exchange # - routing_key is queue provided in _register_rpc_function # sanity check assert method.routing_key in self.__rpc_queue_map, \ "%s not a valid RPC queue" % (method.routing_key,) # hand off the RPC request to the RPCWorker req_body = serializer_utils.deserialize(body, props.content_type) callback = None if req_body['command'] in self.__rpc_queue_map[method.routing_key]: callback = self.__rpc_queue_map[method.routing_key][req_body['command']] self.__rpc_worker.add_request( RPCRequest( correlation_id = props.correlation_id, content_type = props.content_type, reply_to = props.reply_to, callback = callback, args = req_body['args'] ) ) else: self._logger.error("command %s not configured for queue %s", req_body['command'], method.routing_key) ch.basic_ack(delivery_tag = method.delivery_tag)
def __on_receive_packet(self, ch, method, props, body): self._logger.debug("received packet from exchange '%s' with routing key %s and correlation_id %s", method.exchange, method.routing_key, props.correlation_id) frame = serializer_utils.deserialize(body, props.content_type) # the following frames are handled here: # • XBee "raw" frames # - sent to exhange 'raw_xbee_frames' # - routing_key is '<frame type>.<source addr>' # • XBee reply frames in response to a command or data sent to a device # - sent to empty exchange # - routing_key is name of our private queue # - have correlation_id matching a key in __pending_xb_requests # differentiate replies from raw packets if (props.correlation_id != None) and (method.routing_key == self.__queue_name): # this is a reply with self.__pending_xb_requests_lock: if props.correlation_id in self.__pending_xb_requests: req = self.__pending_xb_requests[props.correlation_id] if not req.async: self.finish_async_request(req, frame) else: self.handle_async_reply(req, frame) else: self._logger.error("got %s reply for unknown correlation %s: %s", frame['id'], props.correlation_id, frame) # this needs to get called every now and then self.__reap_unfinished_requests() else: # standard raw packet; guaranteed to have a routing_key of the form # <frame id>.<address>, where the address is one we're subscribed to formatted_addr = method.routing_key.split('.')[1] try: self.handle_packet(formatted_addr, frame) except: self._logger.critical("exception handling packet", exc_info = True)
def __on_receive_rpc_response(self, channel, method, props, body): # props.correlation_id is the request ticket with self.__pending_requests_lock: request = self.__pending_requests.pop(props.correlation_id) try: resp_data = serializer_utils.deserialize(body, props.content_type) if "exception" in resp_data: request.exception = resp_data["exception"] else: request.response = resp_data["result"] except: self._logger.error("exception unpickling", exc_info=True) request.exception = sys.exc_info()[1] request.event.set() channel.basic_ack(delivery_tag=method.delivery_tag)
def __handle_xb_tx(self, chan, method, props, body): ## no need for a connection lock since we're running in the main ## thread, and there isn't any possibility for concurrent access ## to the connection for this thread try: # ack the message; there's nothing below that would be # recoverable if the same message were received again chan.basic_ack(delivery_tag = method.delivery_tag) req = serializer_utils.deserialize(body, props.content_type) self._logger.debug( "TX method %s for dest %s with correlation ID %s", req['method'], req['dest'], props.correlation_id ) # mapping of frame id to message properties; used to direct the # response frame_id = self.__next_frame_id() if props.headers == None: props.headers = {} if 'keep_alive' not in props.headers: props.headers['keep_alive'] = False with self.__correlation_lock: self.__correlations[frame_id] = { 'props' : props, 'keep_alive' : bool(props.headers['keep_alive']), 'expiration' : time.time() + 120, } if req['method'] == 'send_remote_at': # {'method' : 'send_remote_at', # 'dest' : <addr>, # 'command' : …, # 'param_val' : …, # } self.xbee.remote_at(frame_id = frame_id, dest_addr_long = parse_addr(req['dest']), command = req['command'], parameter = req['param_val']) elif req['method'] == 'send_data': # {'method' : 'send_data', # 'dest' : <addr>, # 'data' : …, # } self.xbee.zb_tx_request( frame_id = frame_id, dest_addr_long = parse_addr(req['dest']), data = req['data'] ) self._logger.debug("XBee command sent and message ack'd") except: self._logger.error("failed processing XBee TX message", exc_info = True)