read networkstream

Hi Experts,
I get HEX data from a port as per sample:
Each occurance of 0x55 indicates start of string and each 0xAA indicates end of string.
You will notice that there are several occurances of such strings plus some other garbage as well.
I need to identify each such string within the stream and write it to a database.
Would appreciate help to get this done i.e. identify first string, store 'somewhere' continue and get next valid string.

0x55 0x02 0x00 0x0A 0x00 0x01 0x00 0xE1 0xFF 0x00 0x00 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x79 0x06 0xAA 0x61 0x0D 0x0A 0x55 0x02 0x00 0x0A 0x00 0x01 0x00 0xD1 0xFF 0xBE 0x07 0x00 0x00 0xA1 0x5D 0x2C 0x00 0x00 0x00 0xF9 0xFF 0xFF 0xFF 0xC2 0x07 0xAA 0x00 0x0D 0x0A 
 0x55 0x02 0x00 0x02 0x00 0x01 0x00 0xD1 0x02 0x0B 0x1B 0x00 0x00 0xB8 0x5D 0xFF 0xFF 0xFF 0xFF 0xF9 0xFF 0xFF 0xFF 0x05 0x0A 0xAA 0x00 0x0D 0x0A 0x55 0x02 0x00 0x0B 0x00 0x01 0x00 0xE1 0xFF 0x00 0x00 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x7A 0x06 0xAA 0x61 0x0D 0x0A  0x55 0x02 0x00 0x02 0x00 0x01 0x00 0xD1 0x02 0x0B 0x1B 0x00 0x00 0xB8 0x5D 0xFF 0xFF 0xFF 0xFF 0xF9 0xFF 0xFF 0xFF 0x05 0x0A 0xAA 0x00 0x0D 0x0A 0x55 0x02 0x00 0x0B 0x00 0x01 0x00 0xE1 0xFF 0x00 0x00 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x61 0x7A 0x06 0xAA 0x61 0x0D 0x0A

Open in new window

espsAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Bob LearnedCommented:
Have you tried implementing a BinaryReader, and looking for the marker bytes?
espsAuthor Commented:
Hi TheLearnedOne,
Thank you for your response.
In the absence of a potential solution, I have in fact gone ahead and coded a rather primative solution by analysing the bytes coming in on the stream byte by byte.
Probably not the most effective method but it works, for now.
If you would like, I could share the coseand you could possibly suggest a better method.
Otherwise I will award a few point to you for your response and close
rgs
Bob LearnedCommented:
I would love to see your attempt.  There might be a better way to approach a solution.
Bootstrap 4: Exploring New Features

Learn how to use and navigate the new features included in Bootstrap 4, the most popular HTML, CSS, and JavaScript framework for developing responsive, mobile-first websites.

