def decode(cls, raw): raw = bytearray(raw) if len(raw) < 5: raise MessageError( 'Could not decode. Message length should be >=5 bytes but was %d.' % len(raw), internal=Message.INCOMPLETE) sync, length, type_ = raw[:MSG_HEADER_SIZE] if sync != MESSAGE_TX_SYNC: raise MessageError( 'Could not decode. Expected TX sync but got 0x%.2x.' % sync, internal=Message.CORRUPTED) if len(raw) < (length + MSG_HEADER_SIZE + MSG_FOOTER_SIZE): raise MessageError( 'Could not decode. Message length should be %d but was %d.' % (length + MSG_HEADER_SIZE + MSG_FOOTER_SIZE, len(raw)), internal=Message.INCOMPLETE) msg = Message(type=type_) # pylint: disable=unexpected-keyword-arg msg.payload = raw[MSG_HEADER_SIZE:length + MSG_HEADER_SIZE] if msg.checksum != raw[length + MSG_HEADER_SIZE]: raise MessageError( 'Could not decode. Checksum should be 0x%.2x but was 0x%.2x.' % (raw[length + MSG_HEADER_SIZE], msg.checksum), internal=Message.CORRUPTED) return msg
def status(self, status): if (status > 0xFF) or (status < 0x00): raise MessageError( 'Could not set channel status. Should be 0 to 255 but was %s.' % status) self._payload[1] = status
def messageCode(self, message_code): if (message_code > 0xFF) or (message_code < 0x00): raise MessageError( 'Could not set message code. Should be 0 to 255 but was %s.' % message_code) self._payload[2] = message_code
def messageID(self, message_id): if (message_id > 0xFF) or (message_id < 0x00): raise MessageError( 'Could not set message ID. Should be 0 to 255 but was %s.' % message_id) self._payload[1] = message_id
def channelNumber(self, number): if (number > 0xFF) or (number < 0x00): raise MessageError( 'Could not set channel number. Should be 0 to 255 but was %s.' % number) self._payload[0] = number
def setStdOptions(self, num): if (num > 0xFF) or (num < 0x00): raise MessageError('Could not set std options ' \ '(out of range).') if num is None or 0x00: del self._payload[2] self._payload[2] = num
def setPayload(self, payload): if len(payload) > 9: raise MessageError( 'Could not set payload (payload too long).') self.payload = [] for byte in payload: self.payload += byte
def setAdvOptions2(self, num): if (num > 0xFF) or (num < 0x00): raise MessageError('Could not set adv options 2 ' \ '(out of range).') if len(self.payload) == 4: self.payload.append('\x00') self.payload[4] = chr(num)
def advOptions2(self, num): if (num > 0xFF) or (num < 0x00): raise MessageError( 'Could not set adv options 2. Should be 0 to 255 but was %s.' % num) if len(self._payload) == 4: self._payload.append(0) self._payload[4] = num
def set_payload(self, payload): """ A payload can be 8 bytes + 1 for the channel number. :param payload: :return: """ if len(payload) > 9: raise MessageError('Could not set payload (payload too long).') self._payload = bytearray(payload)
def get_proper_message(raw=b''): if raw is None or not len(raw): return None # print("get_proper_message raw: {}".format(encode_bytes(raw, separator=' '))) msg_id = raw[2] # print("get_proper_message msg_id: {:02X}".format(msg_id)) if msg_id == MESSAGE_CHANNEL_UNASSIGN: msg = ChannelUnassignMessage() elif msg_id == MESSAGE_CHANNEL_ASSIGN: msg = ChannelAssignMessage() elif msg_id == MESSAGE_CHANNEL_ID: msg = ChannelIDMessage() elif msg_id == MESSAGE_CHANNEL_PERIOD: msg = ChannelPeriodMessage() elif msg_id == MESSAGE_CHANNEL_SEARCH_TIMEOUT: msg = ChannelSearchTimeoutMessage() elif msg_id == MESSAGE_CHANNEL_FREQUENCY: msg = ChannelFrequencyMessage() elif msg_id == MESSAGE_CHANNEL_TX_POWER: msg = ChannelTXPowerMessage() elif msg_id == MESSAGE_NETWORK_KEY: msg = NetworkKeyMessage() elif msg_id == MESSAGE_TX_POWER: msg = TXPowerMessage() elif msg_id == MESSAGE_SYSTEM_RESET: msg = SystemResetMessage() elif msg_id == MESSAGE_CHANNEL_OPEN: msg = ChannelOpenMessage() elif msg_id == MESSAGE_CHANNEL_CLOSE: msg = ChannelCloseMessage() elif msg_id == MESSAGE_CHANNEL_REQUEST: msg = ChannelRequestMessage() elif msg_id == MESSAGE_CHANNEL_BROADCAST_DATA: msg = ChannelBroadcastDataMessage() elif msg_id == MESSAGE_CHANNEL_ACKNOWLEDGED_DATA: msg = ChannelAcknowledgedDataMessage() elif msg_id == MESSAGE_CHANNEL_BURST_DATA: msg = ChannelBurstDataMessage() elif msg_id == MESSAGE_CHANNEL_EVENT: msg = ChannelEventMessage() elif msg_id == MESSAGE_CHANNEL_STATUS: msg = ChannelStatusMessage() elif msg_id == MESSAGE_VERSION: msg = VersionMessage() elif msg_id == MESSAGE_CAPABILITIES: msg = CapabilitiesMessage() elif msg_id == MESSAGE_SERIAL_NUMBER: msg = SerialNumberMessage() elif msg_id == MESSAGE_STARTUP: msg = NotificationStartupMessage() else: raise MessageError('Could not find message handler ' \ '(unknown message type).') msg.decode(raw) return msg
def waitFor(self, foo, timeout=10): # pylint: disable=blacklisted-name messages = self.messages basetime = time() while time() - basetime < timeout: with self.lock: for emsg in messages: if self.WAIT_UNTIL(foo, emsg): messages.remove(emsg) return emsg sleep(0.001) raise MessageError("%s: timeout" % str(foo), internal=foo)
def decode(self, raw): if len(raw) < 5: raise MessageError('Could not decode (message is incomplete).') sync, length, type_ = struct.unpack('BBB', raw[:3]) if sync != MESSAGE_TX_SYNC: raise MessageError('Could not decode (expected TX sync).') if length > 9: raise MessageError('Could not decode (payload too long).') if len(raw) < (length + 4): raise MessageError('Could not decode (message is incomplete).') self.setType(type_) self.setPayload(raw[3:length + 3]) if self.getChecksum() != ord(raw[length + 3]): raise MessageError('Could not decode (bad checksum).', internal='CHECKSUM') return self.getSize()
def getHandler(self, raw=None): if raw: self.decode(raw) msg = None if self.type_ == MESSAGE_CHANNEL_UNASSIGN: msg = ChannelUnassignMessage() elif self.type_ == MESSAGE_CHANNEL_ASSIGN: msg = ChannelAssignMessage() elif self.type_ == MESSAGE_CHANNEL_ID: msg = ChannelIDMessage() elif self.type_ == MESSAGE_CHANNEL_PERIOD: msg = ChannelPeriodMessage() elif self.type_ == MESSAGE_CHANNEL_SEARCH_TIMEOUT: msg = ChannelSearchTimeoutMessage() elif self.type_ == MESSAGE_CHANNEL_FREQUENCY: msg = ChannelFrequencyMessage() elif self.type_ == MESSAGE_CHANNEL_TX_POWER: msg = ChannelTXPowerMessage() elif self.type_ == MESSAGE_NETWORK_KEY: msg = NetworkKeyMessage() elif self.type_ == MESSAGE_TX_POWER: msg = TXPowerMessage() elif self.type_ == MESSAGE_SYSTEM_RESET: msg = SystemResetMessage() elif self.type_ == MESSAGE_CHANNEL_OPEN: msg = ChannelOpenMessage() elif self.type_ == MESSAGE_CHANNEL_CLOSE: msg = ChannelCloseMessage() elif self.type_ == MESSAGE_CHANNEL_REQUEST: msg = ChannelRequestMessage() elif self.type_ == MESSAGE_CHANNEL_BROADCAST_DATA: msg = ChannelBroadcastDataMessage() elif self.type_ == MESSAGE_CHANNEL_ACKNOWLEDGED_DATA: msg = ChannelAcknowledgedDataMessage() elif self.type_ == MESSAGE_CHANNEL_BURST_DATA: msg = ChannelBurstDataMessage() elif self.type_ == MESSAGE_CHANNEL_EVENT: msg = ChannelEventMessage() elif self.type_ == MESSAGE_CHANNEL_STATUS: msg = ChannelStatusMessage() elif self.type_ == MESSAGE_VERSION: msg = VersionMessage() elif self.type_ == MESSAGE_CAPABILITIES: msg = CapabilitiesMessage() elif self.type_ == MESSAGE_SERIAL_NUMBER: msg = SerialNumberMessage() else: raise MessageError('Could not find message handler ' \ '(unknown message type).') msg.setPayload(self.getPayload()) return msg
def decode(self, raw): """ :param raw: a bytes object :return: """ if len(raw) < 5: raise MessageError('Could not decode (message is incomplete).') if checksum(raw[:len(raw) - 1]) != raw[-1]: raise MessageError('Could not decode (bad checksum).', internal='CHECKSUM') # Unpack the first 3 bytes sync = raw[0] msg_length = raw[1] msg_id = raw[2] if sync != MESSAGE_TX_SYNC: raise MessageError('Could not decode (expected TX sync).') self.sync = sync self.msg_id = msg_id self.set_payload(raw[3:msg_length + 3]) # 2 Types: Standard and Extended if msg_length > 9 and len( raw) >= 12 and raw[12] == EXTENDED_FORMAT_FLAG_BYTE: # Only valid if the message is in Flagged Extended Data Message Format self.flag_byte = EXTENDED_FORMAT_FLAG_BYTE self.is_extended_message = True elif msg_length > 9: raise MessageError('Could not decode (payload too long).') # Checks that the supplied msg_length byte == the length of the actual raw message if len(raw) < (msg_length + 4): # 4 because of sync, len, id, crc raise MessageError('Could not decode (message is incomplete).') return self.get_size()
def decode(cls, raw): raw = bytearray(raw) if len(raw) < 5: raise MessageError('Could not decode (message is incomplete).', internal=Message.INCOMPLETE) sync, length, type_ = raw[:MSG_HEADER_SIZE] if sync != MESSAGE_TX_SYNC: raise MessageError('Could not decode (expected TX sync).', internal=Message.CORRUPTED) if len(raw) < (length + MSG_HEADER_SIZE + MSG_FOOTER_SIZE): raise MessageError('Could not decode (message is incomplete).', internal=Message.INCOMPLETE) msg = Message(type=type_) # pylint: disable=unexpected-keyword-arg msg.payload = raw[MSG_HEADER_SIZE:length + MSG_HEADER_SIZE] if msg.checksum != raw[length + MSG_HEADER_SIZE]: raise MessageError('Could not decode (bad checksum).', internal=Message.CORRUPTED) return msg
def __call__(cls, *args, **kwargs): if cls.type is not None: return super(MessageType, cls).__call__(*args, **kwargs) type_ = kwargs.get('type') if type_ is None: raise RuntimeError("Message' cannot be untyped") del kwargs['type'] msgType = cls.TYPES.get(type_) if msgType is not None: return msgType(*args, **kwargs) if 0x00 <= type_ <= 0xFF: msg = super(MessageType, cls).__call__(*args, **kwargs) msg.type = type_ return msg else: raise MessageError('Could not set type (type out of range).', internal=Message.CORRUPTED)
def setSerialNumber(self, serial): if (len(serial) != 4): raise MessageError('Could not set serial number ' \ '(expected 4 bytes).') self.setPayload(serial)
def setAdvOptions(self, num): if (num > 0xFF) or (num < 0x00): raise MessageError('Could not set adv options ' \ '(out of range).') self.payload[3] = chr(num)
def setMaxNetworks(self, num): if (num > 0xFF) or (num < 0x00): raise MessageError('Could not set max networks ' \ '(out of range).') self.payload[1] = chr(num)
def setMaxChannels(self, num): if (num > 0xFF) or (num < 0x00): raise MessageError('Could not set max channels ' \ '(out of range).') self.payload[0] = chr(num)
def setVersion(self, version): if (len(version) != 9): raise MessageError('Could not set ANT version ' \ '(expected 9 bytes).') self.setPayload(version)
def serialNumber(self, serial): if len(serial) != 4: raise MessageError( 'Could not set serial number (expected 4 bytes).') self.payload = bytearray(serial)
def setMessageCode(self, message_code): if (message_code > 0xFF) or (message_code < 0x00): raise MessageError('Could not set message code ' \ '(out of range).') self.payload[2] = chr(message_code)
def setMessageID(self, message_id): if (message_id > 0xFF) or (message_id < 0x00): raise MessageError('Could not set message ID ' \ '(out of range).') self.payload[1] = chr(message_id)
def setChannelNumber(self, number): if (number > 0xFF) or (number < 0x00): raise MessageError('Could not set channel number ' \ '(out of range).') self.payload[0] = chr(number)
def setType(self, type_): if (type_ > 0xFF) or (type_ < 0x00): raise MessageError('Could not set type (type out of range).') self.type_ = type_
def setStatus(self, status): if (status > 0xFF) or (status < 0x00): raise MessageError('Could not set channel status ' \ '(out of range).') self.payload[1] = chr(status)
def payload(self, payload): if len(payload) > 9: raise MessageError('Could not set payload (payload too long).', internal=Message.MALFORMED) self._payload = payload
def advOptions(self, num): if (num > 0xFF) or (num < 0x00): raise MessageError( 'Could not set adv options. Should be 0 to 255 but was %s.' % num) self._payload[3] = num