protected static ESPPacket makeFromBufferSPP(List <Byte> buffer, Devices lastV1Type) { int startIdx = -1; int endIdx = -1; // Make a copy of the buffer as it was at the beginning of the method call List <Byte> curStartBuffer = new List <Byte>(); mCopyBuffer(buffer, curStartBuffer); for (int index = 0; index < buffer.Count; index++) { byte test = buffer[index]; //.ByteValue(); if (test == frameDelimitedConstant) { if (startIdx == -1) { // We are looking for the start index startIdx = index; } else { // We are looking for the end index if (index == startIdx + 1) { // There are two delimiters together. This is expected to happen during startup when we can // receive the end of one packet followed by a valid packet. In this instance, we want to // move the start index to the beginning of the new packet startIdx = index; } else { // This should be the end of the packet so save the index and stop searching endIdx = index; break; } } } } if (startIdx == -1 || endIdx == -1) { // Copy start and end buffer in case the next call fails mCopyBuffer(curStartBuffer, mLastStartBuffer); mCopyBuffer(buffer, mLastEndBuffer); // We did not receive a full packet return(null); } if (startIdx != 0 && ESPLibraryLogController.LOG_WRITE_ERROR) { //Log.e(LOG_TAG, "Skipping " + startIdx + " bytes because there was no delimiter at index 0"); //Log.e(LOG_TAG, " Current buffer: " + getBufferLogString(buffer)); //Log.e(LOG_TAG, " Last Start buffer: " + getBufferLogString(mLastStartBuffer)); //Log.e(LOG_TAG, " Last End buffer: " + getBufferLogString(mLastEndBuffer)); } // Process the buffer int i = startIdx; int payloadIdx = 0; ESPPacket retPacket = null; ProcessState processState = ProcessState.START_PACK_BYTE; bool dataError = false; // Store these values until we have a packet to put them into byte tempLength = 0; byte tempDest = 0; byte tempOrigin = 0; byte packetChecksum = 0; byte espChecksum = 0; while (i <= endIdx) { // Read the next byte from the buffer byte curByte = buffer[i]; //.get(i).byteValue(); if (curByte == frameDataEscapeConstant) { // Check the next byte to see if it should be turned into an 0x7F or 0x7D i++; curByte = buffer[i]; //.get(i).byteValue(); // Skip the next byte after the delimiter if (curByte == (byte)0x5D) { // If we find 0x5D after the delimiter, turn it into an 0x7D curByte = (byte)0x7D; } else if (curByte == (byte)0x5F) { // If we find 0x5F after the delimiter, turn it into an 0x7F curByte = (byte)0x7F; } } switch (processState) { default: case ProcessState.START_PACK_BYTE: if (curByte != frameDelimitedConstant) { // How did THIS happen?!? dataError = true; if (ESPLibraryLogController.LOG_WRITE_ERROR) { //Log.e(LOG_TAG, "Missing 0x7F at startIdx: " + startIdx); } } // Move to the next state. If there is a data error, the next state will never be used so // we don't need to check for that. processState = ProcessState.PACKET_LENGTH; break; case ProcessState.PACKET_LENGTH: tempLength = curByte; // Update the checksum packetChecksum += curByte; // Move to the next state. If there is a data error, the next state will never be used so // we don't need to check for that. processState = ProcessState.SOF; break; case ProcessState.SOF: if (curByte != startOfFrameConstant) { // Bad data so let's bail dataError = true; if (ESPLibraryLogController.LOG_WRITE_ERROR) { //Log.e(LOG_TAG, "Missing SOF at the expected index: " + i); } } // Update the checksum packetChecksum += curByte; espChecksum += curByte; // Move to the next state. If there is a data error, the next state will never be used so // we don't need to check for that. processState = ProcessState.DESTINATION; break; case ProcessState.DESTINATION: if ((curByte & destinationIdentifierBaseConstant) != destinationIdentifierBaseConstant) { // This is not a valid destination dataError = true; if (ESPLibraryLogController.LOG_WRITE_ERROR) { //Log.e(LOG_TAG, "Invalid destination ID (" + String.format("%02X ", curByte) + ") at the expected index: " + i); } } tempDest = curByte; // Update the checksum packetChecksum += curByte; espChecksum += curByte; // Move to the next state. If there is a data error, the next state will never be used so // we don't need to check for that. processState = ProcessState.ORIGINATOR; break; case ProcessState.ORIGINATOR: if ((curByte & originationIdentifierBaseConstant) != originationIdentifierBaseConstant) { // This is not a valid originator dataError = true; if (ESPLibraryLogController.LOG_WRITE_ERROR) { //Log.e(LOG_TAG, "Invalid originator ID (" + String.format("%02X ", curByte) + ") at the expected index: " + i); } } tempOrigin = curByte; // Update the checksum packetChecksum += curByte; espChecksum += curByte; // Move to the next state. If there is a data error, the next state will never be used so // we don't need to check for that. 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; if (ESPLibraryLogController.LOG_WRITE_ERROR) { //Log.e(LOG_TAG, "Unable to generate packet for packet id (" + String.format("%02X ", curByte) + ")"); } } else { // We have a good packet so fill it up retPacket.headerDelimter = frameDelimitedConstant; //<- We can't get here if this wasn't true retPacket.packetLength = tempLength; 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"); } } } } // Update the checksum packetChecksum += curByte; espChecksum += curByte; // Move to the next state. If there is a data error, the next state will never be used so // we don't need to check for that. processState = ProcessState.PAYLOAD_LENGTH; break; case ProcessState.PAYLOAD_LENGTH: if (curByte != 0) { byte tmp; 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 payload 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; // Update the PACKET checksum packetChecksum += 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; // Update the PACKET checksum packetChecksum += curByte; // If we have reached the end of the payload data, handle checking the checksum. 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 the calculated checksum does not equal the checksum byte, an error has occurred. 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)); } } // Store the checksum packetChecksum += curByte; 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; // Update the packet checksum packetChecksum += curByte; // Move to the next state. If there is a data error, the next state will never be used so // we don't need to check for that. processState = ProcessState.BT_CHECKSUM; break; case ProcessState.BT_CHECKSUM: // Update the packet checksum if (packetChecksum != curByte) { // We are missing something dataError = true; if (ESPLibraryLogController.LOG_WRITE_ERROR) { //Log.e(LOG_TAG, "Bad packet checksum. Expected 0x" + String.format("%02X ", packetChecksum) + " but found 0x" + String.format("%02X ", curByte)); } } retPacket.packetChecksum = curByte; // Move to the next state. If there is a data error, the next state will never be used so // we don't need to check for that. processState = ProcessState.END_PACK_BYTE; break; case ProcessState.END_PACK_BYTE: if (i != endIdx) { // We should be at the end of the data by now dataError = true; if (ESPLibraryLogController.LOG_WRITE_ERROR) { //Log.e(LOG_TAG, "Excpected to be at index " + endIdx + " but we are at index " + i); } } else if (curByte != frameDelimitedConstant) { // How did THIS happen?!? dataError = true; if (ESPLibraryLogController.LOG_WRITE_ERROR) { //Log.e(LOG_TAG, "Missing 0x7F at endIdx: " + endIdx); } } retPacket.endDelimter = curByte; // Move to the next state. If there is a data error, the next state will never be used so // we don't need to check for that. processState = ProcessState.START_PACK_BYTE; break; } if (dataError) { // Stop processing the data break; } // Increment the index to the next byte i++; } // Remove all bytes up to and including the end index TrimBuffer(buffer, endIdx); // Copy start and end buffer in case the next call fails mCopyBuffer(curStartBuffer, mLastStartBuffer); mCopyBuffer(buffer, mLastEndBuffer); if (dataError) { return(null); } // Force the ESPPacket checksum to zero if the V1 does not support checksums before returning the packet. if ((retPacket.V1Type == Devices.VALENTINE1_LEGACY) || (retPacket.V1Type == Devices.VALENTINE1_WITHOUT_CHECKSUM)) { retPacket.checkSum = 0; } return(retPacket); }
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); }