espsAuthor Commented:
Note that sourcestring is the stream captured from the port and the positions of the Hex Data identified by the seperate functions represents different values which is then converted to decimal.

 Function updateAll(ByVal SourceString As String)
        Dim stringlen As Int32 = Len(sourceString)
        Dim wordToFind1 As String = "0x55"
        Dim wordToFind2 As String = "0xAA"

        Dim tt1 As Int16
        Dim tt2 As Int16
        Dim v55 As String
        Dim vAA As String
        Dim locationInString1 As Int16
        Dim locationInString2 As Int16
        Dim switch As Int16 = 0
        For i = 1 To stringlen
            locationInString1 = InStr(i, sourceString, wordToFind1)
            tt1 = locationInString1 + 2
            v55 = Mid(sourceString, tt1, 2)
            locationInString2 = InStr(i, sourceString, wordToFind2)
            tt2 = locationInString2 + 2
            vAA = Mid(sourceString, tt2, 2)
            i = i + locationInString1
                Dim val1 As Int64 = getAmps(sourceString, locationInString1)
                Dim val2 As Int64 = getVolts(sourceString, locationInString1)
                Dim val3 As Int64 = getReal(sourceString, locationInString1)
                Dim val4 As Int64 = getApparent(sourceString, locationInString1)
                Dim unit As Int64 = getUnit(sourceString, locationInString1)
                updateGullserver(unit, RealPower, amps, volts, Apparent)
       

            locationInString1 = 0
            locationInString2 = 0
        Next

    End Function
    Function val1(ByVal sourceString As String, ByVal vlocation As Int16)
        Dim TT As String = Mid(sourceString, vlocation + 62, 2) & Mid(sourceString, vlocation + 57, 2) & Mid(sourceString, vlocation + 52, 2) & Mid(sourceString, vlocation + 47, 2)
        Dim value As Long = Long.Parse(TT, Globalization.NumberStyles.HexNumber)
               Return value
    End Function
    Function val2(ByVal sourceString As String, ByVal vlocation As Int16)
        Dim TT As String = Mid(sourceString, vlocation + 72, 2) & Mid(sourceString, vlocation + 67, 2)
        Dim value As Long = Long.Parse(TT, Globalization.NumberStyles.HexNumber)
        Return value
    End Function
    Function val3(ByVal sourceString As String, ByVal vlocation As Int16)
        Dim TT As String = Mid(sourceString, vlocation + 92, 2) & Mid(sourceString, vlocation + 87, 2) & Mid(sourceString, vlocation + 82, 2) & Mid(sourceString, vlocation + 77, 2)
        Dim value As Long = Long.Parse(TT, Globalization.NumberStyles.HexNumber)
             Return value
    End Function
    Function val4(ByVal sourceString As String, ByVal vlocation As Int16)
        Dim TT As String = Mid(sourceString, vlocation + 112, 2) & Mid(sourceString, vlocation + 107, 2) & Mid(sourceString, vlocation + 102, 2) & Mid(sourceString, vlocation + 97, 2)
        Dim value As Long = Long.Parse(TT, Globalization.NumberStyles.HexNumber)
                Return value
    End Function
    Function getUnit(ByVal sourceString As String, ByVal vlocation As Int16)
        Dim Amps As String = Mid(sourceString, vlocation + 22, 2) & Mid(sourceString, vlocation + 17, 2)
        Dim value As Long = Long.Parse(TT, Globalization.NumberStyles.HexNumber)
              Return value
    End Function
Bob LearnedCommented:
1) How many bytes would the typical length be?  

2) Converting the entire byte array to a string, and then looking for bytes doesn't sound optimized.

3) There is an algorithm for strings (Boyer-Moore), that is optimized to 3n comparisons.  It might work for byte arrays, too.

Boyer-Moore String Search Algorithm
http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm

4) String.IndexOf() uses internally generated assembly code to more than likely use the Boyer-Moore algorithm.

Fast Text Search with Boyer-Moore
http://www.blackbeltcoder.com/Articles/algorithms/fast-text-search-with-boyer-moore

5) I wouldn't know if Instr is optimized, since it is included for backwards compatibility with VB6.
espsAuthor Commented:
26 Bytes.
My problem is that I can never tell how many strings of 26 bytes plus some garbage in between wil be in the stream.
You have some good points though.
I'll do few tests with indexof as well.
Well ok, unless you have some more ideas, lets close this and I'll award the point to your last response.
Thanks again!
Bob LearnedCommented:
I mean how many bytes for the entire array?
espsAuthor Commented:
Dim inStream(10024) As Byte
A valid string is:
0x55 0x02 0x00 0x02 0x00 0x01 0x00 0xD1 0x02 0x0B 0x1B 0x00 0x00 0xB8 0x5D 0xFF 0xFF 0xFF 0xFF 0xF9 0xFF 0xFF 0xFF 0x05 0x0A 0xAA
with ox55 = beginning of string and 0xAA end of string.
Bob LearnedCommented:
Here is a long discussion about this type of problem, and a lot of suggestions:

byte[] array pattern search
http://stackoverflow.com/questions/283456/byte-array-pattern-search

Here is VB.NET code for one suggestion for Boyer-Moore:


Public Class BoyerMoore

	Private Shared ALPHABET_SIZE As Integer = 256

	Private text As Byte()
	Private pattern As Byte()

	Private last As Integer()
	Private match As Integer()
	Private suffix As Integer()

	Public Sub New(pattern As Byte(), text As Byte())
		Me.text = text
		Me.pattern = pattern
		last = New Integer(ALPHABET_SIZE - 1) {}
		match = New Integer(pattern.Length - 1) {}
		suffix = New Integer(pattern.Length - 1) {}
	End Sub


	'*
