Using the serial port - vb.net

For some time I've been working on learning how to program VB.NET. With the help of this page and the internet, I managed to create a program that sends some hex values to an interface box and get a routine response from it.
The problem here is that the communication was TCP/IP. But now I have a new box with a USB interface and now I do not have the slightest idea of how to send and receive those same hex values using the Serial port.
Below is the code. I don't know if someone could help me set it up for a serial port named COM13 or at least explain to me what to do.
This is what the program does.
Push scan
Connects to the TCP/IP of the BOX (10.2.12.65)
Sends the activation protocol E1 33
Sends the get date command 05 6c 29 f1 3c 81
Box responds back date with bytes
When the program reads the byte corresponding to 81(hex) it starts converting them into characters and adding them to a string to be displayed on the textbox on the bottom.
That's basically it. The problem is that until now I have been able to send only text strings but the box does not recognize it and it responds garbage and not the date.
Here is the code:
Imports System.Net.Sockets
Imports System.Threading
Imports System.IO
Public Class Form1
Dim client As New TcpClient
Dim transmit As NetworkStream
Dim protocol As Byte()
Dim data As Byte()
Dim ByteArrayToHexStr As String = String.Empty
Dim message As String
Dim datos_byte As Byte()
Dim respuesta As [String] = [String].Empty
Dim transision As [String] = [String].Empty
Dim Date_full As [String] = [String].Empty
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
TextBox1.Clear()
client = New TcpClient("10.2.12.65", 10001)
transmit = client.GetStream()
protocol = {225, 51} ' E1 33 in hex value
transmit.Write(protocol, 0, protocol.Length)
Thread.Sleep(45)
data = {5, 108, 41, 241, 60, 129} ' 05 6c 29 f1 3c 81 in hex value
transmit.Write(data, 0, data.Length)
data = New Byte(66) {}
Thread.Sleep(45)
Dim bytes As Int32 = transmit.Read(data, 0, data.Length)
Dim Date1 As String = String.Empty
Dim Date2 As String = String.Empty
Dim Date_temp As Integer = 0
For i As Integer = 0 To UBound(data)
Date1 = data(i)
If Date1 = "129" Then
Date_temp = i + 1
i = 1000
For k As Integer = 0 To 5
If k = 0 Then
Date1 = data(Date_temp + k)
Date_full = Chr(Date1)
Else
Date1 = data(Date_temp + k)
Date2 = Chr(Date1)
Date_full = Date_full & Date2
End If
Next
Else
End If
Next
Thread.Sleep(45)
transmit.Close()
client.Close()
TextBox1.Text = TextBox1.Text & Date_full
End Sub
End Class

Please have a look at Microsoft's example of the SerialPort class: https://msdn.microsoft.com/en-us/library/system.io.ports.serialport(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2
If you get garbage back that might indicate the baudrate is configured incorrectly. I'm not sure what you mean by 'box' but this device should have a specified baudrate which you should be able to find in its datasheet or product information.

Related

Can send normal UDP packet with VB.net - But how do you send a WOL packet?

