def run(self, name): print("Starting {}".format(name)) log.INFO(__name__, self.request_queue, "Starting {}".format(name)) self.ws = websocket.WebSocket() self.ws.connect(self.url) self.do_handshake() self.subscribe('settings') self.sound_player = SoundPlayer('assets/beep.wav', 0, 0) while True: json_msg = self.ws.recv() try: msg = json.loads(json_msg) if msg['type'] == "ping": reply = {'type': 'ping'} self.send_msg(reply) elif msg['type'] == "pub": if msg['path'] == "/api/settings": payload = msg['message'] self.handle_settings(payload) except Exception as e: print("Invalid message from websockets {}".format(json_msg)) log.ERROR( __name__, self.request_queue, "Invalid message from websockets {}".format(json_msg)) print(e) log.ERROR(__name__, self.request_queue, "Exception occurred {}".format(e))
def run(self, name): print('Starting {}'.format(name)) log.INFO(__name__, self.request_queue, "Starting {}".format(name)) while True: try: msg = self.serial_queue.get(block=False) except queue.Empty: msg = None if msg != None: try: key = msg['type'] value = msg['val'] if key in proto.settings: self.settings[key] = float(value) print(self.settings) except Exception as e: print("Invalid message {}".format(msg)) log.ERROR(__name__, self.request_queue, "Invalid message {}".format(msg)) print(e) log.ERROR(__name__, self.request_queue, "Exception occurred {}".format(e)) time.sleep(0.2)
def last_n_data(self, type_data, N=1200): """ retrieve the last "N" added measurement N = 1000 Returns: TODO add return value explanation """ data_TPRES = self.db.targetpressure_values.find().sort("loggedAt", -1).limit(N) if type_data == 'BPM': return self.db.breathsperminute_values.find().sort( "loggedAt", -1).limit(N), data_TPRES elif type_data == 'VOL': return self.db.volume_values.find().sort("loggedAt", -1).limit(N), data_TPRES elif type_data == 'TRIG': return self.db.trigger_values.find().sort("loggedAt", -1).limit(N), data_TPRES elif type_data == 'PRES': return self.db.pressure_values.find().sort("loggedAt", -1).limit(N), data_TPRES elif type_data == 'TPRES': return self.db.targetpressure_values.find().sort("loggedAt", -1).limit(N), None else: print( "[ERROR] value type not recognized use: BPM, VOL, TRIG, or PRES" ) log.ERROR( __name__, self.request_queue, "value type not recognized use: BPM, VOL, TRIG, or PRES") return None, None
def run(self, name): print("Starting {}".format(name)) log.INFO(__name__, self.request_queue, "Starting {}".format(name)) # Only start MongoClient after fork() # and each child process should have its own instance of the client try: self.client = MongoClient(self.addr) except errors.ConnectionFailure: print("Unable to connect, client will attempt to reconnect") log.ERROR(__name__, self.request_queue, "Unable to connect, client will attempt to reconnect") self.db = self.client.beademing while True: try: msg = self.queue.get() except queue.Empty: continue try: if msg['type'] == 'BPM': self.store_bpm(msg) elif msg['type'] == 'VOL': self.store_volume(msg) elif msg['type'] == 'TRIG': self.store_trigger(msg) elif msg['type'] == 'PRES': self.store_pressure(msg) elif msg['type'] == 'TPRES': self.store_target_pressure(msg) elif msg['type'] == 'FLOW': self.store_flow(msg) elif msg['type'] == 'CPU': self.store_cpu(msg) except Exception as e: print("Invalid message from database = {}".format(msg)) log.ERROR(__name__, self.request_queue, "Invalid message from database = {}".format(msg)) print(e) log.ERROR(__name__, self.request_queue, "Exception occurred {}".format(e))
def run(self, name): waiting_for_acks = {} self.ser = serial.Serial(self.port, self.baudrate) self.ser.reset_input_buffer() self.ser.reset_output_buffer() print("Starting {}".format(name)) log.INFO(__name__, self.request_queue, "Starting {}".format(name)) while True: try: msg = self.out_queue.get(block=False) except queue.Empty: msg = None if msg != None: print("outgoing message: {} with id {}".format(msg, self.message_id)) msg_bytes = proto.construct_serial_message(msg['type'], msg['val'], self.message_id) waiting_for_ack = {'msg': msg, 'sent_at': time.monotonic()} waiting_for_acks[self.message_id] = waiting_for_ack # we sent a message with id, so increment it self.message_id += 1 if self.message_id == 256: self.message_id = 0 try: self.ser.write(msg_bytes) except: print("Unable to send line ", msg_bytes) log.ERROR(__name__, self.request_queue, "Unable to send line ", msg_bytes) self.attempt_reconnection() line = "" try: if (self.ser.inWaiting()>0): line = self.ser.readline() except: self.attempt_reconnection() if line == "": continue try: line = line[:-2] # strip out '\r\n' checksum = int(line[-1]) # get raw checksum value line = line[:-1] calculated_checksum = proto.compute_LRC(line) id = line[-2] line = line[:-2] line = line.decode('ascii') tokens = line.split('=') key = tokens[0] val = tokens[1] if checksum != calculated_checksum: print(line) print("Checksum does not match, discard") print("key: {}," "val: {}," "checksum: {}, " "calculated_checksum: {}".format(key, int(val), checksum, calculated_checksum)) continue print("Received message: {}".format(line)) if line.startswith(proto.ack + '='): print("Received ack for id {}".format(id)) del waiting_for_acks[id] if line.startswith(proto.alarm + '='): val = tokens[1] self.alarm_queue.put({'type': 'ALARM', 'val': int(float(val)), 'source': 'serial'}) # acknowledge receipt print('Send ACK for id: {}'.format(id)) msg_ack_bytes = proto.construct_ack_message(id) try: self.ser.write(msg_ack_bytes) except: print("Unable to send line ", msg_ack_bytes) log.ERROR(__name__, self.request_queue, "Unable to send line ", msg_ack_bytes) # handle measurements for msgtype in proto.measurements: if line.startswith((msgtype + '=')): val = tokens[1] self.queue_put(msgtype, val, datetime.utcnow()) # handle settings for msgtype in proto.settings: if line.startswith((msgtype + '=')): val = tokens[1] if proto.settings_values[msgtype] != val: # send to GUI self.request_queue.put({'type': 'setting', 'key': msgtype, 'value': float(val)}) # acknowledge receipt print('Send ACK for id: {}'.format(id)) msg_ack_bytes = proto.construct_ack_message(id) try: self.ser.write(msg_ack_bytes) except: print("Unable to send line ", msg_ack_bytes) log.ERROR(__name__, self.request_queue, "Unable to send line ", msg_ack_bytes) for msgtype in proto.internal_settings: if line.startswith((msgtype + "=")): print("Received internal settings parameter {}".format(msgtype)) # resend messages waiting for ack now = time.monotonic() delete = [] for waiting_message in waiting_for_acks.items(): if waiting_message[1]['sent_at'] + 1 < now: #throws error # resend message print("outgoing message: {}", waiting_message[1]['msg']) self.out_queue.put(waiting_message[1]['msg']) delete.append(waiting_message[0]) for i in delete: del waiting_for_acks[i] except Exception as e: print(e) log.ERROR(__name__, self.request_queue, "Exception occurred = {}".format(e)) traceback.print_exc()
def run(self, name): print("[INFO] Starting {}".format(name)) log.INFO(__name__, self.request_queue, "Starting {}".format(name)) # Only start MongoClient after fork() # and each child process should have its own instance of the client try: self.client = MongoClient(self.addr) except errors.ConnectionFailure: print( "[ERROR] Unable to connect, client will attempt to reconnect") log.ERROR(__name__, self.request_queue, "Unable to connect, client will attempt to reconnect") self.db = self.client.beademing self.sound_player = SoundPlayer('assets/beep.wav', 0, 0) while True: try: self.alarm_bits = AlarmBits.NONE.value data_p, data_TPRES = self.last_n_data('PRES') pressure_monitor = PressureMonitor(data_p, data_TPRES) data_v, data_TPRES = self.last_n_data('VOL') volume_monitor = VolumeMonitor(data_v, data_TPRES) # BT: Below Threshold # AT Above Threshold # BPM - # Respiratory rate (RR) breathing_cycle_per_minute, number_of_breathing_cycle, average_dtime_breathing_cycle = pressure_monitor.get_nbr_bpm( ) if abs(breathing_cycle_per_minute - self.settings['RR']) > 0.50: print("[WARNING] Breathing at {} per minute".format( breathing_cycle_per_minute)) self.alarm_bits = self.alarm_bits | AlarmBits.DATABASE_PROCESSING_PRESSURE_BPM_BT.value # performance 'IE', # Inspiration/Expiration (N for 1/N) # in the function definition used as default values 2.75 / 10 seconds nbr_ie_ratio_BT, nbr_dtinhale_AT, nbr_dtexhale_AT = pressure_monitor.analyze_inhale_exhale_time( threshold_ratio_ie=self.settings['IE'], threshold_dt_ie=10) if False: # nbr_ie_ratio_BT > 0: print("[WARNING] # Respiratory rate below threshold : {} ". format(nbr_ie_ratio_BT)) self.alarm_bits = self.alarm_bits | AlarmBits.DATABASE_PROCESSING_PRESSURE_IE_RATIO_BT.value if False: # nbr_dtinhale_AT > 0 or nbr_dtexhale_AT > 0: print( "[WARNING] # inhale time above 10s : {} and # exhale time above 10s :{} " .format(nbr_dtinhale_AT, nbr_dtexhale_AT)) self.alarm_bits = self.alarm_bits | AlarmBits.DATABASE_PROCESSING_PRESSURE_TIME_INHALE_EXHALE_AT.value # Pressure performance Tracking -- Peak Pressure PK and ADPK Allowed deviation Peak Pressure # in the function defaults values are 51 / 3 / (5 for data points) nbr_dp_AT, dp_list = pressure_monitor.check_pressure_tracking_performance( pressure_desired=self.settings['PK'], threshold_dp=self.settings['ADPK'], nbr_data_point=5) if False: # nbr_dp_AT > 3: print( "[WARNING] # Pressure deviate during inhale {}".format( nbr_dp_AT)) self.alarm_bits = self.alarm_bits | AlarmBits.DATABASE_PROCESSING_PRESSURE_DP_AT.value # Pressure below peep value 'PP', # PEEP (positive end expiratory pressure) # 'ADPP', # Allowed deviation PEEP # in the function defaults values are 10/5 dp_peep_above_threshold, p_0200, p_0250 = pressure_monitor.detect_pressure_below_peep( peep_value=self.settings['PP'], threshold_dp_peep=self.settings['ADPP'], nbr_data_point=35) if False: # dp_peep_above_threshold > 0: print("[WARNING] # Pressure below peep level detected {}". format(dp_peep_above_threshold)) self.alarm_bits = self.alarm_bits | AlarmBits.DATABASE_PROCESSING_PRESSURE_DP_PEEP_AT.value """ # TODO confirm that this function is no longer needed # TODO if yes alarm value need to be changed then # Detect when the pressure_peak_overshoot # default values are 51 / 3 nbr_pressure_overshoot_AT, overshoot_pressure_list = pressure_monitor.pressure_peak_overshoot(pressure_desired=self.settings['PK'], threshold_dp_overshoot=self.settings['ADPK'], nbr_data_point=10) if nbr_pressure_overshoot_AT > 0: print("[WARNING] Pressure peak overshoot {}".format(nbr_pressure_overshoot_AT)) self.alarm_bits = self.alarm_bits | int('00100000', 2) # frank will define these bits, example for now 8-bit """ # Detect when the pressure peak of breathing cycle is not in the allowed range defined # default values are PK = 51 / ADPK = 3 pressure_AT_BT, val_max_pressure, val_min_inhale_pressure = pressure_monitor.pressure_peak_too_low_high( pressure_desired=self.settings['PK'], threshold_dp=self.settings['ADPK']) if pressure_AT_BT > 0: print("[WARNING] # Pressure outside the allowed range {}". format(pressure_AT_BT)) self.alarm_bits = self.alarm_bits | AlarmBits.DATABASE_PROCESSING_PRESSURE_AT_BT.value # desired volume VT / allowed deviation volume ADVT # function to find the peak volume ==>> at the begining peak of the cycle volume_AT_BT, val_max_volume = volume_monitor.volume_peak_too_low_high( volume_desired=self.settings['VT'], threshold_dv=self.settings['ADVT']) if volume_AT_BT > 0: print("[WARNING] # Volume outside the allowed range {}". format(volume_AT_BT)) self.alarm_bits = self.alarm_bits | AlarmBits.DATABASE_PROCESSING_VOLUME_AT_BT.value # function to check volume near 0 ==>> at the end of every cycle # TODO do we have in the settings a value for the threshold_dv_zero? if we need to find value 0 set then the threshold to 0 volome_not_near_zero_ebc, val_min_volume = volume_monitor.detect_volume_not_near_zero_ebc( threshold_dv_zero=50) if volome_not_near_zero_ebc > 0: print( "[WARNING] Volume not near zero at the end of breathing cycle {}" .format(volome_not_near_zero_ebc)) self.alarm_bits = self.alarm_bits | AlarmBits.DATABASE_PROCESSING_VOLUME_NOT_NEAR_ZERO_EBC.value if self.alarm_bits > 0: self.alarm_queue.put({ 'type': proto.alarm, 'val': self.alarm_bits, 'source': 'processing' }) #play an alarm print('play beep') if self.previous_alarm_bits == 0: if self.sound_player.is_alive(): self.sound_player.terminate() self.sound_player.join() self.sound_player = SoundPlayer( 'assets/beep.wav', -1, 0.200) self.sound_player.start() elif self.alarm_bits == 0 and self.previous_alarm_bits != 0: print('stop beep') if self.sound_player.is_alive(): self.sound_player.terminate() self.sound_player.join() if self.settings['MT'] == 0 and self.previous_mute_setting != 0: print('play beep MT') if self.alarm_bits > 0: if self.sound_player.is_alive(): self.sound_player.terminate() self.sound_player.join() self.sound_player = SoundPlayer( 'assets/beep.wav', -1, 0.200) self.sound_player.start() elif self.settings[ 'MT'] == 1 and self.previous_mute_setting == 0: print('stop beep MT') if self.sound_player.is_alive(): self.sound_player.terminate() self.sound_player.join() self.previous_mute_setting = self.settings['MT'] self.previous_alarm_bits = self.alarm_bits averageIE = pressure_monitor.get_IE() averagePressurePlateau = pressure_monitor.get_PressurePlateau() volumelastMinute = volume_monitor.get_TidalVolume_lastMinute() print("*" * 21) print("[INFO] Processing Settings", self.settings) print("[INFO] BPM = {}".format(breathing_cycle_per_minute)) print( "[INFO] # IE_ratio_BT = {}, # dt_inhale_AT = {}, # dt_exhale_AT = {} " .format(nbr_ie_ratio_BT, nbr_dtinhale_AT, nbr_dtexhale_AT)) print("[INFO] # pressure desired not reached {}".format( nbr_dp_AT)) print("[INFO] # pressure below peep+dp = {} ".format( dp_peep_above_threshold)) print("[INFO - OK] # peak pressure not in allowed range = {}". format(pressure_AT_BT)) print( "[INFO] Max pressure and min pressure during inhale time = {}" .format(val_max_pressure)) print("[INFO - OK] # peak volume not in allowed range = {}". format(volume_AT_BT)) print("[INFO] Max volume during last breathing cycle= {}". format(val_max_volume)) print("[INFO] # volume not near zero at ebc = {} ".format( volome_not_near_zero_ebc)) print("[INFO] the average IE = {} ".format(averageIE)) print("[INFO] the average PressurePlateau = {} ".format( averagePressurePlateau)) print("[INFO] the average PressurePlateau = {} ".format( volumelastMinute)) print("*" * 21) print("alarm_bits ", hex(self.alarm_bits)) log.INFO(__name__, self.request_queue, "BPM = {}".format(breathing_cycle_per_minute)) log.INFO( __name__, self.request_queue, "# IE_ratio_BT = {}, # dt_inhale_AT = {}, # dt_exhale_AT = {} " .format(nbr_ie_ratio_BT, nbr_dtinhale_AT, nbr_dtexhale_AT)) log.INFO(__name__, self.request_queue, "# pressure desired not reached {}".format(nbr_dp_AT)) log.INFO( __name__, self.request_queue, "# pressure below peep+dp = {} ".format( dp_peep_above_threshold)) log.INFO( __name__, self.request_queue, "# peak pressure not in allowed range = {}".format( pressure_AT_BT)) log.INFO( __name__, self.request_queue, "# peak volume not in allowed range = {}".format( volume_AT_BT)) log.INFO( __name__, self.request_queue, "# volume not near zero at ebc = {} ".format( volome_not_near_zero_ebc)) except Exception as e: print("[INFO] Processing Settings", self.settings) print('[WARNING] Exception occurred: ', e) log.ERROR(__name__, self.request_queue, "Exception occurred = {}".format(e)) self.alarm_bits = self.alarm_bits | AlarmBits.DATABASE_PROCESSING_EXCEPTION.value self.alarm_queue.put({ 'type': proto.alarm, 'val': self.alarm_bits, 'source': 'processing' }) time.sleep(0.5)