'    * Searches the pattern in the text.
'    * returns the position of the first occurrence, if found and -1 otherwise.
'    

	Public Function Match() As Integer
		' Preprocessing
		ComputeLast()
		ComputeMatch()

		' Searching
		Dim i As Integer = pattern.Length - 1
		Dim j As Integer = pattern.Length - 1
		While i < text.Length
			If pattern(j) = text(i) Then
				If j = 0 Then
					Return i
				End If
				j -= 1
				i -= 1
			Else
				i += pattern.Length - j - 1 + Math.Max(j - last(text(i)), match(j))
				j = pattern.Length - 1
			End If
		End While
		Return -1
	End Function


	'*
'    * Computes the function last and stores its values in the array last.
'    * last(Char ch) = the index of the right-most occurrence of the character ch
'    *                                                           in the pattern; 
'    *                 -1 if ch does not occur in the pattern.
'    

	Private Sub ComputeLast()
		For k As Integer = 0 To last.Length - 1
			last(k) = -1
		Next
		For j As Integer = pattern.Length - 1 To 0 Step -1
			If last(pattern(j)) < 0 Then
				last(pattern(j)) = j
			End If
		Next
	End Sub


	'*
'    * Computes the function match and stores its values in the array match.
'    * match(j) = min{ s | 0 < s <= j && p[j-s]!=p[j]
'    *                            && p[j-s+1]..p[m-s-1] is suffix of p[j+1]..p[m-1] }, 
'    *                                                         if such s exists, else
'    *            min{ s | j+1 <= s <= m 
'    *                            && p[0]..p[m-s-1] is suffix of p[j+1]..p[m-1] }, 
'    *                                                         if such s exists,
'    *            m, otherwise,
'    * where p is the pattern and m is its length.
'    

	Private Sub ComputeMatch()
		' Phase 1 

		For j As Integer = 0 To match.Length - 1
			match(j) = match.Length
		Next
		'O(m) 
		ComputeSuffix()
		'O(m)
		' Phase 2 

		'Uses an auxiliary array, backwards version of the KMP failure function.
		'suffix[i] = the smallest j > i s.t. p[j..m-1] is a prefix of p[i..m-1],
		'if there is no such j, suffix[i] = m

		'Compute the smallest shift s, such that 0 < s <= j and
		'p[j-s]!=p[j] and p[j-s+1..m-s-1] is suffix of p[j+1..m-1] or j == m-1}, 
		'                                                         if such s exists,
		For i As Integer = 0 To match.Length - 2
			Dim j As Integer = suffix(i + 1) - 1
			' suffix[i+1] <= suffix[i] + 1
			If suffix(i) > j Then
				' therefore pattern[i] != pattern[j]
				match(j) = j - i
			Else
				' j == suffix[i]
				match(j) = Math.Min(j - i + match(i), match(j))
			End If
		Next

		' Phase 3 

		'Uses the suffix array to compute each shift s such that
		'p[0..m-s-1] is a suffix of p[j+1..m-1] with j < s < m
		'and stores the minimum of this shift and the previously computed one.
		If suffix(0) < pattern.Length Then
			For j As Integer = suffix(0) - 1 To 0 Step -1
				If suffix(0) < match(j) Then
					match(j) = suffix(0)
				End If
			Next
			If True Then
				Dim j As Integer = suffix(0)
				Dim k As Integer = suffix(j)
				While k < pattern.Length
					While j < k
						If match(j) > k Then
							match(j) = k
						End If
						j += 1
					End While
					k = suffix(k)
				End While
			End If
		End If
	End Sub


	'*
'    * Computes the values of suffix, which is an auxiliary array, 
'    * backwards version of the KMP failure function.
'    * 
'    * suffix[i] = the smallest j > i s.t. p[j..m-1] is a prefix of p[i..m-1],
'    * if there is no such j, suffix[i] = m, i.e. 
'
'    * p[suffix[i]..m-1] is the longest prefix of p[i..m-1], if suffix[i] < m.
'    

	Private Sub ComputeSuffix()
		suffix(suffix.Length - 1) = suffix.Length
		Dim j As Integer = suffix.Length - 1
		For i As Integer = suffix.Length - 2 To 0 Step -1
			While j < suffix.Length - 1 AndAlso Not pattern(j).Equals(pattern(i))
				j = suffix(j + 1) - 1
			End While
			If pattern(j) = pattern(i) Then
				j -= 1
			End If
			suffix(i) = j + 1
		Next
	End Sub

End Class

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
espsAuthor Commented:
Good discussion
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.