docs: def _parse_message(self, data):
          """
          Parse the message from the device.
  
          :param data: message data
          :type data: string
  
          :raises: :py:class:`~alarmdecoder.util.InvalidMessageError`
          """
          match = self._regex.match(str(data))
  
          if match is None:
              raise InvalidMessageError('Received invalid message: {0}'.format(data))
  
          header, self.bitfield, self.numeric_code, self.panel_data, alpha = match.group(1, 2, 3, 4, 5)
  
          is_bit_set = lambda bit: not self.bitfield[bit] == "0"
  
          self.ready = is_bit_set(1)
          self.armed_away = is_bit_set(2)
          self.armed_home = is_bit_set(3)
          self.backlight_on = is_bit_set(4)
          self.programming_mode = is_bit_set(5)
          self.beeps = int(self.bitfield[6], 16)
          self.zone_bypassed = is_bit_set(7)
          self.ac_power = is_bit_set(8)
          self.chime_on = is_bit_set(9)
          self.alarm_event_occurred = is_bit_set(10)
          self.alarm_sounding = is_bit_set(11)
          self.battery_low = is_bit_set(12)
          self.entry_delay_off = is_bit_set(13)
          self.fire_alarm = is_bit_set(14)
          self.check_zone = is_bit_set(15)
          self.perimeter_only = is_bit_set(16)
          self.system_fault = is_bit_set(17)
          if self.bitfield[18] in list(PANEL_TYPES):
              self.panel_type = PANEL_TYPES[self.bitfield[18]]
          # pos 20-21 - Unused.
          self.text = alpha.strip('"')
          self.mask = int(self.panel_data[3:3+8], 16)
  
          if self.panel_type in (ADEMCO, DSC):
              if int(self.panel_data[19:21], 16) & 0x01 > 0:
                  # Current cursor location on the alpha display.
                  self.cursor_location = int(self.panel_data[21:23], 16)