This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 8 years ago.
The problem is: I get a NullReferenceException but I can't seem to find out why. (I just start with C#) and have read the C# for kids from Microsoft. It explained a lot but this I do not understand.
But I don't get the piece of code which throw the exception to my head.
Code is:
using System;
using System.Collections.Generic;
using System.Linq; using System.Text;
using System.IO.Ports;
using PlugwiseLib.BLL.BC;
using plugwiseLib.BLL.BPC;
using System.Text.RegularExpressions;
using System.Threading;
using System.IO;
using PlugwiseLib.BLL.BPC;
using PlugwiseLib.UTIL;
namespace PlugwiseLib {
public class plugwiseControl
{
private SerialPort port;
private PlugwiseActions currentAction;
public delegate void PlugwiseDataReceivedEvent(object
sender, System.EventArgs e,
List<PlugwiseMessage> data);
public event PlugwiseDataReceivedEvent
DataReceived;
private PlugwiseReader reader;
/// <summary>
/// Constructor for the Plugwise Control class
/// </summary>
/// <param name="serialPort">The serial port name that the plugwise stick takes</param>
public plugwiseControl(string serialPort)
{
try
{
port = new SerialPort(serialPort);
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
port.BaudRate = 115200;
currentAction = PlugwiseActions.None;
reader = new PlugwiseReader();
}
catch (Exception e)
{
throw new Exception("Could not connect to plug.");
}
}
/// <summary>
/// This is the method that sends a command to the plugwise plugs.
/// </summary>
/// <param name="mac">The mac adress of the plug that needs to perform the action</param>
/// <param name="action">The action that has to be performed</param>
public void Action(string mac,PlugwiseActions action)
{
try
{
string message = "";
switch (action)
{
case PlugwiseActions.On:
currentAction = PlugwiseActions.On;
message = PlugwiseSerialPortFactory.Create(PlugwiseSerialPortRequest.on,mac);
break;
case PlugwiseActions.Off:
currentAction = PlugwiseActions.Off;
message = PlugwiseSerialPortFactory.Create(PlugwiseSerialPortRequest.off, mac);
break;
case PlugwiseActions.Status:
currentAction = PlugwiseActions.Status;
message = PlugwiseSerialPortFactory.Create(PlugwiseSerialPortRequest.status, mac);
break;
case PlugwiseActions.Calibration:
currentAction = PlugwiseActions.Calibration;
message = PlugwiseSerialPortFactory.Create(PlugwiseSerialPortRequest.calibration, mac);
break;
case PlugwiseActions.powerinfo:
currentAction = PlugwiseActions.powerinfo;
message = PlugwiseSerialPortFactory.Create(PlugwiseSerialPortRequest.powerinfo,mac);
break;
case PlugwiseActions.history:
message = "";
break;
}
if (message.Length > 0)
{
port.WriteLine(message);
Thread.Sleep(10);
}
}
catch (Exception e)
{
throw e;
}
}
/// <summary>
/// This is the method that sends a command to the plugwise plugs that retrieves the history power information
/// </summary>
/// <param name="mac">The mac adress of the plug that needs to perform the action</param>
/// <param name="logId">The id of the history message that has to be retrieved</param>
/// <param name="action">The action that has to be performed this MUST be history</param>
public void Action(string mac,int logId,PlugwiseActions action)
{
string message = "";
switch(action)
{
case PlugwiseActions.history:
currentAction = PlugwiseActions.history;
message = PlugwiseSerialPortFactory.Create(PlugwiseSerialPortRequest.history, MessageHelper.ConvertIntToPlugwiseLogHex(logId), mac);
break;
}
if (message.Length > 0)
{
port.WriteLine(message);
Thread.Sleep(10);
}
}
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{// Event for receiving data
string txt = port.ReadExisting();
List<PlugwiseMessage> msg = reader.Read(Regex.Split(txt, "\r\n"));
DataReceived(sender, new System.EventArgs(), msg);
}
/// <summary>
/// This method Opens the connection to the serial port
/// </summary>
public void Open()
{
try
{
if (!port.IsOpen)
{
port.Open();
}
}
catch (System.IO.IOException ex)
{
throw ex;
}
}
/// <summary>
/// This method closes the connection to the serial port
/// </summary>
public void Close()
{
try
{
if (port.IsOpen)
{
port.Close();
}
Thread.Sleep(5);
}
catch (IOException ex)
{
throw ex;
}
}
}
}
I get the exception at this piece (in Visual C# 2008 express)
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{// Event for receiving data
string txt = port.ReadExisting();
List<PlugwiseMessage> msg = reader.Read(Regex.Split(txt, "\r\n"));
DataReceived(sender, new System.EventArgs(), msg);
I checked 'msg' but this is filled with so far i can see valid data.
So I don't know why I get the exception.
Do you have any subscribers for plugwiseControl.DataReceived event? A common way to raise event is
var handler = DataReceived;
if(handler != null) handler(sender, EventArgs.Empty, msg);
I think DataReceived event is not initialized, by the calling method.
In .NET, if you raise an event and there are no registered listeners for that event (nothing has done to your event what you do to your port's DataReceived event in the second line of your try {} block in your constructor), it shows up as null, and raises that exception. In your Watch list screenshot, DataReceived is null, which makes me think this is the problem. So:
if (DataReceived != null)
DataReceived(...arguments here...);
Related
I just started learning how to send and receive data from my hardware through the C# GUI.
Can anyone please write a detail how to read data from the serial port?
SerialPort (RS-232 Serial COM Port) in C# .NET
This article explains how to use the SerialPort class in .NET to read and write data, determine what serial ports are available on your machine, and how to send files. It even covers the pin assignments on the port itself.
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());
}
}
}
I spent a lot of time to use SerialPort class and has concluded to use SerialPort.BaseStream class instead. You can see source code: SerialPort-source and
SerialPort.BaseStream-source for deep understanding.
I created and use code that shown below.
The core function
public int Recv(byte[] buffer, int maxLen)
has name and works like "well known" socket's recv().
It means that
in one hand it has timeout for no any data and throws TimeoutException.
In other hand, when any data has received,
it receives data either until maxLen bytes
or short timeout (theoretical 6 ms) in UART data flow
.
public class Uart : SerialPort
{
private int _receiveTimeout;
public int ReceiveTimeout { get => _receiveTimeout; set => _receiveTimeout = value; }
static private string ComPortName = "";
/// <summary>
/// It builds PortName using ComPortNum parameter and opens SerialPort.
/// </summary>
/// <param name="ComPortNum"></param>
public Uart(int ComPortNum) : base()
{
base.BaudRate = 115200; // default value
_receiveTimeout = 2000;
ComPortName = "COM" + ComPortNum;
try
{
base.PortName = ComPortName;
base.Open();
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine("Error: Port {0} is in use", ComPortName);
}
catch (Exception ex)
{
Console.WriteLine("Uart exception: " + ex);
}
} //Uart()
/// <summary>
/// Private property returning positive only Environment.TickCount
/// </summary>
private int _tickCount { get => Environment.TickCount & Int32.MaxValue; }
/// <summary>
/// It uses SerialPort.BaseStream rather SerialPort functionality .
/// It Receives up to maxLen number bytes of data,
/// Or throws TimeoutException if no any data arrived during ReceiveTimeout.
/// It works likes socket-recv routine (explanation in body).
/// Returns:
/// totalReceived - bytes,
/// TimeoutException,
/// -1 in non-ComPortNum Exception
/// </summary>
/// <param name="buffer"></param>
/// <param name="maxLen"></param>
/// <returns></returns>
public int Recv(byte[] buffer, int maxLen)
{
/// The routine works in "pseudo-blocking" mode. It cycles up to first
/// data received using BaseStream.ReadTimeout = TimeOutSpan (2 ms).
/// If no any message received during ReceiveTimeout property,
/// the routine throws TimeoutException
/// In other hand, if any data has received, first no-data cycle
/// causes to exit from routine.
int TimeOutSpan = 2;
// counts delay in TimeOutSpan-s after end of data to break receive
int EndOfDataCnt;
// pseudo-blocking timeout counter
int TimeOutCnt = _tickCount + _receiveTimeout;
//number of currently received data bytes
int justReceived = 0;
//number of total received data bytes
int totalReceived = 0;
BaseStream.ReadTimeout = TimeOutSpan;
//causes (2+1)*TimeOutSpan delay after end of data in UART stream
EndOfDataCnt = 2;
while (_tickCount < TimeOutCnt && EndOfDataCnt > 0)
{
try
{
justReceived = 0;
justReceived = base.BaseStream.Read(buffer, totalReceived, maxLen - totalReceived);
totalReceived += justReceived;
if (totalReceived >= maxLen)
break;
}
catch (TimeoutException)
{
if (totalReceived > 0)
EndOfDataCnt--;
}
catch (Exception ex)
{
totalReceived = -1;
base.Close();
Console.WriteLine("Recv exception: " + ex);
break;
}
} //while
if (totalReceived == 0)
{
throw new TimeoutException();
}
else
{
return totalReceived;
}
} // Recv()
} // Uart
Note that usage of a SerialPort.DataReceived event is optional. You can set proper timeout using SerialPort.ReadTimeout and continuously call SerialPort.Read() after you wrote something to a port until you get a full response.
Moreover, you can use SerialPort.BaseStream property to extract an underlying Stream instance. The benefit of using a Stream is that you can easily utilize various decorators with it:
var port = new SerialPort();
// LoggingStream inherits Stream, implements IDisposable, needed abstract methods and
// overrides needed virtual methods.
Stream portStream = new LoggingStream(port.BaseStream);
portStream.Write(...); // Logs write buffer.
portStream.Read(...); // Logs read buffer.
For more information:
Top 5 SerialPort Tips article by Kim Hamilton, BCL Team Blog
C# await event and timeout in serial port communication discussion on StackOverflow
I'm developing an application to control cafeteria consumption for my company. Basically each employee has a badge id with a barcode, and they are entitled to a free meal every day. The application will scan the badge and log each employees' meals. It will run on a Motorola MK4000 device, which has an integrated scanner and runs on Windows CE.
I've got an issue with the device scanner. I can get it to run and scan fine, but if it stays idle for a few minutes, it goes to "Waiting" status, the laser turns off, and doesn't come back on. I've tried monitoring the status and starting a new read when it changes to that status, but then it just keeps scanning false reads indefinitely.
Can you guys help me figure out what im doing wrong?
This is the class I'm using for the scanner functionality. It wasn't developed by me, but its begin used for other applications on the same device (I made a few changes to it, mostly on the error messages).
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace MK4000
{
class BarCode
{
#region Fields
private Symbol.Barcode.Reader myReader = null;
private Symbol.Barcode.ReaderData myReaderData = null;
private System.EventHandler myReadNotifyHandler = null;
private System.EventHandler myStatusNotifyHandler = null;
#endregion Fields
#region Properties
/// <summary>
/// Provides the access to the Symbol.Barcode.Reader reference.
/// The user can use this reference for his additional Reader - related operations.
/// </summary>
public Symbol.Barcode.Reader Reader
{
get
{
return myReader;
}
}
public String ErrorMessage
{
get
{
return "Error";
}
}
#endregion Properties
#region Methods
/// <summary>
/// Attach a ReadNotify handler.
/// </summary>
public void AttachReadNotify(System.EventHandler ReadNotifyHandler)
{
// If we have a reader
if (myReader != null)
{
// Attach the read notification handler.
myReader.ReadNotify += ReadNotifyHandler;
myReadNotifyHandler = ReadNotifyHandler;
}
}
/// <summary>
/// Attach a StatusNotify handler.
/// </summary>
public void AttachStatusNotify(System.EventHandler StatusNotifyHandler)
{
// If we have a reader
if (myReader != null)
{
// Attach status notification handler.
myReader.StatusNotify += StatusNotifyHandler;
myStatusNotifyHandler = StatusNotifyHandler;
}
}
/// <summary>
/// Detach the ReadNotify handler.
/// </summary>
public void DetachReadNotify()
{
if ((myReader != null) && (myReadNotifyHandler != null))
{
// Detach the read notification handler.
myReader.ReadNotify -= myReadNotifyHandler;
myReadNotifyHandler = null;
}
}
/// <summary>
/// Detach a StatusNotify handler.
/// </summary>
public void DetachStatusNotify()
{
// If we have a reader registered for receiving the status notifications
if ((myReader != null) && (myStatusNotifyHandler != null))
{
// Detach the status notification handler.
myReader.StatusNotify -= myStatusNotifyHandler;
myStatusNotifyHandler = null;
}
}
/// <summary>
/// Initialize the reader.
/// </summary>
public bool InitReader()
{
// If the reader is already initialized then fail the initialization.
if (myReader != null)
{
return false;
}
else // Else initialize the reader.
{
try
{
// Get the device selected by the user.
Symbol.Generic.Device MyDevice =
Symbol.StandardForms.SelectDevice.Select(
Symbol.Barcode.Device.Title,
Symbol.Barcode.Device.AvailableDevices);
if (MyDevice == null)
{
MessageBox.Show(ErrorMessage);
return false;
}
// Create the reader, based on selected device.
myReader = new Symbol.Barcode.Reader(MyDevice);
// Create the reader data.
myReaderData = new Symbol.Barcode.ReaderData(
Symbol.Barcode.ReaderDataTypes.Text,
Symbol.Barcode.ReaderDataLengths.MaximumLabel);
// Enable the Reader.
myReader.Actions.Enable();
// In this sample, we are setting the aim type to trigger.
switch (myReader.ReaderParameters.ReaderType)
{
case Symbol.Barcode.READER_TYPE.READER_TYPE_IMAGER:
myReader.ReaderParameters.ReaderSpecific.ImagerSpecific.AimType = Symbol.Barcode.AIM_TYPE.AIM_TYPE_TRIGGER;
//myReader.Parameters.Feedback.Success.BeepTime = 0;
break;
case Symbol.Barcode.READER_TYPE.READER_TYPE_LASER:
myReader.ReaderParameters.ReaderSpecific.LaserSpecific.AimType = Symbol.Barcode.AIM_TYPE.AIM_TYPE_TRIGGER;
break;
case Symbol.Barcode.READER_TYPE.READER_TYPE_CONTACT:
// AimType is not supported by the contact readers.
break;
}
myReader.Actions.SetParameters();
}
catch (Symbol.Exceptions.OperationFailureException ex)
{
MessageBox.Show(ex.Message);
return false;
}
catch (Symbol.Exceptions.InvalidRequestException ex)
{
MessageBox.Show(ex.Message);
return false;
}
catch (Symbol.Exceptions.InvalidIndexerException ex)
{
MessageBox.Show(ex.Message);
return false;
};
return true;
}
}
/// <summary>
/// Start a read on the reader.
/// </summary>
public void StartRead(bool toggleSoftTrigger)
{
// If we have both a reader and a reader data
if ((myReader != null) &&
(myReaderData != null))
try
{
if (!myReaderData.IsPending)
{
// Submit a read.
myReader.Actions.Read(myReaderData);
if (toggleSoftTrigger && myReader.Info.SoftTrigger == false)
{
myReader.Info.SoftTrigger = true;
}
}
}
catch (Symbol.Exceptions.OperationFailureException ex)
{
MessageBox.Show(ex.Message);
}
catch (Symbol.Exceptions.InvalidRequestException ex)
{
MessageBox.Show(ex.Message);
}
catch (Symbol.Exceptions.InvalidIndexerException ex)
{
MessageBox.Show(ex.Message);
};
}
/// <summary>
/// Stop all reads on the reader.
/// </summary>
public void StopRead()
{
//If we have a reader
if (myReader != null)
{
try
{
// Flush (Cancel all pending reads).
if (myReader.Info.SoftTrigger == true)
{
myReader.Info.SoftTrigger = false;
}
myReader.Actions.Flush();
}
catch (Symbol.Exceptions.OperationFailureException ex)
{
MessageBox.Show(ex.Message);
}
catch (Symbol.Exceptions.InvalidRequestException ex)
{
MessageBox.Show(ex.Message);
}
catch (Symbol.Exceptions.InvalidIndexerException ex)
{
MessageBox.Show(ex.Message);
};
}
}
/// <summary>
/// Stop reading and disable/close the reader.
/// </summary>
public void TermReader()
{
// If we have a reader
if (myReader != null)
{
try
{
// stop all the notifications.
StopRead();
//Detach all the notification handler if the user has not done it already.
DetachReadNotify();
DetachStatusNotify();
// Disable the reader.
myReader.Actions.Disable();
// Free it up.
myReader.Dispose();
// Make the reference null.
myReader = null;
}
catch (Symbol.Exceptions.OperationFailureException ex)
{
MessageBox.Show(ex.Message);
}
catch (Symbol.Exceptions.InvalidRequestException ex)
{
MessageBox.Show(ex.Message);
}
catch (Symbol.Exceptions.InvalidIndexerException ex)
{
MessageBox.Show(ex.Message);
};
}
// After disposing the reader, dispose the reader data.
if (myReaderData != null)
{
try
{
// Free it up.
myReaderData.Dispose();
// Make the reference null.
myReaderData = null;
}
catch (Symbol.Exceptions.OperationFailureException ex)
{
MessageBox.Show(ex.Message);
}
catch (Symbol.Exceptions.InvalidRequestException ex)
{
MessageBox.Show(ex.Message);
}
catch (Symbol.Exceptions.InvalidIndexerException ex)
{
MessageBox.Show(ex.Message);
};
}
}
#endregion Methods
}
}
And this is the code for the actual form:
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace MK4000
{
public partial class Form1 : Form
{
private bool isReaderInitiated;
private BarCode myScanner;
private EventHandler myStatusNotifyHandler = null;
private EventHandler myReadNotifyHandler = null;
private String MacAddress = "00-00-00-00-00-00";
private String strIPAddress = "000.000.000.000";
private String version = "0.0.0.1";
public static int TaskbarHeight = Screen.PrimaryScreen.Bounds.Height - Screen.PrimaryScreen.WorkingArea.Height;
private int counter = 0;
private int itemLimit = 10;
public String ErrorMessage
{
get
{
return "Error";
}
}
public Form1()
{
InitializeComponent();
this.Width = Screen.PrimaryScreen.Bounds.Width;
this.Height = Screen.PrimaryScreen.Bounds.Height - TaskbarHeight;
this.FormBorderStyle = FormBorderStyle.None;
this.ControlBox = false;
this.MinimizeBox = false;
this.EmpID.Visible = false;
this.EmpName.Visible = false;
this.messageLabel.Visible = false;
this.lblCounter.Text = counter.ToString();
this.lblCounter.Visible = false;
this.statusBar1.Text = "Initializing.. Reticulating Splines " + MacAddress + " | " + strIPAddress + " | " + version;
this.listView1.View = View.Details;
this.listView1.Columns.Add("EmployeeID", 150, HorizontalAlignment.Left);
this.listView1.Columns.Add("EmployeeName", 330, HorizontalAlignment.Left);
this.listView1.Columns.Add("Time", 250, HorizontalAlignment.Left);
this.Closing += new CancelEventHandler(Form1_OnClosing);
this.myScanner = new BarCode();
this.isReaderInitiated = this.myScanner.InitReader();
if (!(this.isReaderInitiated))// If the reader has not been initialized
{
// Display a message & exit the application.
MessageBox.Show(ErrorMessage);
Application.Exit();
}
else // If the reader has been initialized
{
// Attach a status natification handler.
myScanner.AttachStatusNotify(myScanner_StatusNotify);
// Start a read operation & attach a handler.
myScanner.StartRead(true);
myScanner.AttachReadNotify(myScanner_ReadNotify);
}
}
private void myScanner_ReadNotify(object Sender, EventArgs e)
{
// Get ReaderData
Symbol.Barcode.ReaderData TheReaderData = this.myScanner.Reader.GetNextReaderData();
processData(TheReaderData.ToString());
this.myScanner.StopRead();
System.Threading.Thread.Sleep(1000);
this.myScanner.StartRead(true);
}
private void processData(string readerData)
{
string EmployeeName = "";
string EmployeeID = readerData;
hideMessage();
//This will query the employee database and proceed if employee exists, right now i just give it a random name
EmployeeName = "John Doe";
if (EmployeeName != "")
{
addToList(EmployeeID, EmployeeName);
counter += 1;
this.lblCounter.Text = counter.ToString();
this.EmpID.Visible = true
this.EmpName.Visible = true
this.lblCounter.Visible = true;
showMessage("Thank You!", System.Drawing.Color.LimeGreen);
}
}
private void showMessage(string messageText, System.Drawing.Color messageColor)
{
this.messageLabel.Text = messageText;
this.messageLabel.BackColor = messageColor;
this.messageLabel.Visible = true;
}
private void hideMessage()
{
this.messageLabel.Text = "";
this.messageLabel.BackColor = System.Drawing.Color.Black;
this.messageLabel.Visible = false;
}
private void addToList(string EmployeeID, string EmployeeName)
{
if (this.listView1.Items.Count >= itemLimit)
{
this.listView1.Items.RemoveAt(0);
}
ListViewItem item = new ListViewItem(EmployeeID);
//item.Text = EmployeeID;
item.SubItems.Add(EmployeeName);
item.SubItems.Add(DateTime.Now.ToString());
this.listView1.Items.Add(item);
this.listView1.Refresh();
}
private void myScanner_StatusNotify(object Sender, EventArgs e)
{
// Get ReaderData
Symbol.Barcode.BarcodeStatus TheStatusData = this.myScanner.Reader.GetNextStatus();
switch (TheStatusData.State)
{
case Symbol.Barcode.States.IDLE:
this.statusBar1.Text = "Idle - Scan ID Barcode " + MacAddress + " | " + strIPAddress + " | " + version;
break;
case Symbol.Barcode.States.READY:
this.statusBar1.Text = "Ready - Scan ID Barcode " + MacAddress + " | " + strIPAddress + " | " + version;
break;
case Symbol.Barcode.States.WAITING:
//this.myScanner.StopRead();
//this.myScanner.StartRead(true);
this.statusBar1.Text = "Waiting- Scan ID Barcode " + MacAddress + " | " + strIPAddress + " | " + version;
break;
default:
this.statusBar1.Text = TheStatusData.Text + " " + MacAddress + " | " + strIPAddress + " | " + version;
break;
}
}
private void Form1_OnClosing(object Sender, EventArgs e)
{
if (isReaderInitiated)
{
myScanner.DetachReadNotify();
myScanner.DetachStatusNotify();
myScanner.TermReader();
}
}
private void pictureBox1_Click(object sender, EventArgs e)
{
this.Close();
}
private void pictureBox2_Click(object sender, EventArgs e)
{
this.myScanner.StopRead();
this.myScanner.StartRead(true);
}
}
}
This is still a work in progress, mind you, so there is some functionality missing, but I want to have the scanner workingfull before moving forward. Any help will be greatly appreciated, thank you.
Ok, I figured out that the scanner goes into a cycle of switching between Idle and Waiting status, this is why my StatusNotify event handler was making the scanner laser turn on and off repeatedly.
I solved it by saving the previous status, and only restarting the scanner when the previous status is not one of those two.
case Symbol.Barcode.States.WAITING:
if (lastScannerStatus != "WAITING" && lastScannerStatus != "INIT" && lastScannerStatus != "IDLE")
{
this.myScanner.StopRead();
this.myScanner.StartRead(true);
}
this.statusBar1.Text = "Waiting- Scan ID Barcode " + MacAddress + " | " + strIPAddress + " | " + version;
break;
I am basically trying to take input as RGB Stream from Kinect for Windows using the same code as given in the SDK (ColorBasics Example).
The code of the Example in SDK is as follow
public partial class MainWindow : Window
{
/// <summary>
/// Active Kinect sensor
/// </summary>
private KinectSensor sensor;
/// <summary>
/// Bitmap that will hold color information
/// </summary>
private WriteableBitmap colorBitmap;
/// <summary>
/// Intermediate storage for the color data received from the camera
/// </summary>
private byte[] colorPixels;
/// <summary>
/// Initializes a new instance of the MainWindow class.
/// </summary>
public MainWindow()
{
//InitializeComponent();
}
/// <summary>
/// Execute startup tasks
/// </summary>
/// <param name="sender">object sending the event</param>
/// <param name="e">event arguments</param>
private void WindowLoaded(object sender, RoutedEventArgs e)
{
// Look through all sensors and start the first connected one.
// This requires that a Kinect is connected at the time of app startup.
// To make your app robust against plug/unplug,
// it is recommended to use KinectSensorChooser provided in Microsoft.Kinect.Toolkit
foreach (var potentialSensor in KinectSensor.KinectSensors)
{
if (potentialSensor.Status == KinectStatus.Connected)
{
this.sensor = potentialSensor;
break;
}
}
if (null != this.sensor)
{
// Turn on the color stream to receive color frames
this.sensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
// Allocate space to put the pixels we'll receive
this.colorPixels = new byte[this.sensor.ColorStream.FramePixelDataLength];
// This is the bitmap we'll display on-screen
this.colorBitmap = new WriteableBitmap(this.sensor.ColorStream.FrameWidth, this.sensor.ColorStream.FrameHeight, 96.0, 96.0, PixelFormats.Bgr32, null);
// Set the image we display to point to the bitmap where we'll put the image data
this.Image.Source = this.colorBitmap;
// Add an event handler to be called whenever there is new color frame data
this.sensor.ColorFrameReady += this.SensorColorFrameReady;
// Start the sensor!
try
{
this.sensor.Start();
}
catch (IOException)
{
this.sensor = null;
}
}
if (null == this.sensor)
{
this.statusBarText.Text = Properties.Resources.NoKinectReady;
}
}
/// <summary>
/// Execute shutdown tasks
/// </summary>
/// <param name="sender">object sending the event</param>
/// <param name="e">event arguments</param>
private void WindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (null != this.sensor)
{
this.sensor.Stop();
}
}
/// <summary>
/// Event handler for Kinect sensor's ColorFrameReady event
/// </summary>
/// <param name="sender">object sending the event</param>
/// <param name="e">event arguments</param>
private void SensorColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
if (colorFrame != null)
{
// Copy the pixel data from the image to a temporary array
colorFrame.CopyPixelDataTo(this.colorPixels);
// Write the pixel data into our bitmap
this.colorBitmap.WritePixels(
new Int32Rect(0, 0, this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight),
this.colorPixels,
this.colorBitmap.PixelWidth * sizeof(int),
0);
}
}
}
/// <summary>
/// Handles the user clicking on the screenshot button
/// </summary>
/// <param name="sender">object sending the event</param>
/// <param name="e">event arguments</param>
private void ButtonScreenshotClick(object sender, RoutedEventArgs e)
{
if (null == this.sensor)
{
this.statusBarText.Text = Properties.Resources.ConnectDeviceFirst;
return;
}
// create a png bitmap encoder which knows how to save a .png file
BitmapEncoder encoder = new PngBitmapEncoder();
// create frame from the writable bitmap and add to encoder
encoder.Frames.Add(BitmapFrame.Create(this.colorBitmap));
string time = System.DateTime.Now.ToString("hh'-'mm'-'ss", CultureInfo.CurrentUICulture.DateTimeFormat);
string myPhotos = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
string path = Path.Combine(myPhotos, "KinectSnapshot-" + time + ".png");
// write the new file to disk
try
{
using (FileStream fs = new FileStream(path, FileMode.Create))
{
encoder.Save(fs);
}
this.statusBarText.Text = string.Format("{0} {1}", Properties.Resources.ScreenshotWriteSuccess, path);
}
catch (IOException)
{
this.statusBarText.Text = string.Format("{0} {1}", Properties.Resources.ScreenshotWriteFailed, path);
}
}
}
}
And the code in my application is as follows
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Kinect;
namespace VideoKinect
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private KinectSensor sensor;
private WriteableBitmap colorBitmap;
private byte[] colorPixels;
public MainWindow()
{
//InitializeComponent();
}
private void WindowLoaded(object sender, RoutedEventArgs e)
{
foreach (var potentialSensor in KinectSensor.KinectSensors)
{
if (potentialSensor.Status == KinectStatus.Connected)
{
this.sensor = potentialSensor;
break;
}
}
if (null != this.sensor)
{
// Turn on the color stream to receive color frames
this.sensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
// Allocate space to put the pixels we'll receive
this.colorPixels = new byte[this.sensor.ColorStream.FramePixelDataLength];
// This is the bitmap we'll display on-screen
this.colorBitmap = new WriteableBitmap(this.sensor.ColorStream.FrameWidth, this.sensor.ColorStream.FrameHeight, 96.0, 96.0, PixelFormats.Bgr32, null);
// Set the image we display to point to the bitmap where we'll put the image data
this.ColorImage.Source = this.colorBitmap;
// Add an event handler to be called whenever there is new color frame data
this.sensor.ColorFrameReady += this.SensorColorFrameReady;
// Start the sensor!
//try
//{
this.sensor.Start();
// }
// catch (IOException)
//{
this.sensor = null;
// }
}
if (null == this.sensor)
{
MessageBox.Show("No Kinect Available");
}
}
private void SensorColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
if (colorFrame != null)
{
// Copy the pixel data from the image to a temporary array
colorFrame.CopyPixelDataTo(this.colorPixels);
// Write the pixel data into our bitmap
this.colorBitmap.WritePixels(
new Int32Rect(0, 0, this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight),
this.colorPixels,
this.colorBitmap.PixelWidth * sizeof(int),
0);
}
}
}
}
}
But I am getting the Error at "IOException" in my code and the Image "ColorImage" is not being detected even though I named the image in my xaml file as the same.
I was able to compile and execute your code above with the expected behaviour - the only change was uncommenting the InitializeComponent(); and adding <Image x:Name="ColorImage"/> to the MainWindow.xaml.
What exactly does the IOException say? Can you double check that you Kinect sensor is connected properly via at least a USB 2.0 bus - 1.1 has insufficient bandwidth? Are you also sure that the sensor has sufficient power as you will need the kinect power supply cable. You could always check to see if the SDK is installed properly, have a look at this post.
With regards to it not finding your ColorImage rebuilding the solution should resolve the issue, assuming there is not a spelling mistake on the x:Name of the Image in XAML.
You messed up when you commented out the try ... catch statement, you left sensor = null; in there, after you started it, meaning you had no sensor. You should have commented that out.
// What it should be:
// try
// {
this.sensor.Start();
// }
// catch (IOException)
// {
// this.sensor = null; <- What it should be
// }
// What it is:
// try
// {
this.sensor.Start();
// }
// catch (IOException)
// {
this.sensor = null; //turns sensor null, then SensorColorFrame
// never gets called, etc.
// }
That line will ultimately destroy any Kinect program you ever write. Hope this helps!
you left out a reference. you need to include:
using System.IO;
at the very top. Hope This helps!
I have a method that loops ping requests, and I'd like when I click Ctrl+c, it break the loop and give me statics like the normal cmd, but when I click Ctrl+c, I get
Press Any Key To Continue... <<
and then program closes .
For example : ping google.com -t << that will ping google with endless loop, but I need to break the loop ONLY when I click Ctrl+c
private void _t(string website)
{
Ping pingSender = new Ping();
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 10000;
try
{
PingOptions options = new PingOptions(64, false);
PingReply send0 = pingSender.Send(website, timeout, buffer, options);
Console.WriteLine("\nPinging {0} [{1}] With {2} bytes of data :", website, send0.Address.ToString(), send0.Buffer.Length);
while (1 < 2)
{
PingReply reply = pingSender.Send(website, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine("Reply from {0}: Bytes {1} time={2} TTL={3}", reply.Address.ToString(), reply.Buffer.Length, reply.RoundtripTime / 5, reply.Options.Ttl);
}
else
{
Console.WriteLine("Request timed out.");
}
}
}
catch
{
Console.WriteLine("Ping request could not find host {0} ", website + ".Please check the name and try again.");
}
}
But instead of using while (1<2), I want to use something like :
while (ConsoleKeyInfo.Equals("Control + c") not clicked) // sure it is wrong , but that`s what I wanna achieve
{
PingReply reply = pingSender.Send(website, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine("Reply from {0}: Bytes {1} time={2} TTL={3}", reply.Address.ToString(), reply.Buffer.Length, reply.RoundtripTime / 5, reply.Options.Ttl);
}
else
{
Console.WriteLine("Request timed out.");
}
}
I might be a little late, but here's a better way, one that works on all platforms:
Console.TreatControlCAsInput = true;
There is a fairly complete tutorial (with code) here. I did a quick test and their example actually worked (imagine that).
Here is their code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Text;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using System.Threading;
using System.Reflection;
namespace ConsoleApplication1
{
class ControlChecker
{
#region GLOBAL VARS
private static readonly Mutex mutex = new Mutex(true, Assembly.GetExecutingAssembly().GetName().CodeBase);
private static bool _userRequestExit = false;
private static bool _doIStop = false;
static HandlerRoutine consoleHandler;
#endregion
[DllImport("Kernel32")]
public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add);
// A delegate type to be used as the handler routine for SetConsoleCtrlHandler.
public delegate bool HandlerRoutine(CtrlTypes CtrlType);
// An enumerated type for the control messages sent to the handler routine.
public enum CtrlTypes
{
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT,
CTRL_CLOSE_EVENT,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT
}
/// <summary>
///
/// </summary>
/// <param name="ctrlType"></param>
/// <returns></returns>
private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
{
// Put your own handler here
switch (ctrlType)
{
case CtrlTypes.CTRL_C_EVENT:
_userRequestExit = true;
Console.WriteLine("CTRL+C received, shutting down");
break;
case CtrlTypes.CTRL_BREAK_EVENT:
_userRequestExit = true;
Console.WriteLine("CTRL+BREAK received, shutting down");
break;
case CtrlTypes.CTRL_CLOSE_EVENT:
_userRequestExit = true;
Console.WriteLine("Program being closed, shutting down");
break;
case CtrlTypes.CTRL_LOGOFF_EVENT:
case CtrlTypes.CTRL_SHUTDOWN_EVENT:
_userRequestExit = true;
Console.WriteLine("User is logging off!, shutting down");
break;
}
return true;
}
/// <summary>
/// Main entry point
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
static int Main(string[] args)
{
try
{
//make sure we only have one....
if (!mutex.WaitOne(TimeSpan.Zero, true))
{
Console.WriteLine("Another instance already running");
Thread.Sleep(5000);
return 1;
}
//save a reference so it does not get GC'd
consoleHandler = new HandlerRoutine(ConsoleCtrlCheck);
//set our handler here that will trap exit
SetConsoleCtrlHandler(consoleHandler, true);
DoMyTask();
return 0;
}
catch (Exception x)
{
Console.WriteLine("Main Error [{0}]", x.Message);
return -1;
}
}
/// <summary>
/// Run the export
/// </summary>
/// <param name="pAuthority"></param>
/// <returns></returns>
private static void DoMyTask()
{
//execcute until we have no more records to process
while (!_doIStop)
{
//did user request exit?
if (_userRequestExit)
{
_doIStop = true; //set flag to exit loop. Other conditions could cause this too, which is why we use a seperate variable
Console.WriteLine("Shutting down, user requested exit");
break;
}
//do some other stuff here
Console.WriteLine(String.Format("{0}, no exit requested yet...", DateTime.Now));
//sleep 1 second
Thread.Sleep(1000);
}
}
}
}
Another way is to handle the Console.CancelKeyPress event:
Console.CancelKeyPress += Console_CancelKeyPress
This allows you to keep the shortcut, but decide whether to exit on a case by case basis.
private static void HandleConsole_CancelKeyPress(ConsoleCancelEventArgs consoleCancelEventArgs)
{
if (doNotExitYet) {
consoleCancelEventArgs.Cancel = true;
}
}
I just started learning how to send and receive data from my hardware through the C# GUI.
Can anyone please write a detail how to read data from the serial port?
SerialPort (RS-232 Serial COM Port) in C# .NET
This article explains how to use the SerialPort class in .NET to read and write data, determine what serial ports are available on your machine, and how to send files. It even covers the pin assignments on the port itself.
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());
}
}
}
I spent a lot of time to use SerialPort class and has concluded to use SerialPort.BaseStream class instead. You can see source code: SerialPort-source and
SerialPort.BaseStream-source for deep understanding.
I created and use code that shown below.
The core function
public int Recv(byte[] buffer, int maxLen)
has name and works like "well known" socket's recv().
It means that
in one hand it has timeout for no any data and throws TimeoutException.
In other hand, when any data has received,
it receives data either until maxLen bytes
or short timeout (theoretical 6 ms) in UART data flow
.
public class Uart : SerialPort
{
private int _receiveTimeout;
public int ReceiveTimeout { get => _receiveTimeout; set => _receiveTimeout = value; }
static private string ComPortName = "";
/// <summary>
/// It builds PortName using ComPortNum parameter and opens SerialPort.
/// </summary>
/// <param name="ComPortNum"></param>
public Uart(int ComPortNum) : base()
{
base.BaudRate = 115200; // default value
_receiveTimeout = 2000;
ComPortName = "COM" + ComPortNum;
try
{
base.PortName = ComPortName;
base.Open();
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine("Error: Port {0} is in use", ComPortName);
}
catch (Exception ex)
{
Console.WriteLine("Uart exception: " + ex);
}
} //Uart()
/// <summary>
/// Private property returning positive only Environment.TickCount
/// </summary>
private int _tickCount { get => Environment.TickCount & Int32.MaxValue; }
/// <summary>
/// It uses SerialPort.BaseStream rather SerialPort functionality .
/// It Receives up to maxLen number bytes of data,
/// Or throws TimeoutException if no any data arrived during ReceiveTimeout.
/// It works likes socket-recv routine (explanation in body).
/// Returns:
/// totalReceived - bytes,
/// TimeoutException,
/// -1 in non-ComPortNum Exception
/// </summary>
/// <param name="buffer"></param>
/// <param name="maxLen"></param>
/// <returns></returns>
public int Recv(byte[] buffer, int maxLen)
{
/// The routine works in "pseudo-blocking" mode. It cycles up to first
/// data received using BaseStream.ReadTimeout = TimeOutSpan (2 ms).
/// If no any message received during ReceiveTimeout property,
/// the routine throws TimeoutException
/// In other hand, if any data has received, first no-data cycle
/// causes to exit from routine.
int TimeOutSpan = 2;
// counts delay in TimeOutSpan-s after end of data to break receive
int EndOfDataCnt;
// pseudo-blocking timeout counter
int TimeOutCnt = _tickCount + _receiveTimeout;
//number of currently received data bytes
int justReceived = 0;
//number of total received data bytes
int totalReceived = 0;
BaseStream.ReadTimeout = TimeOutSpan;
//causes (2+1)*TimeOutSpan delay after end of data in UART stream
EndOfDataCnt = 2;
while (_tickCount < TimeOutCnt && EndOfDataCnt > 0)
{
try
{
justReceived = 0;
justReceived = base.BaseStream.Read(buffer, totalReceived, maxLen - totalReceived);
totalReceived += justReceived;
if (totalReceived >= maxLen)
break;
}
catch (TimeoutException)
{
if (totalReceived > 0)
EndOfDataCnt--;
}
catch (Exception ex)
{
totalReceived = -1;
base.Close();
Console.WriteLine("Recv exception: " + ex);
break;
}
} //while
if (totalReceived == 0)
{
throw new TimeoutException();
}
else
{
return totalReceived;
}
} // Recv()
} // Uart
Note that usage of a SerialPort.DataReceived event is optional. You can set proper timeout using SerialPort.ReadTimeout and continuously call SerialPort.Read() after you wrote something to a port until you get a full response.
Moreover, you can use SerialPort.BaseStream property to extract an underlying Stream instance. The benefit of using a Stream is that you can easily utilize various decorators with it:
var port = new SerialPort();
// LoggingStream inherits Stream, implements IDisposable, needed abstract methods and
// overrides needed virtual methods.
Stream portStream = new LoggingStream(port.BaseStream);
portStream.Write(...); // Logs write buffer.
portStream.Read(...); // Logs read buffer.
For more information:
Top 5 SerialPort Tips article by Kim Hamilton, BCL Team Blog
C# await event and timeout in serial port communication discussion on StackOverflow