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)
Beispiel #3
0
    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
Beispiel #4
0
    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))
Beispiel #5
0
    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()
Beispiel #6
0
    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)