I can send a packet with this:
Public Class Form1
Dim publisher As New Sockets.UdpClient(0)
Dim subscriber As New Sockets.UdpClient(2000)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
publisher.Connect(TBTo.Text, TBPort.Text)
Dim sendbytes() As Byte = ASCII.GetBytes("test")
publisher.Send(sendbytes, sendbytes.Length)
End Sub
End Class
It works great and using WireShark I can see on Port 9 a UDP Packet being sent to my IP (which I type into the address/word box).
I understand for WOL (Which I DO have working, just want to make my own application for fun/experience) you need a MAC, will it just "adding a MAC" address to this make it a WOL packet or is it more complicated than that?
NOTE: I can see the difference in WOL and UDP packets in Wireshark and changing my IP to "MYIP". For example below is a WOL packet sent from a WOL application.
40.000203000 MYIP 192.168.1.1 WOL 144 MagicPacket for Micro-St_21:94:b6 (44:8a:5b:21:94:b6)
Compared to a normal UDP packet:
69 12170.303276000 192.168.1.1 MYIP UDP 46 Source port: 57465 Destination port: 9
EDIT:
I have played about A LOT with some examples but they are not the best.
I managed to do it after a few hours. If anyone else is stuck, here is how I did it:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim MacAddress As String = "YOUR MAC ADDRESS HERE"
Dim myAddress As String = "YOURIP HERE"
Dim udpClient As New System.Net.Sockets.UdpClient
Dim buf(101) As Char
Dim sendBytes As [Byte]() = System.Text.Encoding.ASCII.GetBytes(buf)
For x As Integer = 0 To 5
sendBytes(x) = CByte("&HFF")
Next
Dim i As Integer = 6
For x As Integer = 1 To 16
sendBytes(i) = CByte("&H" + MacAddress.Substring(0, 2))
sendBytes(i + 1) = CByte("&H" + MacAddress.Substring(2, 2))
sendBytes(i + 2) = CByte("&H" + MacAddress.Substring(4, 2))
sendBytes(i + 3) = CByte("&H" + MacAddress.Substring(6, 2))
sendBytes(i + 4) = CByte("&H" + MacAddress.Substring(8, 2))
sendBytes(i + 5) = CByte("&H" + MacAddress.Substring(10, 2))
i += 6
Next
udpClient.Send(sendBytes, sendBytes.Length, myAddress, 9)
End Sub
End Class
That is it. Then all you do is change your IP and MAC to suit your needs. Or if you need, you can add in text boxes for different inputs.

Read specific columns and rows from .text

Well, I need to read columns and rows from a .txt
and get only the data I need.
Example: The file "sample.txt" has the following content
C = Columns
R = Rows
C1 C2 C3
R1 0 0 0 3694440008091082330089 ALBINA HANSEN OF OLMEDO 00000075000000022091401520117873
I need the following data for each row:
0003694440008091082330089 ALBINA HANSEN DE OLMEDO 00000075000000022091401520117873
(The series of numbers and letters above the value of the first line)
First Value: Starts at C19 to C25 (2330089)
Second Value: Starts at C28 to C50 (ALBINA HANSEN DE OLMEDO)
Third Value: Starts at C64 to C68 (75000)
Fourth Value: Starts at C73 to C78 (220914)
Fifth Value: It is only the C80 column (1)
And I need to display the data in a message box:
I have the following code:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim fileReader As String
fileReader = My.Computer.FileSystem.ReadAllText("C:\Users\cogentvaio\Desktop\Banco Itau\TXT-FOMENTO ANGELIUS.txt")
MsgBox(fileReader)
End Sub
End Class
This allows me to read the entire contents of .txt
Hopefully you can help me with this, I'm learning to program in vb.net.
I'll show you my code, I can not see the boundaries made with ​​substrinng, I used the code you suggested,
Imports System
Imports System.IO
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim fileReader = My.Computer.FileSystem.ReadAllText("C:\Users\cogentvaio\Desktop\Banco Itau\ejemplo\-TXT-ITAU ANGELIUS.txt")
Dim line As String
For Each line In fileReader
If line.Length > 80 Then
Dim c1 = line.Substring(18, 7)
Dim c2 = line.Substring(28, 50)
Dim c3 = line.Substring(64, 68)
Dim c4 = line.Substring(73, 78)
Dim c5 = line.Substring(80)
End If
Next
MessageBox.Show(fileReader)
End Sub
End Class
And what I got was this
IMAGE_PHOTO
I don't know where is my mistake
string.Substring is your friend here. This method extracts substring from a string starting from a char index and getting back the requested number of chars (length). Also remember that an array (a string is an array of chars) starts always at index zero, so your values Cx values should be decremented by one.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' Instead of ReadAllText, use ReadAllLines to have your input splitted in an array of strings
Dim fileReader = System.IO.File.ReadAllLines(......)
for each line in fileReader
' To avoid nasty exceptions be sure that the line is at least 81 chars long
if line.Length > 80 Then
Dim c1 = line.Substring(18, 7)
Dim c2 = line.Substring(27, 23)
Dim c3 = line.Substring(63, 5)
Dim c4 = line.Substring(72, 6)
Dim c5 = line.Substring(79, 1)
.... process these values....
.... for example ....
Dim newLine = string.Join(" ", c1,c2,c3,c4,c5)
MessageBox.Show(newLine)
End if
Next
End Sub
This changes takes a line, extract the part and creates a new string with only the parts required joined together with a space. Then prints out this new text. Of course, you want a join of all the rows with these subparts you need to add the newLine variable to a List( Of String) an then do a final join of the single rows
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' Instead of ReadAllText, use ReadAllLines to have your input splitted in an array of strings
Dim fileReader = System.IO.File.ReadAllLines(......)
Dim subText = New StringBuilder()
for each line in fileReader
if line.Length > 80 Then
....
Dim newLine = string.Join(" ", c1,c2,c3,c4,c5)
subText.Add(newLine)
End if
Next
MessageBox.Show(string.Join(Environment.NewLine, subText))
However your indexes doesn't seem to correctly point to the data required.
This substring extraction seems to find correctly your data
Dim c1 = line.Substring(18, 7)
Dim c2 = line.Substring(26, 23)
Dim c3 = line.Substring(56, 5)
Dim c4 = line.Substring(65, 6)
Dim c5 = line.Substring(72, 1)

