def __init__(self, packetString=None, header=None, data=None, checkCRC=True): if (packetString != None): # Sanity check packetStringLength = len(packetString) if (packetStringLength < 4): raise InvalidPacketFormatError( \ 'Impossible packet, must have a packet of at least 4 bytes but got {0}' \ .format(packetStringLength)) # The string can either be bytes or an actual string # Force it to a string if that is the case. if (type(packetString) == str): packetString = packetString.encode('iso-8859-1') # Extract the header information self.headerLength = 4 headerString = packetString[:self.headerLength] ctrlByte, packetLength, crc, command \ = struct.unpack(Formatting.CommandData.Header, headerString) # Extract the value from the subsystem byte subSystem = ctrlByte & BitMask.SubSystem # Check if the response byte is an acknowledge packetTypeCode = ctrlByte & BitMask.PacketType packetType = packetTypeCode >> BitPosition.PacketType # See if the packet is a response or a command packet if (packetType == PacketType.Command): raise InvalidPacketFormatError('Cannot create a response packet with the string of a command packet.') self.header = NebHeader(subSystem, packetType, command, crc, packetLength) # Extract the data substring dataString = packetString[self.headerLength:self.headerLength + packetLength] # Perform CRC of data bytes if (checkCRC): calculatedCRC = nebUtilities.genNebCRC8(bytearray(packetString)) if calculatedCRC != self.header.crc: raise CRCError(calculatedCRC, self.header.crc) if packetType == PacketType.Ack: self.data = AckData() else: # Build the data object based on the subsystem and command. self.data = ResponsePacketDataConstructors[subSystem][self.header.command](dataString) elif (header != None and data != None): self.header = header self.data = data
def __init__(self, subSystem, commandType, enable=True, **kwargs): # Logic for determining which type of command packet it is based on the header if subSystem == SubSystem.Debug and commandType == Commands.Debug.UnitTestMotionData: self.data = NebUnitTestMotionDataCommandData(kwargs['timestamp'], kwargs['accel'],\ kwargs['gyro'], kwargs['mag']) elif subSystem == SubSystem.Debug and commandType == Commands.Debug.InterfaceState: self.data = NebDataPortState(enable, kwargs['interface']) elif subSystem == SubSystem.Motion and commandType == Commands.Motion.Downsample: self.data = NebDownsampleCommandData(enable) elif subSystem == SubSystem.Motion and commandType == Commands.Motion.AccRange: self.data = NebAccRangeCommandData(enable) elif subSystem == SubSystem.Storage and commandType == Commands.Storage.Playback : self.data = NebFlashPlaybackCommandData(enable, kwargs['sessionID']) elif subSystem == SubSystem.Storage and commandType == Commands.Storage.SessionInfo: self.data = NebFlashSessionInfoCommandData(kwargs['sessionID']) elif subSystem == SubSystem.EEPROM: if commandType == Commands.EEPROM.Read: self.data = NebEEPROMCommandData(False, kwargs['pageNumber']) elif commandType == Commands.EEPROM.Write : self.data = NebEEPROMCommandData(True, kwargs['pageNumber'], kwargs['dataBytes']) elif subSystem == SubSystem.LED and commandType == Commands.LED.SetVal: self.data = NebSetLEDCommandData(kwargs['ledValueTupleList']) elif subSystem == SubSystem.LED and commandType == Commands.LED.GetVal: self.data = NebGetLEDCommandData(kwargs['ledIndices']) else: self.data = NebCommandData(enable) self.header = NebHeader(subSystem, PacketType.Command, commandType, length=len(self.data.encode())) # Perform CRC calculation self.header.crc = nebUtilities.crc8(bytearray(self.header.encode() + self.data.encode()))
def createResponsePacket(self, subSystem, commands, data, dataString): crc = nebUtilities.crc8(bytearray(dataString)) header = NebHeader(subSystem, False, commands, crc, len(dataString)) responsePacket = NebResponsePacket(packetString=None, header=header, data=data, checkCRC=False) responsePacket.header.crc = nebUtilities.genNebCRC8(bytearray(responsePacket.stringEncode())) return responsePacket
class NebResponsePacket(object): """docstring for NebResponsePacket""" @staticmethod def createResponsePacket(self, subSystem, commands, data, dataString): crc = nebUtilities.crc8(bytearray(dataString)) header = NebHeader(subSystem, False, commands, crc, len(dataString)) responsePacket = NebResponsePacket(packetString=None, header=header, data=data, checkCRC=False) responsePacket.header.crc = nebUtilities.genNebCRC8(bytearray(responsePacket.stringEncode())) return responsePacket @classmethod def createEmptyResponsePacket(cls, subSystem, command): garbage = ('\000' * 16).encode('utf-8') data = BlankData(garbage) dataString = data.encode() return cls.createResponsePacket(cls, subSystem, command, data, dataString) @classmethod def createMAGResponsePacket(cls, timestamp, mag, accel): data = MAGData(timestamp, mag, accel) dataString = data.encode() return cls.createResponsePacket(cls, SubSystem.Motion, Commands.Motion.MAG, data, dataString) @classmethod def createIMUResponsePacket(cls, timestamp, accel, gyro): data = IMUData(timestamp, accel, gyro) dataString = data.encode() return cls.createResponsePacket(cls, SubSystem.Motion, Commands.Motion.IMU, data, dataString) @classmethod def createEulerAngleResponsePacket(cls, timestamp, yaw, pitch, roll, demoHeading=0.0): # Multiply the euler angle values by 10 to emulate the firmware behavior yaw = int(yaw * 10) pitch = int(pitch * 10) roll = int(roll * 10) demoHeading = int(demoHeading * 10) garbage = '\000\000\000\000'.encode('utf-8') dataString = struct.pack(Formatting.Data.Euler, int(timestamp), yaw, pitch, roll, demoHeading, garbage) data = EulerAngleData(dataString) return cls.createResponsePacket(cls, SubSystem.Motion, Commands.Motion.EulerAngle, data, dataString) @classmethod def createPedometerResponsePacket(cls, timestamp, stepCount, stepsPerMinute, walkingDirection): # Multiply the walking direction value by 10 to emulate the firmware behavior walkingDirection = int(walkingDirection * 10) garbage = ('\000' * 7).encode('utf-8') dataString = struct.pack(Formatting.Data.Pedometer, timestamp, stepCount, \ stepsPerMinute, walkingDirection, garbage) data = PedometerData(dataString) return cls.createResponsePacket(cls, SubSystem.Motion, Commands.Motion.Pedometer, data, dataString) @classmethod def createRotationResponsePacket(cls, timestamp, rotationCount, rpm): garbage = ('\000' * 6).encode('utf-8') dataString = struct.pack(Formatting.Data.RotationInfo, timestamp, rotationCount, \ rpm, garbage) data = RotationData(dataString) return cls.createResponsePacket(cls, SubSystem.Motion, Commands.Motion.RotationInfo, data, dataString) def __init__(self, packetString=None, header=None, data=None, checkCRC=True): if (packetString != None): # Sanity check packetStringLength = len(packetString) if (packetStringLength < 4): raise InvalidPacketFormatError( \ 'Impossible packet, must have a packet of at least 4 bytes but got {0}' \ .format(packetStringLength)) # The string can either be bytes or an actual string # Force it to a string if that is the case. if (type(packetString) == str): packetString = packetString.encode('iso-8859-1') # Extract the header information self.headerLength = 4 headerString = packetString[:self.headerLength] ctrlByte, packetLength, crc, command \ = struct.unpack(Formatting.CommandData.Header, headerString) # Extract the value from the subsystem byte subSystem = ctrlByte & BitMask.SubSystem # Check if the response byte is an acknowledge packetTypeCode = ctrlByte & BitMask.PacketType packetType = packetTypeCode >> BitPosition.PacketType # See if the packet is a response or a command packet if (packetType == PacketType.Command): raise InvalidPacketFormatError('Cannot create a response packet with the string of a command packet.') self.header = NebHeader(subSystem, packetType, command, crc, packetLength) # Extract the data substring dataString = packetString[self.headerLength:self.headerLength + packetLength] # Perform CRC of data bytes if (checkCRC): calculatedCRC = nebUtilities.genNebCRC8(bytearray(packetString)) if calculatedCRC != self.header.crc: raise CRCError(calculatedCRC, self.header.crc) if packetType == PacketType.Ack: self.data = AckData() else: # Build the data object based on the subsystem and command. self.data = ResponsePacketDataConstructors[subSystem][self.header.command](dataString) elif (header != None and data != None): self.header = header self.data = data def isPacketError(self): return self.header.packetType == PacketType.ErrorLogResp def isPacketValid(self, packetType, subSystem, command): return self.isPacketHeaderValid(packetType, subSystem, command) def isPacketHeaderValid(self, packetType, subSystem, command): valid = (self.header.packetType == packetType) valid &= (self.header.subSystem == subSystem) valid &= (self.header.command == command) return valid def stringEncode(self): headerStringCode = self.header.encode() dataStringCode = self.data.encode() return headerStringCode + dataStringCode def __str__(self): stringFormat = "header = [{0}] data = [{1}]" stringDescriptor = stringFormat.format(self.header, self.data) return stringDescriptor