Main method to read from buffer. Optionally pass in device to
        only get response from that device

def get_buffer_status(self, device_from=None):
        """Main method to read from buffer. Optionally pass in device to
        only get response from that device"""
        device_from = device_from or ''

        # only used if device_from passed in
        return_record = OrderedDict()
        return_record['success'] = False
        return_record['error'] = True

        command_url = self.hub_url + '/buffstatus.xml'
        self.logger.info("get_buffer_status: %s", command_url)

        response = self.get_direct_command(command_url)
        raw_text = response.text
        raw_text = raw_text.replace('<response><BS>', '')
        raw_text = raw_text.replace('</BS></response>', '')
        raw_text = raw_text.strip()
        buffer_length = len(raw_text)
        self.logger.info('get_buffer_status: Got raw text with size %s and contents: %s',
                         buffer_length, raw_text)

        if buffer_length == 202:
            # 2015 hub
            # the last byte in the buffer indicates where it stopped writing.
            # checking for text after that position would show if the buffer
            # has overlapped and allow ignoring the old stuff after
            buffer_end = raw_text[-2:]
            buffer_end_int = int(buffer_end, 16)
            raw_text = raw_text[0:buffer_end_int]
            self.logger.info('bufferEnd hex %s dec %s', buffer_end, buffer_end_int)
            self.logger.info('get_buffer_status: non wrapped %s', raw_text)

        self.buffer_status = OrderedDict()

        self.buffer_status['error'] = False
        self.buffer_status['success'] = True
        self.buffer_status['message'] = ''
        self.buffer_status['msgs'] = []

        buffer_contents = StringIO(raw_text)

        while True:

            msg = buffer_contents.read(4)
            if (len(msg) < 4) or (msg == '') or (msg == '0000'):
                break

            #im_start = msg[0:2]
            im_cmd = msg[2:4]

            response_record = OrderedDict()
            response_record['im_code'] = im_cmd

            # Standard Message Received
            if im_cmd == '50':
                msg = msg + buffer_contents.read(18)
                response_record['im_code_desc'] = 'Standard Message Received'
                response_record['raw'] = msg
                response_record['id_from'] = msg[4:10]
                # direct id high, group group_id, broadcast cat
                response_record['id_high'] = msg[10:12]
                # direct id mid, broadcast subcat
                response_record['id_mid'] = msg[12:14]
                # direct id low, broadcast firmware version
                response_record['id_low'] = msg[14:16]
                # 2 ack, 8 broadcast
                response_record['flag1'] = msg[16:17]
                # hop count B
                response_record['flag2'] = msg[17:18]
                # direct cmd, broadcast 01, status db delta
                response_record['cmd1'] = msg[18:20]
                # direct cmd 2, broadcast 00, status on level
                response_record['cmd2'] = msg[20:22]

            # Extended Mesage Received
            elif im_cmd == '51':
                msg = msg + buffer_contents.read(46)

                response_record['im_code_desc'] = 'Extended Message Received'
                response_record['raw'] = msg
                response_record['id_from'] = msg[4:10]
                # direct id high, group group_id, broadcast cat
                response_record['id_high'] = msg[10:12]
                # direct id mid, broadcast subcat
                response_record['id_mid'] = msg[12:14]
                # direct id low, broadcast firmware version
                response_record['id_low'] = msg[14:16]
                # 2 ack, 8 broadcast + hop count B
                response_record['flags'] = msg[16:18]
                # direct cmd, broadcast 01, status db delta
                response_record['cmd1'] = msg[18:20]
                # direct cmd 2, broadcast 00, status on level
                response_record['cmd2'] = msg[20:22]
                response_record['user_data_1'] = msg[22:24]
                response_record['user_data_2'] = msg[24:26]
                response_record['user_data_3'] = msg[26:28]
                response_record['user_data_4'] = msg[28:30]
                response_record['user_data_5'] = msg[30:32]
                response_record['user_data_6'] = msg[32:34]
                response_record['user_data_7'] = msg[34:36]
                response_record['user_data_8'] = msg[36:38]
                response_record['user_data_9'] = msg[38:40]
                response_record['user_data_10'] = msg[40:42]
                response_record['user_data_11'] = msg[42:44]
                response_record['user_data_12'] = msg[44:46]
                response_record['user_data_13'] = msg[46:48]
                response_record['user_data_14'] = msg[48:50]

            # X10 Received (not implemented)
            elif im_cmd == '52':
                self.logger.error('Not implemented handling of 0252 X10 Received')
                break

            # ALL-Linking Completed
            elif im_cmd == '53':
                msg = msg = buffer_contents.read(16)

                response_record['im_code_desc'] = 'ALL-Linking Completed'
                response_record['raw'] = msg
                response_record['link_status'] = msg[4:6]

                if response_record['link_status'] == '00':
                    response_record['link_status_desc'] = 'IM is Responder'
                elif response_record['link_status'] == '01':
                    response_record['link_status_desc'] = 'IM is Controller'
                elif response_record['link_status'] == 'FF':
                    response_record['link_status_desc'] = 'Link Deleted'

                response_record['group'] = msg[6:8]
                response_record['id_high'] = msg[8:10]
                response_record['id_mid'] = msg[10:12]
                response_record['id_low'] = msg[12:14]
                response_record['dev_cat'] = msg[14:16]
                response_record['dev_subcat'] = msg[16:18]
                response_record['dev_firmware_rev'] = msg[18:20] # or FF for newer devices

            # Button Event Report
            elif im_cmd == '54':
                msg = msg + buffer_contents.read(2)

                response_record['im_code_desc'] = 'Button Event Report'
                response_record['raw'] = msg
                response_record['report_type'] = msg[4:6]
                if response_record['report_type'] == "02":
                    response_record['report_type_desc'] = "IM's SET Button tapped"
                elif response_record['report_type'] == "03":
                    response_record['report_type_desc'] = "IM's SET Button held"
                elif response_record['report_type'] == "04":
                    response_record['report_type_desc'] = "IM's SET Button released after hold"
                elif response_record['report_type'] == "12":
                    response_record['report_type_desc'] = "IM's Button 2 tapped"
                elif response_record['report_type'] == "13":
                    response_record['report_type_desc'] = "IM's Button 2 held"
                elif response_record['report_type'] == "14":
                    response_record['report_type_desc'] = "IM's Button 2 released after hold"
                elif response_record['report_type'] == "22":
                    response_record['report_type_desc'] = "IM's Button 3 tapped"
                elif response_record['report_type'] == "23":
                    response_record['report_type_desc'] = "IM's Button 3 held"
                elif response_record['report_type'] == "24":
                    response_record['report_type_desc'] = "IM's Button 3 released after hold"

            # User Reset Detected
            elif im_cmd == '55':
                response_record['im_code_desc'] = 'User Reset Detected'
                response_record['raw'] = msg
                response_record['im_code_desc2'] = "User pushed and held IM's " \
                                                   "SET Button on power up"

            # ALL-Link Cleanup Failure Report
            elif im_cmd == '56':
                msg = msg + buffer_contents.read(10)

                response_record['im_code_desc'] = 'ALL-Link Cleanup Failure Report'
                response_record['raw'] = msg
                response_record['group'] = msg[4:6]
                # 01 means member did not acknlowedge all-link cleanup cmd
                response_record['ack'] = msg[6:8]
                response_record['id_high'] = msg[8:10]
                response_record['id_mid'] = msg[10:12]
                response_record['id_low'] = msg[12:14]

            # ALL-Link Record Response
            elif im_cmd == '57':
                msg = msg + buffer_contents.read(20)

                response_record['im_code_desc'] = 'ALL-Link Record Response'
                response_record['raw'] = msg
                response_record['flags'] = msg[4:6] # hub dev manual p 39
                response_record['group'] = msg[6:8]
                response_record['id_high'] = msg[8:10]
                response_record['id_mid'] = msg[10:12]
                response_record['id_low'] = msg[12:14]
                response_record['link_data_1'] = msg[14:16]
                response_record['link_data_2'] = msg[16:18]
                response_record['link_data_3'] = msg[18:20]

            # ALL-Link Cleanup Status Report
            elif im_cmd == '58':
                msg = msg + buffer_contents.read(2)

                response_record['im_code_desc'] = 'ALL-Link Cleanup Status Report'
                response_record['raw'] = msg
                response_record['cleanup_status'] = msg[4:6]
                if response_record['cleanup_status'] == '06':
                    response_record['cleanup_status_desc'] = 'ALL-Link Cleanup ' \
                                                            'sequence completed'
                elif response_record['cleanup_status'] == '15':
                    response_record['cleanup_status_desc'] = 'ALL-Link Cleanup ' \
                                                             'sequence aborted due ' \
                                                             'to INSTEON traffic'

            # Database Record Found
            elif im_cmd == '59':
                msg = msg + buffer_contents.read(18)

                response_record['im_code_desc'] = 'Database Record Found'
                response_record['raw'] = msg
                response_record['address_low'] = msg[4:6]
                response_record['record_flags'] = msg[6:8]
                response_record['group'] = msg[8:10]
                response_record['id_high'] = msg[10:12]
                response_record['id_mid'] = msg[12:14]
                response_record['id_low'] = msg[14:16]
                response_record['link_data_1'] = msg[16:18]
                response_record['link_data_2'] = msg[18:20]
                response_record['link_data_3'] = msg[20:22]

            # Get IM Info
            elif im_cmd == '60':
                msg = msg + buffer_contents.read(14)

                response_record['im_code_desc'] = 'Get IM Info'
                response_record['raw'] = msg
                response_record['id_high'] = msg[4:6]
                response_record['id_mid'] = msg[6:8]
                response_record['id_low'] = msg[8:10]
                response_record['dev_cat'] = msg[10:12]
                response_record['dev_subcat'] = msg[12:14]
                response_record['dev_firmware_rev'] = msg[14:16]
                response_record['ack_or_nak'] = msg[16:18] # 06 ack

            # Send ALL-Link Command
            elif im_cmd == '61':
                msg = msg + buffer_contents.read(8)

                response_record['im_code_desc'] = 'Send ALL-Link Command'
                response_record['raw'] = msg
                response_record['group'] = msg[4:6]
                response_record['cmd'] = msg[6:8]
                response_record['broadcast_cmd2'] = msg[8:10] # FF or 00
                response_record['ack_or_nak'] = msg[10:12] # 06 ack

            # Send Message (Pass through command to PLM)
            elif im_cmd == '62':
                msg = msg + buffer_contents.read(8)
                response_record['id'] = msg[4:10]
                response_record['flags'] = msg[10:12]

                # Standard Message
                if response_record['flags'][0] == '0':
                    response_record['im_code_desc'] = 'Send Standard Message'
                    msg = msg + buffer_contents.read(6)
                    response_record['cmd1'] = msg[12:14]
                    response_record['cmd2'] = msg[14:16]
                    response_record['ack_or_nak'] = msg[16:18] # 06 ack 15 nak

                # Extended Message
                elif response_record['flags'][0] == '1':
                    response_record['im_code_desc'] = 'Send Extended Message'
                    msg = msg + buffer_contents.read(34)
                    response_record['cmd1'] = msg[12:14]
                    response_record['cmd2'] = msg[14:16]
                    response_record['user_data_1'] = msg[16:18]
                    response_record['user_data_2'] = msg[18:20]
                    response_record['user_data_3'] = msg[20:22]
                    response_record['user_data_4'] = msg[22:24]
                    response_record['user_data_5'] = msg[24:26]
                    response_record['user_data_6'] = msg[26:28]
                    response_record['user_data_7'] = msg[28:30]
                    response_record['user_data_8'] = msg[30:32]
                    response_record['user_data_9'] = msg[32:34]
                    response_record['user_data_10'] = msg[34:36]
                    response_record['user_data_11'] = msg[36:38]
                    response_record['user_data_12'] = msg[38:40]
                    response_record['user_data_13'] = msg[40:42]
                    response_record['user_data_14'] = msg[42:44]
                    response_record['ack_or_nak'] = msg[44:46] # 06 ack 15 nak

                # Not implemented
                else:
                    self.logger.error('Not implemented, message flag %s' % response_record['flags'])

                response_record['raw'] = msg

            # Send X10 (not implemented)
            elif im_cmd == '63':
                self.logger.error('Not implemented handling of 0263 Send X10')
                break

            # Start ALL-Linking
            elif im_cmd == '64':
                msg = msg + buffer_contents.read(6)

                response_record['im_code_desc'] = 'Start ALL-Linking'
                response_record['raw'] = msg
                response_record['link_type'] = msg[4:6]

                if response_record['link_type'] == '00':
                    response_record['link_type_desc'] = 'IM is Responder'
                elif response_record['link_type'] == '01':
                    response_record['link_type_desc'] = 'IM is Controller'
                elif response_record['link_type'] == '03':
                    response_record['link_type_desc'] = 'IM is Either Responder ' \
                                                        'or Controller'
                elif response_record['link_type'] == 'FF':
                    response_record['link_type_desc'] = 'Link Deleted'

                response_record['group'] = msg[6:8]
                response_record['ack_or_nak'] = msg[8:10] # 06 ack 15 nak

            # Cancel ALL-Linking
            elif im_cmd == '65':
                msg = msg + buffer_contents.read(2)

                response_record['im_code_desc'] = 'Cancel ALL-Linking'
                response_record['raw'] = msg
                response_record['ack_or_nak'] = msg[4:6] # 06 ack 15 nak

            # Set Host Device Category
            elif im_cmd == '66':
                msg = msg + buffer_contents.read(8)

                response_record['im_code_desc'] = 'Set Host Device Category'
                response_record['raw'] = msg
                response_record['dev_cat'] = msg[4:6]
                response_record['dev_subcat'] = msg[6:8]
                response_record['dev_firmware_rev'] = msg[8:10] # or 00
                response_record['ack_or_nak'] = msg[10:12] # 06 ack 15 nak

            # Reset the IM
            elif im_cmd == '67':
                msg = msg + buffer_contents.read(2)

                response_record['im_code_desc'] = 'Reset the IM'
                response_record['raw'] = msg
                response_record['ack_or_nak'] = msg[4:6] # 06 ack 15 nak

            # Set INSTEON ACK Message Byte
            elif im_cmd == '68':
                msg = msg + buffer_contents.read(4)

                response_record['im_code_desc'] = 'Set INSTEON ACK Message Byte'
                response_record['raw'] = msg
                response_record['cmd2_data'] = msg[4:6]
                response_record['ack_or_nak'] = msg[6:8] # 06 ack 15 nak

            # Get First ALL-Link Record
            elif im_cmd == '69':
                msg = msg + buffer_contents.read(2)

                response_record['im_code_desc'] = 'Get First ALL-Link Record'
                response_record['raw'] = msg
                response_record['ack_or_nak'] = msg[4:6] # 06 ack 15 nak

            # Get Next ALL-Link Record
            elif im_cmd == '6A':
                msg = msg + buffer_contents.read(2)

                response_record['im_code_desc'] = 'Get Next ALL-Link Record'
                response_record['raw'] = msg
                response_record['ack_or_nak'] = msg[4:6] # 06 ack 15 nak

            # Set IM Configuration
            elif im_cmd == '6B':
                msg = msg + buffer_contents.read(4)

                response_record['im_code_desc'] = 'Set IM Configuration'
                response_record['raw'] = msg
                response_record['im_cfg_flags'] = msg[4:6]
                response_record['ack_or_nak'] = msg[6:8] # 06 ack 15 nak

            # Get ALL-Link Record for Sender
            elif im_cmd == '6C':
                msg = msg + buffer_contents.read(2)

                response_record['im_code_desc'] = 'Get ALL-Link Record for Sender'
                response_record['raw'] = msg
                response_record['ack_or_nak'] = msg[4:6] # 06 ack 15 nak

            # LED On
            elif im_cmd == '6D':
                msg = msg + buffer_contents.read(2)

                response_record['im_code_desc'] = 'LED On'
                response_record['raw'] = msg
                response_record['ack_or_nak'] = msg[4:6] # 06 ack 15 nak

            # LED Off
            elif im_cmd == '6E':
                msg = msg + buffer_contents.read(2)

                response_record['im_code_desc'] = 'LED Off'
                response_record['raw'] = msg
                response_record['ack_or_nak'] = msg[4:6] # 06 ack 15 nak

            # Manage ALL-Link Record
            elif im_cmd == '6F':
                msg = msg + buffer_contents.read(20)

                response_record['im_code_desc'] = 'Manage ALL-Link Record'
                response_record['raw'] = msg
                response_record['ctrl_flags'] = msg[4:6]
                response_record['record_flags'] = msg[6:8]
                response_record['group'] = msg[8:10]
                response_record['id_high'] = msg[10:12]
                response_record['id_mid'] = msg[12:14]
                response_record['id_low'] = msg[14:16]
                response_record['link_data_1'] = msg[16:18]
                response_record['link_data_2'] = msg[18:20]
                response_record['link_data_3'] = msg[20:22]
                response_record['ack_or_nak'] = msg[22:24] # 06 ack

            # Set INSTEON ACK Message Two Bytes
            elif im_cmd == '71':
                msg = msg + buffer_contents.read(6)

                response_record['im_code_desc'] = 'Set INSTEON ACK Message Two Bytes'
                response_record['raw'] = msg
                response_record['cmd1_data'] = msg[4:6]
                response_record['cmd2_data'] = msg[6:8]
                response_record['ack_or_nak'] = msg[8:10] # 06 ack

            # RF Sleep
            elif im_cmd == '72':
                msg = msg + buffer_contents.read(2)

                response_record['im_code_desc'] = 'RF Sleep'
                response_record['raw'] = msg
                response_record['ack_or_nak'] = msg[4:6] # 06 ack

            # Get IM Configuration
            elif im_cmd == '73':
                msg = msg + buffer_contents.read(8)

                response_record['im_code_desc'] = 'Get IM Configuration'
                response_record['raw'] = msg
                response_record['im_cfg_flags'] = msg[4:6]
                response_record['spare1'] = msg[6:8]
                response_record['spare2'] = msg[8:10]
                response_record['ack_or_nak'] = msg[10:12] # 06 ack

            # Cancel Cleanup
            elif im_cmd == '74':
                msg = msg + buffer_contents.read(2)

                response_record['im_code_desc'] = 'Cancel Cleanup'
                response_record['raw'] = msg
                response_record['ack_or_nak'] = msg[4:6] # 06 ack 15 nak

            # Read 8 bytes from Database
            elif im_cmd == '75':
                msg = msg + buffer_contents.read(30)

                response_record['im_code_desc'] = 'Read 8 bytes from Database'
                response_record['raw'] = msg
                response_record['db_addr_high'] = msg[4:6]
                response_record['db_addr_low'] = msg[6:8] # low nibble F, or 8
                response_record['ack_or_nak'] = msg[8:10] # 06 ack
                response_record['record'] = msg[10:34] # database record founnd
                                                       # response 12 bytes

            # Write 8 bytes to Database
            elif im_cmd == '76':
                msg = msg + buffer_contents.read(22)

                response_record['im_code_desc'] = 'Write 8 bytes to Database'
                response_record['raw'] = msg
                response_record['db_addr_high'] = msg[4:6]
                response_record['db_addr_low'] = msg[6:8] # low nibble F, or 8
                response_record['record_flags'] = msg[8:10]
                response_record['group'] = msg[10:12]
                response_record['id_high'] = msg[12:14]
                response_record['id_middle'] = msg[14:16]
                response_record['id_low'] = msg[16:18]
                response_record['link_data_1'] = msg[18:20]
                response_record['link_data_2'] = msg[20:22]
                response_record['link_data_3'] = msg[22:24]
                response_record['ack_or_nak'] = msg[24:26] # 06 ac

            # Beep
            elif im_cmd == '77':
                msg = msg + buffer_contents.read(2)

                response_record['im_code_desc'] = 'Beep'
                response_record['raw'] = msg
                response_record['ack_or_nak'] = msg[4:6] # 06 ack 15 nak

            # Set Status
            # IM reports Status in cmd2 of direct Status Request command (19)
            elif im_cmd == '78':
                msg = msg + buffer_contents.read(2)

                response_record['im_code_desc'] = 'Set Status'
                response_record['raw'] = msg
                response_record['ack_or_nak'] = msg[4:6] # 06 ack

            # Set Database Link Data for Next Link
            elif im_cmd == '79':
                msg = msg + buffer_contents.read(8)

                response_record['im_code_desc'] = 'Set Database Link Data for Next Link'
                response_record['raw'] = msg
                response_record['link_data_1'] = msg[4:6]
                response_record['link_data_2'] = msg[6:8]
                response_record['link_data_3'] = msg[8:10]
                response_record['ack_or_nak'] = msg[10:12] # 06 ack

            # Set Application Retries for New Links
            elif im_cmd == '7A':
                msg = msg + buffer_contents.read(4)

                response_record['im_code_desc'] = 'Set Application Retries for New Links'
                response_record['raw'] = msg
                response_record['num_retries'] = msg[4:6]
                response_record['ack_or_nak'] = msg[6:8] # 06 ack

            # Set RF Frequency Offset
            elif im_cmd == '7B':
                msg = msg + buffer_contents.read(4)

                response_record['im_code_desc'] = 'Set RF Frequency Offset'
                response_record['raw'] = msg
                response_record['rf_freq_offset'] = msg[4:6]
                response_record['ack_or_nak'] = msg[6:8] # 06 ack

            # Set Acknowledge for TempLinc Command (not implemented)
            elif im_cmd == '7C':
                self.logger.error('Not implemented handling of 027C Set '
                                  'Acknowledge for TempLinc command')
                break

            if response_record.get('ack_or_nak', '') == '15':
                self.buffer_status['error'] = True
                self.buffer_status['success'] = False
                self.buffer_status['message'] = 'Device returned nak'

            response_device_from = response_record.get('id_from', '')
            if device_from and device_from == response_device_from:
                return_record = response_record
                return_record['error'] = False
                return_record['success'] = True
                if 'cmd1' in response_record and 'cmd2' in response_record:
                    self.set_command_response_from_cache(response_record, device_from, response_record['cmd1'], response_record['cmd2'])

            self.buffer_status['msgs'].append(response_record)

        # Return last status from this device
        return return_record

        # Tell hub to clear buffer
        self.clear_buffer()

        #pprint.pprint(self.buffer_status)
        self.logger.debug("get_buffer_status: %s", pprint.pformat(self.buffer_status))

        return self.buffer_status