Byte() to unsigned integer in .NET

I have been trying my hand at handling packets and bytes for the first time, and I have not been able to obtain the packet length correctly so far after many different techniques.
Code:
Public Shared Sub Client(packet As Packet)
Console.WriteLine( _
"Client -> " & _
packet.Timestamp.ToString("yyyy-MM-dd hh:mm:ss.fff") & _
" length:" & Convert.ToString(packet.Length))
'Define Byte Array
Dim clientPacket As Byte() = packet.Buffer
' Open a Binary Reader
Dim memStream As MemoryStream = New MemoryStream(clientPacket)
Dim bReader As BinaryReader = New BinaryReader(memStream)
' Remove the Ethernet Header
Dim ethBytes As Byte() = bReader.ReadBytes(14)
' Remove the IPv4 Header
Dim IPv4Bytes As Byte() = bReader.ReadBytes(20)
' Remove the TCP Header
Dim TCPBytes As Byte() = bReader.ReadBytes(20)
' Get the packet length
If clientPacket.Length > 54 Then
Dim len As UInt32 = bReader.ReadUInt32
Console.WriteLine(len)
End If
End Sub
So far, all of my attempts at having the console write the data length have resulted in failure. I validated the endianness and actually wrote out the bytes to verify that I was handling the correct data.
Example bytes:
00 00 00 24 -> UINT32 is 36 bytes, but I am getting an array of Integers like 3808493568
How can I fix this?
I agree with Hans, endianness is your problem. Also, I'd recommend you use the BitConverter class on the clientPacket array, easier than using streams.
Dim len As UInt32
Dim arr() As Byte
arr = {0, 0, 0, 24}
len = BitConverter.ToUInt32(arr, 0)
Console.Write(len.ToString) 'returns 402653184
arr = {24, 0, 0, 0}
len = BitConverter.ToUInt32(arr, 0)
Console.Write(len.ToString) 'returns 24
For your code, I think this might work (untested):
If clientPacket.Length > 54 Then
Dim lenBytes As Byte() = bReader.ReadBytes(4)
Array.Reverse(lenBytes, 0, 4)
Dim len As UInt32 = BitConverter.ToUInt32(lenBytes, 0)

How to send a data array from an Arduino to vb

