def test_round_trip_from_empty_msg_comparison(): # Instantiate an empty message the_msg = IpcMessage() # Set the message type and value msg_type = "cmd" the_msg.set_msg_type(msg_type) msg_val = "reset" the_msg.set_msg_val(msg_val) msg_id = 61616 the_msg.set_msg_id(msg_id) # Define and set some parameters paramInt1 = 1234; paramInt2 = 901201; paramInt3 = 4567; paramStr = "paramString" the_msg.set_param('paramInt1', paramInt1) the_msg.set_param('paramInt2', paramInt2) the_msg.set_param('paramInt3', paramInt3) the_msg.set_param('paramStr', paramStr) # Retrieve the encoded version the_msg_encoded = the_msg.encode() # Create another message from the encoded version msg_from_encoded = IpcMessage(from_str=the_msg_encoded) # Test that the comparison operators work correctly assert_true(the_msg == msg_from_encoded) assert_false(the_msg != msg_from_encoded)
def run(self): self.logger.info("Frame receiver client starting up") self.logger.debug("Control IPC channel has identity {}".format( self.ctrl_channel.identity)) msg = IpcMessage('cmd', 'configure') msg.set_param('test', {'list': True}) self.ctrl_channel.send(msg.encode()) pollevts = self.ctrl_channel.poll(1000) if pollevts == IpcChannel.POLLIN: reply = IpcMessage(from_str=self.ctrl_channel.recv()) self.logger.info("Got response: {}".format(reply))
def process_frames(self): self.frame_header = Struct('<LLQQL') while self._run: if (self.ready_channel.poll(100)): ready_msg = self.ready_channel.recv() ready_decoded = IpcMessage(from_str=ready_msg) if ready_decoded.get_msg_type( ) == 'notify' and ready_decoded.get_msg_val() == 'frame_ready': frame_number = ready_decoded.get_param('frame') buffer_id = ready_decoded.get_param('buffer_id') self.logger.debug( "Got frame ready notification for frame %d buffer ID %d" % (frame_number, buffer_id)) if not self.config.bypass_mode: self.handle_frame(frame_number, buffer_id) release_msg = IpcMessage(msg_type='notify', msg_val='frame_release') release_msg.set_param('frame', frame_number) release_msg.set_param('buffer_id', buffer_id) self.release_channel.send(release_msg.encode()) self.frames_received += 1 elif ready_decoded.get_msg_type( ) == 'notify' and ready_decoded.get_msg_val( ) == 'buffer_config': shared_buffer_name = ready_decoded.get_param( 'shared_buffer_name') self.logger.debug( 'Got shared buffer config notification with name %s' % (shared_buffer_name)) else: self.logger.error( "Got unexpected message on ready notification channel: %s" % (ready_decoded)) self.logger.info("Frame processing thread interrupted, terminating")
def reset_stats_cmd(self, channel): ''' Used to reset statistics in LPD Process Plugin ''' reset = IpcMessage('cmd', 'reset_statistics', id=self._next_msg_id()) channel.send(reset.encode()) reply = self.await_response(channel) return reply
def send_status_cmd(self, channel): ''' Sends a status command to the channel that's passed ''' status_msg = IpcMessage('cmd', 'status', id=self._next_msg_id()) channel.send(status_msg.encode()) reply = self.await_response(channel) return reply
def send_config_msg(self, channel, config): ''' Sends a configuration command to the channel that's passed ''' config_msg = IpcMessage('cmd', 'configure', id=self._next_msg_id()) config_msg.attrs['params'] = config channel.send(config_msg.encode()) reply = self.await_response(channel)
def handle_control_message(self, socket): """Handle a control message on the given socket Args: socket(zmq.Socket): The socket to receive a message and reply on """ message_handlers = { "status": self.status, "configure": self.configure, "request_configuration": self.request_configuration, "request_version": self.version, "shutdown": self.shutdown, } # The first message part is a channel ID channel_id = socket.recv() # The second message part is the IpcMessage message = IpcMessage(from_str=socket.recv()) request_type = message.get_msg_val() handler = message_handlers.get(request_type, None) if handler is not None: reply = handler(message) else: error = "Unknown request type: {}".format(request_type) self._logger.error(error) reply = self._construct_reply( message.get_msg_val(), message.get_msg_id(), error ) socket.send(channel_id, zmq.SNDMORE) socket.send(reply.encode())
def _send_message(self, msg, timeout): msg.set_msg_id(self.message_id) self.message_id = (self.message_id + 1) % self.MESSAGE_ID_MAX self.logger.debug("Sending control message:\n%s", msg.encode()) with self._lock: self.ctrl_channel.send(msg.encode()) expected_id = msg.get_msg_id() id = None while not id == expected_id: pollevts = self.ctrl_channel.poll(timeout) if pollevts == zmq.POLLIN: reply = IpcMessage(from_str=self.ctrl_channel.recv()) id = reply.get_msg_id() if not id == expected_id: self.logger.warn("Dropping reply message with id [" + str(id) + "] as was expecting [" + str(expected_id) + "]") continue if reply.is_valid() and reply.get_msg_type( ) == IpcMessage.ACK: self.logger.debug("Request successful: %s", reply) return True, reply.attrs else: self.logger.debug("Request unsuccessful") return False, reply.attrs else: self.logger.warning("Received no response") return False, None
def test_create_modify_empty_msg_params(): # Instantiate an empty message the_msg = IpcMessage() # Define and set some parameters paramInt1 = 1234; paramInt2 = 901201; paramInt3 = 4567; paramStr = "paramString" the_msg.set_param('paramInt1', paramInt1) the_msg.set_param('paramInt2', paramInt2) the_msg.set_param('paramInt3', paramInt3) the_msg.set_param('paramStr', paramStr) # Read them back and check they have the correct value assert_true(the_msg.get_param('paramInt1'), paramInt1) assert_true(the_msg.get_param('paramInt2'), paramInt2) assert_true(the_msg.get_param('paramInt3'), paramInt3) assert_true(the_msg.get_param('paramStr'), paramStr) # Modify several parameters and check they are still correct paramInt2 = 228724; the_msg.set_param('paramInt2', paramInt2) paramStr = "another string" the_msg.set_param("paramStr", paramStr) assert_true(the_msg.get_param('paramInt2'), paramInt2) assert_true(the_msg.get_param('paramStr'), paramStr)
def set_file_writing(self, enable): self.set_file_name(self.file_name) self.set_file_path(self.file_path) self.set_num_frames(self.frames) self.fp_config['hdf']['frames'] = self.frames self.fp_config['hdf']['write'] = enable # write_config = {} # if enable: # write_config['file'] = { # "path": self.file_path, # "name": self.file_name, # } # write_config["frames"] = self.frames # write_config["write"] = enable config_msg = IpcMessage('cmd', 'configure', id=self._next_msg_id()) #config_msg.set_param('hdf', write_config) config_msg.attrs['params'] = {'hdf': self.fp_config['hdf']} print(config_msg) self.logger.info('Sending file writing {} command to frame processor'.format( 'enable' if enable else 'disable')) self.fp_ctrl_channel.send(config_msg.encode()) self.await_response(self.fp_ctrl_channel)
def test_empty_ipc_msg_invalid(): # Instantiate an empty message the_msg = IpcMessage() # Check that the message is not valid assert_false(the_msg.is_valid())
def send_message(self, ipc_message): self._ctrl_channel.send(ipc_message.encode()) pollevts = self._ctrl_channel.poll(1000) if pollevts == zmq.POLLIN: reply = IpcMessage(from_str=self._ctrl_channel.recv()) if reply: self._current_value = str(reply)
def handle_request_version_message(self, msg_id): """Handle request version message. :param: msg_id: message id to use for reply """ reply = IpcMessage(IpcMessage.ACK, 'request_version', id=msg_id) version = versioneer.get_versions()["version"] major_version = re.findall(MAJOR_VER_REGEX, version)[0] minor_version = re.findall(MINOR_VER_REGEX, version)[0] patch_version = re.findall(PATCH_VER_REGEX, version)[0] short_version = major_version + "." + minor_version + "." + patch_version version_dict = {} odin_data_dict = {} odin_data_dict["full"] = version odin_data_dict["major"] = major_version odin_data_dict["minor"] = minor_version odin_data_dict["patch"] = patch_version odin_data_dict["short"] = short_version version_dict["odin-data"] = odin_data_dict version_dict["writer"] = self.get_writer_version() reply.set_param('version', version_dict) return reply
def send_request(self, value, timeout=1000): msg = IpcMessage("cmd", value) success, reply = self._send_message(msg, timeout) if success: return reply else: self._raise_reply_error(msg, reply)
def _callback(self, msg): # Handle the multi-part message reply = IpcMessage(from_str=msg[0]) if 'request_configuration' in reply.get_msg_val(): self._update_configuration(reply.attrs) if 'status' in reply.get_msg_val(): self._update_status(reply.attrs)
def form_ipc_msg(self, msgType, msgVal, msgDevice, msgConfig, blink_timeout, blink_rate): """ Forms and returns an encoded IPC Message :param msgtype: The type of message i.e CMD :param msgVal: The value of the request i.e STATUS/CONFIG :param msgDevice: The device alias name :param msgConfig: The configuration parameter Returns the encoded ipc message for sending over zmq socket """ request = IpcMessage(msgType, msgVal) request.set_param("DEVICE", msgDevice) if msgVal == "CONFIG": request.set_param("CONFIG", msgConfig) if msgConfig == "BLINK": request.set_param("TIMEOUT", blink_timeout) request.set_param("RATE", blink_rate) print("%s Configuring service request..." % self.identity) # Encode the message to be sent request = request.encode() if isinstance(request, unicode): request = cast_bytes(request) return request
def send_status_cmd(self, channel): status_msg = IpcMessage('cmd', 'status', id=self._next_msg_id()) channel.send(status_msg.encode()) reply = self.await_response(channel) return reply
def handle_status_message(self, msg_id): """Handle status message. :param: msg_id: message id to use for reply """ status_dict = {} for key in self._writers: writer = self._writers[key] status_dict[key] = { 'filename': writer.full_file_name, 'num_processors': writer.number_processes_running, 'written': writer.write_count, 'writing': writer.file_created and not writer.finished } writer.write_timeout_count = writer.write_timeout_count + 1 reply = IpcMessage(IpcMessage.ACK, 'status', id=msg_id) reply.set_param('acquisitions', status_dict) # Now delete any finished acquisitions, and stop any stagnant ones for key, value in self._writers.items(): if value.finished: del self._writers[key] else: if value.number_processes_running == 0 and value.write_timeout_count > 10 and value.file_created: self.logger.info('Force stopping stagnant acquisition: ' + str(key)) value.stop() return reply
def _construct_reply(msg_val, msg_id, error=None): reply = IpcMessage(IpcMessage.ACK, msg_val, id=msg_id) if error is not None: reply.set_msg_type(IpcMessage.NACK) reply.set_param("error", error) return reply
def await_response(self, channel, timeout_ms=1000): reply = None pollevts = channel.poll(1000) if pollevts == IpcChannel.POLLIN: reply = IpcMessage(from_str=channel.recv()) return reply
def await_response(self, channel, timeout_ms=1000): ''' Polls the passed channel for any data to be received, used in various functions below ''' reply = None pollevts = channel.poll(timeout_ms) if pollevts == IpcChannel.POLLIN: reply = IpcMessage(from_str=channel.recv()) return reply
def do_request_config_cmd(self): request_msg = IpcMessage('cmd', 'request_configuration', id=self._next_msg_id()) for (name, channel) in self.channels: self.logger.info("Sending configuration request for frame {}".format(name)) channel.send(request_msg.encode()) reply = self.await_response(channel) if reply is not None: self.logger.info("Got response: {}".format(reply))
def send_configuration(self, content, target=None, valid_error=None): msg = IpcMessage("cmd", "configure") if target is not None: msg.set_param(target, content) else: for parameter, value in content.items(): msg.set_param(parameter, value) self._send_message(msg)
def on_ok(self): msg = IpcMessage("cmd", "configure") config = { "process": { "number": int(self.ctrl1.value), "rank": int(self.ctrl2.value), }, } msg.set_param("hdf", config) self.parentApp.send_message(msg)
def on_ok(self): msg = IpcMessage("cmd", "configure") config = { "file": { "name": self.ctrl1.value, "path": self.ctrl2.value, }, "frames": int(self.ctrl3.value), } msg.set_param("hdf", config) self.parentApp.send_message(msg)
def on_ok(self): msg = IpcMessage("cmd", "configure") config = { "load": { "library": self.ctrl1.value, "index": self.ctrl2.value, "name": self.ctrl3.value, } } msg.set_param("plugin", config) self.parentApp.send_message(msg)
def request_shared_buffer_config(self): success = False max_request_retries = 10 max_reply_retries = 10 request_retries = 0 config_request = IpcMessage(msg_type='cmd', msg_val='request_buffer_config') while success is False and request_retries < max_request_retries: self.logger.debug( "Sending buffer config request {}".format(request_retries + 1)) self.release_channel.send(config_request.encode()) reply_retries = 0 while success is False and reply_retries < max_reply_retries: if self.ready_channel.poll(100): config_msg = self.ready_channel.recv() config_decoded = IpcMessage(from_str=config_msg) self.logger.debug( 'Got buffer configuration response with shared buffer name: {}' .format( config_decoded.get_param('shared_buffer_name'))) self.config.sharedbuf = config_decoded.get_param( 'shared_buffer_name') success = True else: reply_retries += 1 request_retries += 1 # temp hack if not success: self.logger.error("Failed to obtain shared buffer configuration") return success
def recv_reply(self): """ Receive reply from ZMQ socket Receives a multipart message, forms an IPCmessage and prints out the REPLY string """ # Strip off the address r_address, reply = self.socket.recv_multipart() # format it as an IPC message reply = IpcMessage(from_str=reply) print("Received Response: %s" % reply.get_param("REPLY"))
def test_round_trip_from_empty_msg(): # Instantiate an empty message the_msg = IpcMessage() # Set the message type and value msg_type = "cmd" the_msg.set_msg_type(msg_type) msg_val = "reset" the_msg.set_msg_val(msg_val) msg_id = 61616 the_msg.set_msg_id(msg_id) # Define and set some parameters paramInt1 = 1234; paramInt2 = 901201; paramInt3 = 4567; paramStr = "paramString" the_msg.set_param('paramInt1', paramInt1) the_msg.set_param('paramInt2', paramInt2) the_msg.set_param('paramInt3', paramInt3) the_msg.set_param('paramStr', paramStr) # Retrieve the encoded version the_msg_encoded = the_msg.encode() # Create another message from the encoded version msg_from_encoded = IpcMessage(from_str=the_msg_encoded) # Validate the contents of all attributes and parameters of the new message assert_equal(msg_from_encoded.get_msg_type(), msg_type) assert_equal(msg_from_encoded.get_msg_val(), msg_val) assert_equal(msg_from_encoded.get_msg_timestamp(), the_msg.get_msg_timestamp()) assert_equal(msg_from_encoded.get_msg_id(), the_msg.get_msg_id()) assert_equal(msg_from_encoded.get_param('paramInt1'), paramInt1) assert_equal(msg_from_encoded.get_param('paramInt2'), paramInt2) assert_equal(msg_from_encoded.get_param('paramInt3'), paramInt3) assert_equal(msg_from_encoded.get_param('paramStr'), paramStr)
def set_file_writing(self, enable): ''' Enables or disables file writing (typically once a run has finished) ''' self.config_processor['hdf']['frames'] = self.num_frames self.config_processor['hdf']['write'] = enable config_msg = IpcMessage('cmd', 'configure', id=self._next_msg_id()) config_msg.attrs['params'] = {'hdf': self.config_processor['hdf']} print('Sending file writing {} command to frame processor'.format( 'enable' if enable else 'disable')) self.fp_ctrl_channel.send(config_msg.encode()) self.await_response(self.fp_ctrl_channel)