protected static ESPPacket makeFromBufferLE(List <Byte> buffer, Devices lastV1Type) { if (buffer.Count == 0) { return(null); } int bufferSize = buffer.Count; if (buffer[0] != startOfFrameConstant || buffer[bufferSize - 1] != endOfFrameConstant) { return(null); } bool dataError = false; ProcessState processState = ProcessState.SOF; ESPPacket retPacket = null; byte espChecksum = 0; byte tempDest = 0; byte tempOrigin = 0; int payloadIdx = 0; for (int i = 0; i < bufferSize; i++) { byte curByte = buffer[i]; switch (processState) { case ProcessState.SOF: if (curByte != startOfFrameConstant) { dataError = true; } espChecksum += curByte; processState = ProcessState.DESTINATION; break; case ProcessState.DESTINATION: if ((curByte & destinationIdentifierBaseConstant) != destinationIdentifierBaseConstant) { dataError = true; } tempDest = curByte; espChecksum += curByte; processState = ProcessState.ORIGINATOR; break; case ProcessState.ORIGINATOR: if ((curByte & originationIdentifierBaseConstant) != originationIdentifierBaseConstant) { // This is not a valid originator dataError = true; } tempOrigin = curByte; espChecksum += curByte; processState = ProcessState.PACKET_ID; break; case ProcessState.PACKET_ID: // Make the packet retPacket = PacketFactory.getPacket(PacketIdLookup.getConstant(curByte)); if (retPacket == null) { // We couldn't build the packet so stop trying dataError = true; } else { // We have a good packet so fill it up retPacket.headerDelimter = frameDelimitedConstant; //<- We can't get here if this wasn't true // The packet length for LE is equal to the size of the buffer.. retPacket.packetLength = (byte)bufferSize; retPacket.startOfFrame = startOfFrameConstant; //<- We can't get here if this wasn't true retPacket.destinationIdentifier = tempDest; // Don't store the upper nibble of the destinations retPacket.m_destination = (byte)(tempDest - destinationIdentifierBaseConstant); // Don't store the upper nibble of the origin retPacket.originatorIdentifier = (byte)(tempOrigin - originationIdentifierBaseConstant); retPacket.packetIdentifier = curByte; // If the packet is from a V1 set the ESPPacket V1 type to the appropriate Device type. if (IsPacketFromV1(retPacket.originatorIdentifier)) { retPacket.m_valentineType = DevicesUtils.DevicesFromByteValue(retPacket.originatorIdentifier); } else { retPacket.m_valentineType = lastV1Type; } // If the last known V1 type is unknown check to see if the ESPPacket is V1connection version response. if (retPacket.m_valentineType == Devices.UNKNOWN) { if (retPacket.packetIdentifier != PacketId.respVersion.ToByteValue() || retPacket.originatorIdentifier != Devices.V1CONNECT.ToByteValue()) { // Always allow the V1connection version responses to pass through // Don't process any other data until we know what type of V1 we are working with dataError = true; if (ESPLibraryLogController.LOG_WRITE_ERROR) { //Log.e(LOG_TAG, "Ignore packet id 0x" + String.Format("%02X ", curByte) + " because the V1 type is unknown"); } } } } espChecksum += curByte; processState = ProcessState.PAYLOAD_LENGTH; break; case ProcessState.PAYLOAD_LENGTH: if (curByte != 0) { byte tmp; // If this packet is from a V1 that supports checksum, we want to decrement the payload length by 1, to make packet match packets from // Legacy and non-checksum V1's if ((retPacket.m_valentineType == Devices.VALENTINE1_LEGACY) || (retPacket.m_valentineType == Devices.VALENTINE1_WITHOUT_CHECKSUM)) { tmp = curByte; } else { // If this packet is from a V1 that supports checksum, we want to decrement the packet length by 1 // to make packet match packets from Legacy and non-checksum V1's tmp = (byte)(curByte - 1); } retPacket.payloadLength = tmp; // If payloadLength is zero, then the next byte in the buffer will be the packet checksum. For non-checksum V1 devices // the payloadLength is greater than zero so the next byte will be payload data. if (retPacket.payloadLength == 0) { processState = ProcessState.PACKET_CHEKSUM; } else { retPacket.payloadData = new byte[retPacket.payloadLength]; processState = ProcessState.PAYLOAD; } // Always include the payload length in the packet data. espChecksum += curByte; } else { // There is no payload data so go to the end of frame. processState = ProcessState.EOF; } break; case ProcessState.PAYLOAD: retPacket.payloadData[payloadIdx] = curByte; payloadIdx++; // Update the ESP checksum. espChecksum += curByte; // If we have reached the end of the payload data, move on to the next byte in the buffer. if (payloadIdx == retPacket.payloadLength) { if ((retPacket.m_valentineType == Devices.VALENTINE1_LEGACY) || (retPacket.m_valentineType == Devices.VALENTINE1_WITHOUT_CHECKSUM)) { // Get the EOF byte next processState = ProcessState.EOF; } else { processState = ProcessState.PACKET_CHEKSUM; } } break; case ProcessState.PACKET_CHEKSUM: if (espChecksum != curByte) { // The checksum does not match dataError = true; if (ESPLibraryLogController.LOG_WRITE_ERROR) { //Log.e(LOG_TAG, "Bad ESP checksum. Expected 0x" + String.Format("%02X ", espChecksum) + " but found 0x" + String.Format("%02X ", curByte)); } } else { // Store the checksum retPacket.checkSum = curByte; } // Get the EOF byte next processState = ProcessState.EOF; break; case ProcessState.EOF: if (curByte != endOfFrameConstant) { // Bad data so let's bail dataError = true; if (ESPLibraryLogController.LOG_WRITE_ERROR) { //Log.e(LOG_TAG, "Unable to find EOF at the expected index: " + i); } } retPacket.endOfFrame = curByte; break; case ProcessState.BT_CHECKSUM: case ProcessState.END_PACK_BYTE: case ProcessState.PACKET_LENGTH: case ProcessState.START_PACK_BYTE: default: // We should never get here, so something went wrong dataError = true; break; } if (dataError) { break; } } buffer.Clear(); if (dataError) { return(null); } // Force the ESPPacket checksum to zero if the V1 does not support checksums before returning the packet. if ((retPacket.m_valentineType == Devices.VALENTINE1_LEGACY) || (retPacket.m_valentineType == Devices.VALENTINE1_WITHOUT_CHECKSUM)) { retPacket.checkSum = 0; } retPacket.packetChecksum = retPacket.makePacketChecksum(); return(retPacket); }