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 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 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 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 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 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 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)
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 do_config_cmd(self, config_file): try: config_params = json.load(config_file) config_msg = IpcMessage('cmd', 'configure') for param, value in config_params.items(): config_msg.set_param(param, value) self.logger.info( "Sending configure command to frame receiver with specified parameters" ) self.ctrl_channel.send(config_msg.encode()) self.await_response() except JSONDecodeError as e: self.logger.error( "Failed to parse configuration file: {}".format(e))
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 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 handle_control_message(self, receiver): """Handle control message. :param: receiver: ZeroMQ channel to receive message from """ channel_id = receiver.recv() message_val = "" message_id = 0 try: message = IpcMessage(from_str=receiver.recv()) message_val = message.get_msg_val() message_id = message.get_msg_id() if message.get_msg_val() == 'status': reply = self.handle_status_message(message_id) elif message.get_msg_val() == 'request_configuration': reply = self.handle_request_config_message(message_id) elif message.get_msg_val() == 'request_version': reply = self.handle_request_version_message(message_id) elif message.get_msg_val() == 'configure': self.logger.debug('handling control configure message') self.logger.debug(message) params = message.attrs['params'] reply = self.handle_configure_message(params, message_id) else: reply = IpcMessage(IpcMessage.NACK, message_val, id=message_id) reply.set_param('error', 'Unknown message value type') except Exception as err: self.logger.error( 'Unexpected Exception handling control message: ' + str(err)) reply = IpcMessage(IpcMessage.NACK, message_val, id=message_id) reply.set_param('error', 'Error processing control message') receiver.send(channel_id, zmq.SNDMORE) receiver.send(reply.encode())
def run_rep(self): ''' sends a request, waits for a reply, returns response ''' while True: try: client_address, request = self.socket.recv_multipart() request = IpcMessage(from_str=request) print("received request : %s from %s" % (request, client_address.decode())) # Get the alias device name used in the request req_alias = request.get_param("DEVICE") # get the address of the device req_address = self.process_address(request) # get the message value (CONFIG/STATUS/READ) req_msg_val = request.get_msg_val() req_device = None req_config = None reply_message = IpcMessage(msg_type="CMD", msg_val="NOTIFY") # Find the device attached to that request address for device in self.devices: if req_address == device.get_addr(): req_device = device if req_msg_val == "CONFIG": req_config = request.get_param("CONFIG") if req_config == "BLINK": req_timeout = request.get_param("TIMEOUT") req_rate = request.get_param("RATE") req_device.set_config(req_config, req_timeout, req_rate) reply_string = "Processed request from %s. %s at address %s blinked for %s seconds. \ Current status is %s." % (client_address.decode(),req_alias, req_address, req_timeout, req_device.get_config()) else: req_device.set_config(req_config) reply_string = "Processed Request from %s. Set %s at \ address %s to: %s." % (client_address.decode(), req_alias, req_address, req_device.get_config()) if req_msg_val == "STATUS": rep_status = req_device.get_status() reply_string = "Processed Request from %s. Status of %s at \ address %s is: %s." % (client_address.decode(), req_alias, req_address, rep_status) if req_msg_val == "READ": rep_value = req_device.get_data() reply_string = "Processed Request from %s. Value of %s at \ address %s is: %s." % (client_address.decode(), req_alias, req_address, rep_value) reply_message.set_param("REPLY", reply_string) # Encode the message for sending reply_message = reply_message.encode() # check if its unicode, if so covert to bytes if isinstance(reply_message, unicode): reply_message = cast_bytes(reply_message) # send a multipart back to the client self.socket.send_multipart([client_address, b"", reply_message,]) except IpcMessageException as err: print("IPC MESSAGE Error Found %s: " % str(err))
def do_shutdown_cmd(self, channel): ''' Sends a shutdown command to the channel that's passed ''' shutdown_msg = IpcMessage('cmd', 'shutdown', id=self._next_msg_id()) channel.send(shutdown_msg.encode()) self.await_response(channel)
def run(self): self.logger.info("Frame processor starting up") # Connect the IPC channels self.ctrl_channel.connect(self.config.ctrl_endpoint) self.ready_channel.connect(self.config.ready_endpoint) self.release_channel.connect(self.config.release_endpoint) # Ready channel subscribes to all topics self.ready_channel.subscribe(b'') # Map the shared buffer manager - quit if this fails if not self.map_shared_buffer(): self._run = False return self.logger.info( "Mapped shared buffer manager ID %d with %d buffers of size %d" % (self.shared_buffer_manager.get_manager_id(), self.shared_buffer_manager.get_num_buffers(), self.shared_buffer_manager.get_buffer_size())) if self.config.sensortype == 'percivalemulator': self.frame_decoder = PercivalEmulatorFrameDecoder( self.shared_buffer_manager) self.logger.debug( 'Loaded frame decoder for PERCIVAL emulator sensor type') elif self.config.sensortype == 'excalibur': self.frame_decoder = ExcaliburFrameDecoder( self.shared_buffer_manager) self.logger.debug('Loaded frame decoder for EXCALIBUR sensor type') else: self.frame_decoder = None self.logger.error("Unrecognised sensor type specified: %s" % self.config.sensortype) return # Launch the frame processing thread self.frame_processor.start() try: while self._run: if self.config.frames and self.frames_received >= self.config.frames: self.logger.info( "Specified number of frames (%d) received, terminating" % self.config.frames) self._run = False else: msg = IpcMessage(msg_type='cmd', msg_val='status') #self.logger.debug("Sending status command message") self.ctrl_channel.send(msg.encode()) reply = self.ctrl_channel.recv() reply_decoded = IpcMessage(from_str=reply) #self.logger.debug("Got reply, msg_type = " + reply_decoded.get_msg_type() + " val = " + reply_decoded.get_msg_val()) time.sleep(1) except KeyboardInterrupt: self.logger.info("Got interrupt, terminating") self._run = False self.frame_processor.join() self.logger.info("Frame processor shutting down")
def send_config_cmd(self, channel, params): config_msg = IpcMessage('cmd', 'configure', id=self._next_msg_id()) config_msg.attrs['params'] = params channel.send(config_msg.encode()) self.await_response(channel)
def do_status_cmd(self): status_msg = IpcMessage('cmd', 'status') self.logger.info("Sending status request to frame receiver") self.ctrl_channel.send(status_msg.encode()) self.await_response()
def do_shutdown_cmd(self): shutdown_msg = IpcMessage('cmd', 'shutdown') self.logger.info("Sending shutdown command to frame receiver") self.ctrl_channel.send(shutdown_msg.encode()) self.await_response()