I have a tibbo device for converting to serial port to IP. With a program like putty I can connect the device successfully and the device is working.
I want to develop little C# windows form application for listening this device but I can not find any way. Application get data from serial port via ip over tibbo serial to IP converter devices. How can I do it ?
Install the Tibbo Device Server Toolkit and map your tibbo device to a COM Port. If you need more help with SerialPort Communication read this article Serial Port Communication for beginners
Example Code:
using System;
using System.IO.Ports;
using System.Windows.Forms;
namespace SerialPortExample
{
class SerialPortProgram
{
// Create the serial port with basic settings
private SerialPort port = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
[STAThread]
static void Main(string[] args)
{
// Instatiate this class
new SerialPortProgram();
}
private SerialPortProgram()
{
Console.WriteLine("Incoming Data:");
// Attach a method to be called when there
// is data waiting in the port's buffer
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
// Begin communications
port.Open();
// Enter an application loop to keep this thread alive
Application.Run();
}
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// Show all the incoming data in the port's buffer
Console.WriteLine(port.ReadExisting());
}
}
}
Related
I have this Arduino code just for testing purpose:
int num=0;
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println(num);
num+=1;
delay(800);
}
Now it prints an integer and increments its value by one. When I open up Serial Monitor it prints as expected every 800ms.
My Arduino is connected on PORT-6
Now if I try to access the port, it says it is in use, I'm trying to access that from a .NET application. How can I do so?
c# code, collected from the internet, modified a little:
using System;
using System.IO.Ports;
using System.Threading;
namespace ConsoleApp1
{
class Program
{
static SerialPort _serialPort;
public static void Main()
{
_serialPort = new SerialPort();
_serialPort.PortName = "COM6";//Set your board COM
_serialPort.BaudRate = 9600;
_serialPort.Open();
while (true)
{
string a = _serialPort.ReadExisting();
Console.WriteLine(a);
}
}
}
}
How can I sniff data from that serial port ? [Educational Purpose]
You can't open a serial port twice.
If what you want is to get to see what is going through the bus (sniffing), you can use virtual ports and port forwarding, see here for a complete example.
Nothing will stop you from replacing any of the tools discussed in the link with your own code (.NET or other), in case they don't suit your needs or if you have enough determination to reinvent the wheel.
Goal:
Trying to write a string to a serial port, read it, then print it to console
Code:
// for waiting until event is detected
private static ManualResetEvent waitHandle = new ManualResetEvent(false);
public Driver()
{
// create new serial port
comPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
// add event handler
comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived);
// configure port
comPort.DtrEnable = true;
comPort.RtsEnable = true;
comPort.ReadTimeout = 3000;
// open port
comPort.Open();
// send string through port
string command = "test \n";
byte[] MyMessage = System.Text.Encoding.UTF8.GetBytes(command);
comPort.Write(MyMessage, 0, MyMessage.Length);
// wait until event is detected
waitHandle.WaitOne();
}
private void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// Write data to buffer and stop wait
Console.WriteLine(comPort.ReadExisting());
waitHandle.Set();
}
Issue:
Write to serial seems to work fine (confirmed by using Serial Port Monitor) but "comPort_DataReceived" never gets called
If I change my code and add
while(true)
{
Console.WriteLine(comPort.ReadExisting());
}
Right after the "comPort.Write(MyMessage, 0, MyMessage.Length);" line so that I'm polling instead of waiting for the event handler then a whole lot of nothing gets written
If I try polling this way
while (true)
{
Byte[] buf = new Byte[2048];
comPort.Read(buf, 0, 2048);
Console.WriteLine(buf.ToString());
}
It just times out (System.TimeoutException: 'The operation has timed out.'
).
I'm not sure where I am going wrong/why I am unable to read from the serial port
Ok, from what I see it looks like there is no device listening on serial port. Then, if you write something to serial port it does not mean that the same data will occur as a received data. This data is outgoing data. If you want to receive data there must be another device connected to that serial port and sending data as a response to your data written.
Turns out it was a hardware issue (no device was writing to serial port) coupled with a misunderstanding (thinking I could write to a serial port and then read what I wrote from within the same program)
How can I send a hexadecimal like 0x2b or 0x42 to a serial port using either C# or Php.
42 is the HEX that I need to send by the way.
I used this for C#
using System.IO.Ports;
namespace Card_Reader
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
using (SerialPort port = new SerialPort("COM2", 9600, Parity.None, 8))
{
byte[] bytesToSend = new byte[1] { 0x2A };
port.Open();
port.Write(bytesToSend, 0, 1);
}
}
but nothing happens to the device connected to my serial port.
Now I used this for Php
public function dispense_card() {
$serial = new CI_Phpserial();
// First we must specify the device. This works on both linux and windows (if
// your linux serial device is /dev/ttyS0 for COM1, etc)
$serial->deviceSet("COM2");
// We can change the baud rate, parity, length, stop bits, flow control
$serial->confBaudRate(9600);
$serial->confParity("even");
$serial->confCharacterLength(8);
$serial->confStopBits(1);
$serial->confFlowControl("none");
// Then we need to open it
$serial->deviceOpen();
// To write into
/*$serial->sendMessage(0x42);*/
$str = pack("h*",66);
$serial->sendMessage($str);
}
I'm getting close to hanging myself since I'm trying to do this since last year and until now I cannot accomplish it.
Newbie here when it comes to serial data sending.
I am developing a C# Windows Forms Application to communicate via a Bluetooth Connection with a Raspberry Pi Model 3. This connection is mimicked through a virtual serial port on the client machine. I am able to start a bluetooth connection within the C# program but I cannot receive any data from the program. When I use the program Putty, I can see that the data is transmitting on COM Port the way that I would like it to.
I also discovered a weird sort of glitch with the C# program. If i have the COM Port open on Putty and then start the C# program, an error will occur with the port.open() command since the port is reserved. So then if I close Putty and continue the C# application the data will stream perfectly to the program. Has anyone encountered this issue before? I've been at a bit of a loss for a few days now. The Code in my program is shown below:
using System;
using System.IO.Ports;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
using InTheHand.Net;
using InTheHand.Net.Sockets;
using InTheHand.Net.Bluetooth;
using System.Threading;
namespace GUIfromPI
{
static class Program
{
//PC BT USB adapter
private static BluetoothEndPoint EP = new BluetoothEndPoint(BluetoothAddress.Parse("##:##:##:##:##:##"), BluetoothService.BluetoothBase); //addressing the usb adapter used on the PC (endpoint)
private static BluetoothClient BC = new BluetoothClient(EP);
//Pi BT Adapter
private static BluetoothDeviceInfo BTDevice = new BluetoothDeviceInfo(BluetoothAddress.Parse("##:##:##:##:##:##")); //addressing the BT adapter on the Rasperry Pi
// private static NetworkStream stream = null;
public static SerialPort mySerialPort = new SerialPort(); //Bluetooth module mimics serial protocol by streaming data through the COM5 port in the host80 computer
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
public static void Main(string[] args)
{
Console.WriteLine("Executing Program...");
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (BluetoothSecurity.PairRequest(BTDevice.DeviceAddress, "1234"))//MY_PAIRING_CODE))
{
Console.WriteLine("PairRequest: OK");
if (BTDevice.Authenticated)
{
Console.WriteLine("Authenticated: OK");
BC.SetPin("1234");//pairing code
//BC.BeginConnect(BTDevice.DeviceAddress, BluetoothService.SerialPort, new AsyncCallback(Connect), BTDevice);
}
else
{
Console.WriteLine("Authenticated:No");
}
}
else
{
Console.WriteLine("PairRequest: No");
}
//mySerialPort = new SerialPort("COM5");
SerialThreadFunction();
}
public static void SerialThreadFunction()
{
mySerialPort.PortName = "COM10";
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.DtrEnable = true;
mySerialPort.RtsEnable = true;
mySerialPort.ReadTimeout = 100000;
mySerialPort.Open();
//mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
string mydata = "hello";
while (true)
{
Console.WriteLine(mySerialPort.ReadLine());
mydata = mySerialPort.ReadLine();
}
mySerialPort.Close();
}
private static void DataReceivedHandler(
object sender,
SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Console.WriteLine("Data Received: ");
Console.Write(indata);
}
}
}
UPDATE: I just discovered that declaring my Bluetooth Endpoint, client, and device are interfering with reading off of my serial port. Since the bluetooth connection was already initialized previously, I was able to see the data on the port. Now for why it does this?
Okay, it seems you are not doing anything wrong. Inherently .NET cannot handle multiple ownership of the same port. When you declare your SerialPort instance and connect to say... COM11... You have given ownership of COM11 solely to your SerialPort instance. In order to have access to COM11 you will now need to provide a reference to that specific SerialPort object which has ownership of COM11.
In your case you are opening PuTTY and then running your program. Once PuTTY obtains access to the port, your program will not be able to do so. This is completely standard in the .NET framework. Now, there are other ways that you can get multiple accesses to a COM port, but I think that's outside the scope of this question. Here's a software that will allow you to run an application and sniff traffic over the port at the same time... Free Serial Port Monitor. You can get this for free, and there is a better version for purchase that does all kinds of magic.
Here is a little algorithm for ensuring your port is opened properly, you may want to take this... modify it a little bit... and use it as the Connect method on your BluetoothClient class.
SerialPort port = null;
string error = string.Empty;
bool success = false;
int tries = 5;
foreach(var name in System.IO.Ports.SerialPort.GetPortNames())
{
// try each port until you find an open one
port.Name = name;
// there is always a chance that the port is open
// if trying some operations back-to-back
// give it a few extra tries if necessary
for (int i = tries; i > 0; --i)
{
try
{
// avoid the exception by testing if open first
if (!port.IsOpen)
{
port.Open();
success = true;
return;
}
}
catch (UnauthorizedAccessException e)
{
// sometimes the exception happens anyway, especially
// if you have multiple threads/processes banging on the
// ports
error += e.Message;
}
}
}
In addition to all of this, you may want to watch that your Bluetooth classes are not claiming ownership of the port when you need to read it. That may be what's interfering with reading the port. You really should create one single class and call it say BluetoothClient or something, and have that single class be responsible for all the interactions with the SerialPort reference. This way you ensure that whether you want to send/receive on the port you will always have ownership.
I am prototyping a sort of Arduino-based docking station for a tablet, using the USB port as connector. This means I need to support to ability to plug/unplug the USB connector while the application on the tablet is running.
The tablet runs a c# application (.net 4.5 on Win7 64 bit) in which I am connecting to the Arduino Uno. When the application is launched I loop all available COM ports using:
var ports = SerialPort.GetPortNames(); // -> [COM3,COM4,COM8]
foreach (var port in ports)
{
var serial = new SerialPort(portname, baudRate);
//attempt handshake and connect to right port
}
This work fine, but if I unplug and replug the USB cable and reattempt to reconnect to the Arduino (while the application is still running), the Arduino port (COM8) is no longer listed in:
SerialPort.GetPortNames(); // -> [COM3,COM4] and no COM8
Even restarting the application (with the Arduino replugged) will result in only [COM3,COM4] being listed.
The only way to get it back to work is to unplug and replug the Arduino while the application is not running.
What confuses me is the fact that when I plug in the Arduino Uno after starting the application, the SerialClass does recognize the newly added port and allows me to connect.
The problem only occurs when I unplug and replug the device when the application is running. It seems that despite the ability to reset the COM port (in code or manually in device manager), the SerialClass (and native Win32_SerialPort - I checked this too) do not recognize this, unless I restart the application
What could be the reason for this? And how can I make sure that my application can reconnect to that port? Are there any alternatives to using the SerialPort to handle the USB connector?
I found a solution that can handle plugging and unplugging a SerialPort.
First of all, it requires the use the SafeSerialPort, which allows you to dispose the serial port properly.
SafeSerialPort serialPort;
private void Connect()
{
string portname = "COM8";
serialPort = new SafeSerialPort(portname, 9600);
serialPort.DataReceived += port_DataReceived;
serialPort.Open();
}
Second, you need to use LibUsbDotNet to detect whether a USB device is connected or disconnected. This will allow you to determine whether to connect to the device or reset the COM port.
public UsbDevice MyUsbDevice;
//Find your vendor id etc by listing all available USB devices
public UsbDeviceFinder MyUsbFinder = new UsbDeviceFinder(0x2341, 0x0001);
public IDeviceNotifier UsbDeviceNotifier = DeviceNotifier.OpenDeviceNotifier();
private void OnDeviceNotifyEvent(object sender, DeviceNotifyEventArgs e)
{
if (e.Object.ToString().Split('\n')[1].Contains("0x2341"))
{
if (e.EventType == EventType.DeviceArrival)
{
Connect();
}
else if(e.EventType == EventType.DeviceRemoveComplete)
{
ResetConnection();
}
}
}
Finally, disposing the SerialPort will makes sure it is registered by Windows in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM, meaning that SerialPort.GetPortNames() can re-detect the port.
private void ResetConnection()
{
try
{
//Send any data to cause an IOException
serialPort.Write("Any value");
}
catch (IOException ex)
{
//Dispose the SafeSerialPort
serialPort.Dispose();
serialPort.Close();
}
}
After this process, you can simply reconnect to the COM port when the USB device is connected without the need to restart the application.
Full code:
using LibUsbDotNet;
using LibUsbDotNet.DeviceNotify;
using LibUsbDotNet.Info;
using LibUsbDotNet.Main;
SafeSerialPort serialPort;
public SerialPortTest()
{
Connect();
UsbDeviceNotifier.OnDeviceNotify += OnDeviceNotifyEvent;
}
private void Connect()
{
string portname = "COM8";
serialPort = new SafeSerialPort(portname, 9600);
serialPort.DataReceived += port_DataReceived;
serialPort.Open();
}
private void ResetConnection()
{
try
{
serialPort.Write("Any value");
}
catch (IOException ex)
{
serialPort.Dispose();
serialPort.Close();
}
}
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Console.WriteLine(serialPort.ReadExisting());
}
public UsbDevice MyUsbDevice;
//Vendor ID etc can be found through enumerating the USB devices
public UsbDeviceFinder MyUsbFinder = new UsbDeviceFinder(0x2341, 0x0001);
public IDeviceNotifier UsbDeviceNotifier = DeviceNotifier.OpenDeviceNotifier();
private void OnDeviceNotifyEvent(object sender, DeviceNotifyEventArgs e)
{
//if this is your usb device, in my case an Arduino
if (e.Object.ToString().Split('\n')[1].Contains("0x2341"))
{
if (e.EventType == EventType.DeviceArrival)
{
Connect();
}
else
{
ResetConnection();
}
}
}
So I believe this is happening because your program is caching the address of the USB the first time it is plugged in.
When someone plugs in a device, the hub detects voltage on either D+
or D- and signals the insertion to the host via this interrupt
endpoint. When the host polls this interrupt endpoint, it learns that
the new device is present. It then instructs the hub (via the default
control pipe) to reset the port where the new device was plugged in.
***This reset makes the new device assume address 0, and the host can
then interact with it directly; this interaction will result in the
host assigning a new (non-zero) address to the device.
Your best bet is to research how to programically flush the address cache of USB devices.
Reference:http://en.wikipedia.org/wiki/USB_hub