docs: def _parse_message(self, data):
          """
          Parse the raw message from the device.
  
          :param data: message data
          :type data: string
  
          :raises: :py:class:`~alarmdecoder.util.InvalidMessageError`
          """
          try:
              header, values = data.split(':')
              address, channel, value = values.split(',')
  
              self.address = int(address)
              self.channel = int(channel)
              self.value = int(value)
  
          except ValueError:
              raise InvalidMessageError('Received invalid message: {0}'.format(data))
  
          if header == '!EXP':
              self.type = ExpanderMessage.ZONE
          elif header == '!REL':
              self.type = ExpanderMessage.RELAY
          else:
              raise InvalidMessageError('Unknown expander message header: {0}'.format(data))