I am trying to send data bytes from an Arduino to my visual basic app, but it does not work. I've already tried several solutions but I don't get the values back, I've send to the arduino.
The code I'm using for the visual basic app:
Private Sub DataReceivedHandler(sender As Object, e As SerialDataReceivedEventArgs)
Dim bytes As Integer = 6
Dim comBuffer As Byte() = New Byte(bytes - 1) {}
'read the data and store it
SerialPort1.Read(comBuffer, 0, bytes)
Dim aryReceived(10) As Integer
For i As Integer = 1 To (bytes - 1)
aryReceived(i) = comBuffer(i)
Y(i) = aryReceived(i)
Next
a = comBuffer(1)
b = comBuffer(2)
End Sub
Private Sub Verzenden()
Dim waardes() As Byte
waardes = {X(1), X(2), X(3), X(4), X(5), X(6)}
If SerialPort1.IsOpen = True Then
SerialPort1.Write(waardes, 0, waardes.Length)
End If
End Sub
Private Sub VerzendButton_Click(sender As Object, e As EventArgs) Handles VerzendButton.Click
X(1) = 10
X(2) = 11
X(3) = 12
X(4) = 13
X(5) = 14
X(6) = 15
Verzenden()
End Sub
and the arduino code:
int x[9];
void setup() {
Serial.begin(9600);
}
void loop() {
if(Serial.available() >= 6){
for(int i = 1; i < 7; i++){
x[i] = Serial.read();
}
for(int i = 1; i < 7; i++){
Serial.println(x[i]);
}
}
}
I send 6 bytes to the arduino with the following values: 10, 11, 12, 13, 14 & 15, but sometimes I have to send the bytes twice before the debugger breaks. The values that return in a & b are not the same as I send. The code for sending the bytes works fine.
Can someone help me?
The breakpoint I've set is at the 'end sub' command of the receive event. I often get for a 51 and for b 56, but they're random at other times.
X, Y and a & b are all defined in the public.
Public Class Form1
Dim indata As Integer
Dim Setting As New My.MySettings()
Dim Opstartmodus As Byte
Dim OpstartCOMpoort As String
Dim myPort As Array
Delegate Sub SetTextCallBack(ByVal [text] As String)
Dim a As Byte, b As Byte, c As Byte, d As Byte, f As Byte, g As Byte
Dim WaardeVerzenden As Byte, X(9) As Byte, Y(9) As Byte
Edit: I've added a delay of 500 microseconds in the arduino code between the receive action and the sens action. Now, After one click on the send button, the debugger breaks immediately. Thats one problem solved! But now, I get always the following patter back: 49,48,13,10,49,49. That totaly doesn't match with the pattern I send to the Arduino:(
I found the solution;) I have Serial.println replaced by Serial.write(x,6). In the Visual Basic app I replaced the reveive event with:
Private Sub SerialPort1_DataReceived(sender As Object, e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
For i As Integer = 0 To (Bytes - 1)
Y(i) = SerialPort1.ReadByte()
Next
End Sub
The Visual Basic app does now receive the data I send from the arduino:)

VB.Net send decimal udp

I am trying to send a single byte to a PIC from a computer (Note: the pic only accepts a single byte else it will only accept the first byte of the data send)
This shouldn't be much of a problem because I only want to manage a total of 8 LEDS so I only need it to go from 0 to 255 but I am having issues achieving this.
If I try to send the value 1 to the pic my program sends 31 if I try to send 5 it sends 35 If I try to send 255 it sends 3*2*3*5*3*5* so for every single digit I try to send it adds a 3 in front of it. I am using the following code to determine the value and to send it:
Dim t As Integer = 0
Dim result As Integer = 0
For Each chk As CheckBox In GroupBox1.Controls
If chk.Checked = True Then
result = result + 2 ^ t
End If
t = t + 1
Next
publisher.Connect(IPTo, PortTo)
Dim sendbytes() As Byte = ASCII.GetBytes(result)
publisher.Send(sendbytes, sendbytes.Length)
I think the issue is with the convert to ASCII.
I also try to receive the inputs from the PIC to my pc for this I have the following script inside a timer:
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Try
Dim ep As IPEndPoint = New IPEndPoint(IPAddress.Any, 0)
Dim rcvbytes() As Byte = subscriber.Receive(ep)
Dim translate As String
translate = System.BitConverter.ToInt32(rcvbytes, 0)
TBRcv.Text = translate
Catch ex As Exception
End Try
End Sub
ASCII.GetBytes expects a string (encoded in ASCII). Giving it an Int32 doesn't make sense.
Check out System.BitConverter.GetBytes() and System.BitConverter.ToInt32() (for the receiving end)
So the only change you'd need to make is:
Dim sendbytes() As Byte = BitConverter.GetBytes(result)
Further discussion:
What has happened is that your result (let's say 5), is first converted to string (now it's "5"), then ASCII.GetBytes will now return a byte array with a single value 0x35, because Asc("5") is 0x35.
The ASCII value of the character 1 is 0x31, etc. For reference :