incomplete header with socket c# - c#

Hi I've try to send and http request to a Shoutcast stream site and then read response,
I've this two sources one is the main ( I've tested with wpf) and other is a little
helper for socket... well all works, with localhost and other site
but when I try to send a request to "209.9.238.6:6042" the header in response is never
complete but truncked.
I've done a lot of test but nothing it works only with a Thread.sleep(200);
between the send and receive look at (1), so it seems that listen() come too early and
only a part is downloaded...
can You help me?
main.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void connectionButton_Click(object sender, RoutedEventArgs e)
{
var url = "209.9.238.6:6042";
var sockHelp = new SocketHelper(url);
sockHelp.onConnect += sockHelp_onConnect;
sockHelp.connect();
}
void testDebug(string str) {
Action action = () => debugTxt.Text = str;
Dispatcher.BeginInvoke(action);
}
void sockHelp_onConnect(object sender, SocketHelperEventArgs e)
{
var sockHelp = sender as SocketHelper;
testDebug("Connected");
var header = "";
header+="GET / HTTP/1.0\r\n";
header+="Accept: */*\r\n";
header+="Host: 209.9.238.6\r\n";
header+="Connection: close\r\n\r\n";
sockHelp.onSend += sockHelp_onSend;
sockHelp.sendAsync(Encoding.UTF8.GetBytes(header));
}
private void sockHelp_onSend(object sender, SocketAsyncEventArgs e)
{
var sockHelp = sender as SocketHelper;
sockHelp.onReceive+=sockHelp_onReceive;
//Thread.Sleep(200); (1) uncomment this line... to make works
sockHelp.listen();
}
void sockHelp_onReceive(object sender, SocketAsyncEventArgs arg_)
{
testDebug("Receiving");
var t = Encoding.UTF8.GetString(arg_.Buffer);
var idx = IndexOf(arg_.Buffer, new byte[] { 0x0d, 0x0a, 0x0d, 0x0a });
if (idx < 0)
{
testDebug(Encoding.UTF8.GetString(arg_.Buffer));
return ;
}
byte[] binBuff = new byte[idx + 1];
System.Buffer.BlockCopy(arg_.Buffer, 0, binBuff, 0, idx + 1);
testDebug(Encoding.UTF8.GetString(binBuff));
}
private int IndexOf(byte[] searchIn, byte[] searchFor)
{
if ((searchIn != null) && (searchIn != null))
{
if (searchFor.Length > searchIn.Length) return 0;
for (int i = 0; i < searchIn.Length; i++)
{
int startIndex = i;
bool match = true;
for (int j = 0; j < searchFor.Length; j++)
{
if (searchIn[startIndex] != searchFor[j])
{
match = false;
break;
}
else if (startIndex < searchIn.Length)
{
startIndex++;
}
}
if (match)
return startIndex - searchFor.Length;
}
}
return -1;
}
}
}
helper.cs
namespace TestSocket
{
/// <summary>
/// </summary>
public class SocketHelperEventArgs : EventArgs
{
public SocketHelperEventArgs(SocketError se)
{
socketError = se;
}
public SocketHelperEventArgs() { }
SocketError socketError;
SocketAsyncEventArgs args;
}
public class SocketHelper
{
byte[] _buffer = new byte[1024*2];
SocketAsyncEventArgs _args = new SocketAsyncEventArgs();
readonly Socket _socket;
public event EventHandler<SocketHelperEventArgs> onError;
public event EventHandler<SocketHelperEventArgs> onConnect;
public event EventHandler<SocketAsyncEventArgs> onReceive;
public event EventHandler<SocketAsyncEventArgs> onSend;
public SocketHelper(string url)
{
int port=0;
string[] addressVector = url.Split(':');
if (addressVector.Length == 1)
port = 80;
else
port = int.Parse(addressVector[1]);
_args.RemoteEndPoint = new DnsEndPoint(addressVector[0], port); ;
_args.Completed += SocketAsyncEventArgs_Completed;
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
public void listen()
{
_args.SetBuffer(_buffer, 0, _buffer.Length);
_socket.ReceiveAsync(_args);
}
public void connect()
{
bool completesAsynchronously = _socket.ConnectAsync(_args);
if (!completesAsynchronously)
{
SocketAsyncEventArgs_Completed(_args.ConnectSocket, _args);
}
}
public void sendAsync(byte[] data) {
_args.SetBuffer(data, 0, data.Length);
_socket.SendAsync(_args);
}
private void SocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e)
{
// check for errors
if (e.SocketError != SocketError.Success)
{
if (onError != null) onError(this, new SocketHelperEventArgs(e.SocketError));
CleanUp(e);
return;
}
switch (e.LastOperation)
{
case SocketAsyncOperation.Connect:
if (onConnect != null) onConnect(this, EventArgs.Empty as SocketHelperEventArgs);
break;
case SocketAsyncOperation.Send:
if (onSend!= null) onSend(this, e);
break;
case SocketAsyncOperation.Receive:
if (onReceive != null) onReceive(this,e);
break;
}
}
private void CleanUp(SocketAsyncEventArgs e)
{
if (e.ConnectSocket != null)
{
e.ConnectSocket.Shutdown(SocketShutdown.Both);
e.ConnectSocket.Close();
}
}
}
}

You seem to assume that you will get the whole response in one read. That's not correct. You will get some data from the socket when data is available. You need to detect whether there's more data to come according to the application-level protocol - HTTP or ICY or whatever you are using, and, if so, re-arm the asynchronous read.
Right now you are consuming whatever happens to be in the socket receive buffer. Waiting seems to work just because more data piles up there after that timeout, but there's no guarantee you are getting everything.

Related

As my program (C#, NAudio) is playing an audio file, if it encounters 1 min of silence, I want to skip it

My app plays audio files. As the it plays, I want to examine what's going to play for the next minute to see if it will all be silence; If so, I want to skip over the silence.
I'm trying to find a way to look at the stream before it's handed to WaveOutEvent. I'm chaining AudioFileReader, SampleChannel, and OffsetSampleProvider. I haven't found a method that would allow me to simply "peek" at upcoming data. I have looked at Mark Heath's PluralSight courses and the NAudio source code.
//This code is based on examples for Mark Health's NAudo Course on PluralSight.
...
private string fileName;
private IWavePlayer waveOut;
ISampleProvider sampleProvider;
private ISampleProvider CreateInputStream(string fileName)
{
audioFileReader = new AudioFileReader(fileName);
var sampleChannel = new SampleChannel(audioFileReader, true);
var offsetSampleProvider = new OffsetSampleProvider(sampleChannel);
return offsetSampleProvider;
}
private void Play()
{
...
if (waveOut != null)
{
if (waveOut.PlaybackState == PlaybackState.Playing)
{
return;
}
else if (waveOut.PlaybackState == PlaybackState.Paused)
{
waveOut.Play();
return;
}
}
if (string.IsNullOrEmpty(fileName)) GetFileName();
if (string.IsNullOrEmpty(fileName)) return;
try
{
CreateWaveOut();
}
catch (Exception driverCreateException)
{
MessageBox.Show(String.Format("{0}", driverCreateException.Message));
return;
}
try
{
sampleProvider = CreateInputStream(fileName);
}
catch (Exception createException)
{
MessageBox.Show(String.Format("{0}", createException.Message), "Error Loading File");
return;
}
...
try
{
waveOut.Init(sampleProvider);
}
catch (Exception initException)
{
MessageBox.Show(String.Format("{0}", initException.Message), "Error Initializing Output");
return;
}
SetVolume();
waveOut.Play();
}
private void CreateWaveOut()
{
CloseWaveOut();
waveOut = new WaveOutEvent();
waveOut.PlaybackStopped += OnPlaybackStopped;
}
private void OnPlaybackStopped(object sender, StoppedEventArgs e)
{
if (e.Exception != null) MessageBox.Show(e.Exception.Message, "Playback Device Error");
if (audioFileReader != null) audioFileReader.Position = 0;
}
private AudioFileReader audioFileReader;
private void CloseWaveOut()
{
if (waveOut != null) waveOut.Stop();
if (audioFileReader != null)
{
audioFileReader.Dispose();
audioFileReader = null;
}
if (waveOut != null)
{
waveOut.Dispose();
waveOut = null;
}
}
...
private void playToolStripButton_Click(object sender, EventArgs e)
{
Play();
}
...
private void stopToolStripButton_Click(object sender, EventArgs e)
{
if (waveOut != null) waveOut.Stop();
}
private void openToolStripButton_Click(object sender, EventArgs e)
{
GetFileName();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (waveOut != null && audioFileReader != null)
{
TimeSpan currentTime = (waveOut.PlaybackState == PlaybackState.Stopped) ? TimeSpan.Zero : audioFileReader.CurrentTime;
trackBar1.Value = Math.Min(trackBar1.Maximum, (int)(100 * currentTime.TotalSeconds / audioFileReader.TotalTime.TotalSeconds));
currentTimeStripLabel.Text = String.Format("{0:00}:{1:00}", (int)currentTime.TotalMinutes, currentTime.Seconds);
}
else
{
trackBar1.Value = 0;
}
}
private void pauseToolStripButton_Click(object sender, EventArgs e)
{
if (waveOut != null)
{
if (waveOut.PlaybackState == PlaybackState.Playing) waveOut.Pause();
}
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
if (waveOut != null)
{
audioFileReader.CurrentTime = TimeSpan.FromSeconds(audioFileReader.TotalTime.TotalSeconds * trackBar1.Value / 100.0);
}
}
}
}
When the user listens to the dictation, silence that's greater than 1 min with be skipped.
--- this is additional info regarding my question ---
I watched the section of your PluralSight regarding how to Implement an ISampleProvider. Pretty straightforward, thank you! Here's what I have. (See below.) But don't know how to create the in memory buffer you talked about. Do I use BufferedWaveProvider?
public class SkipSilenceSampleProvider : ISampleProvider
{
public WaveFormat WaveFormat
{
get { return sourceProvider.WaveFormat; }
}
private readonly ISampleProvider sourceProvider;
public SkipSilenceSampleProvider(ISampleProvider sourceProvider)
{
this.sourceProvider = sourceProvider;
}
public int Read(float[] buffer, int offset, int count)
{
// Extract samples for the next minute and determine if the whole range is silence.
int readCount = sourceProvider.Read(buffer, offset, count);
return readCount;
}
}
You could implement this by implementing a custom ISampleProvider that wraps your AudioFileReader. In the Read method, you'd need to read ahead enough from the source AudioFileReader to determine if there is silence that needs to be skipped. So you'd need a memory buffer containing a minutes worth of audio. Then the Read method should return the next non-silent samples. Read should always return the number of samples asked for unless you have reached the end of the source file.

Serial Port Unauthorized Exception

I am trying to access RFID Reader through Arduino application which gives me the right output on control monitor.
But when I tried to access it through visual studio C#, it works only once and then gives me access is denied! And also stopped working on Arduino IDE.
//Function to initialize serial port
SerialPort RFIDPort
public SerialPort initializeRFIDPort()
{
try
{
RFIDPort = new SerialPort("COM4",9600,Parity.None,8, StopBits.One);
if (RFIDPort.IsOpen)
RFIDPort.Close();
if(!RFIDPort.IsOpen)
RFIDPort.Open();
}
catch (UnauthorizedAccessException ex) {MessageBox.Show( ex.Message); }
catch (Exception)
{
RFIDPort = null;
}
return RFIDPort;
}
I put the function here:
public products()
{
InitializeComponent();
initializeRFIDPort();
}
There is two scan button the first one for scanning and then add data to the database and the second button is to scan and search for data
private void ScanButton_Click(object sender, EventArgs e)
{
try
{
scanButtonIsClicked = true;
if (RFIDPort.IsOpen)
{
RFIDPort.DataReceived += serialPort1_DataReceived;
textBox1.Text = "";
}
else
MessageBox.Show("RFID Reader is not connected!");
}
catch (System.Exception)
{
MessageBox.Show("Please Try Again");
}
}
private void Searchbutton_Click(object sender, EventArgs e)
{
scansearchbtn = true;
scanButtonIsClicked = false;
try
{
if (RFIDPort.IsOpen)
{
RFIDPort.DataReceived += serialPort1_DataReceived;
textBox2.Text = "";
}
else
{
MessageBox.Show("RFID Reader is not connected!");
}
}
catch (IOException)
{
MessageBox.Show("Please reconnect your device ");
}
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
try
{
string line = RFIDPort.ReadLine();
if (scanButtonIsClicked == true)
this.BeginInvoke(new LineReceivedEvent(LineReceived), line);
else
this.BeginInvoke(new LineReceivedEvent(Line2Received), line);
}
catch (TimeoutException) { }
catch (Exception){ MessageBox.Show("Can't Read from RFID Device.Please try again"); }
}
private delegate void LineReceivedEvent(string line);
private void LineReceived(string line)
{
textBox2.Text = line;
}
private void Line2Received(string line)
{
textBox1.Text = line;
}
And then I closed serial port in Forum-Closing.
Please if anyone can lead me to the right way. I have try many times and it works randomly!
On Aruino side this is my code:
#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class
MFRC522::MIFARE_Key key;
// Init array that will store new NUID
byte nuidPICC[10];
void setup()
{
Serial.begin(9600);
SPI.begin(); // Init SPI bus
rfid.PCD_Init(); // Init MFRC522
for (byte i = 0; i < 6; i++)
{
key.keyByte[i] = 0xFF;
}
printHex(key.keyByte, MFRC522::MF_KEY_SIZE);
Serial.println();
}
void loop()
{
if ( ! rfid.PICC_IsNewCardPresent())
return;
if ( ! rfid.PICC_ReadCardSerial())
return;
// Serial.print(F("PICC type: "));
MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
// Serial.println(rfid.PICC_GetTypeName(piccType));
// Check is the PICC of Classic MIFARE type
if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI && piccType !=
MFRC522::PICC_TYPE_MIFARE_1K && piccType != MFRC522::PICC_TYPE_MIFARE_4K)
{
Serial.println(F("Your tag is not of type MIFARE Classic."));
return;
}
// Store NUID into nuidPICC array
for (byte i = 0; i < 4; i++)
{
nuidPICC[i] = rfid.uid.uidByte[i];
}
printHex(rfid.uid.uidByte, rfid.uid.size);
Serial.println();
// Halt PICC
rfid.PICC_HaltA();
// Stop encryption on PCD
rfid.PCD_StopCrypto1();
}
void printHex(byte *buffer, byte bufferSize)
{
for (byte i = 0; i < bufferSize; i++) {
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], HEX);
}
}

Not getting response from Lane Control Board

I'm trying to get inputs/outputs from a LCB(lane control board),which in serial. I'm using prolific usb-serial as the interface . I'm new to programming,but i've managed to get send/receive inputs when i shorted pin 2 and 3 of DB9 together . But when i plugged the db9 connector to the LCB , it can send , but not receiving any .
I'm using VS2010 in Windows 10.
Below are my snippets ;
namespace serialPort_wengweng
{
public partial class Form1 : Form
{
byte[] DataReceived = new byte[4096];
byte[] DataTransmitted = new byte[15] { 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15 };
ArrayList ar = new ArrayList();
//------------------------------------LCB input properties here-START------------------------//
String LCBInput;
Boolean i1, i2, i3, i4, i5, i6, i7, i8 = false;
//------------------------------------LCB input properties here-START------------------------//
public Form1()
{
InitializeComponent();
this.serialPort1.DataReceived +=new SerialDataReceivedEventHandler(serialPort1_DataReceived);
}
private void btnConnect_Click(object sender, EventArgs e)
{
Console.Write("Connect button pressed .. ");
//if (serialPort1.IsOpen == true)
//{
//}
//else
// MessageBox.Show("");
if (btnConnect.Text == "Connect")
{
serialPort1.PortName = Convert.ToString(cboPortNames.SelectedItem);
serialPort1.BaudRate = Convert.ToInt32(cboBaudRate.SelectedItem);
serialPort1.DataBits = Convert.ToInt32(cboDataBits.SelectedItem);
serialPort1.DtrEnable = true;
serialPort1.Handshake = (Handshake)Enum.Parse(typeof(Handshake), cboHandshake.SelectedItem.ToString());
serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), cboStopBits.SelectedItem.ToString());
serialPort1.RtsEnable = true;
serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), cboParity.SelectedItem.ToString());
try
{
if (serialPort1.IsOpen) serialPort1.Close();
serialPort1.Open();
progressBar.Value = 100;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
btnConnect.Text = "Disconnect";
}
else
{
btnConnect.Text = "Connect";
if (serialPort1.IsOpen) serialPort1.Close();
progressBar.Value = 0;
txtTX.Text = String.Empty;
txtRXAll.Text = String.Empty;
txtRXParsing1.Text = String.Empty;
}
Console.WriteLine("Done!");
}
void UpdateTextBox(TextBox objTextBox, String DataParsing)
{
Console.WriteLine("In Update Text Box...");
objTextBox.AppendText(DataParsing);
Console.WriteLine("Done!");
}
void ReceivedData(TextBox objTextBox, String DataParsing)
{
Console.WriteLine("In ReceivedData...");
if (objTextBox.InvokeRequired)
{
this.Invoke(new Action<TextBox, String>(UpdateTextBox), new object[] { objTextBox, DataParsing });
}
Console.WriteLine("Done!");
}
private void PrintValues(ArrayList ar, ComboBox objComboBox)
{
Console.Write("Printing Values... ");
try
{
if (objComboBox.Name == "cboPortNames")
{
foreach (var v in ar)
{
objComboBox.Items.Add("COM" + v);
}
}
else
{
foreach (var v in ar)
{
objComboBox.Items.Add(v);
}
}
}
catch (NotImplementedException nie)
{
Console.WriteLine(nie);
Console.WriteLine("Print Values T.T");
}
Console.WriteLine("Done!");
}
private void Form1_Load(object sender, EventArgs e)
{
Console.Write("In Form Load()");
GetPortNames();
GetBaudRate();
GetDataBits();
GetParity();
GetStopBits();
GetHandshake();
txtTX.Text = ASCIIEncoding.ASCII.GetString(DataTransmitted);
Console.WriteLine("Done!");
}
void GetPortNames()
{
Console.Write("Getting Port Names..");
ar.Clear();
foreach (String s in SerialPort.GetPortNames())
{
ar.Add(s.Substring(3));
}
ar.Sort();
PrintValues(ar, cboPortNames);
cboPortNames.SelectedIndex = 0;
Console.WriteLine("Done!");
}
void GetBaudRate()
{
Console.Write("Getting BaudRate..");
ar.Clear();
ar.Add(110);
ar.Add(300);
ar.Add(1200);
ar.Add(2400);
ar.Add(4800);
ar.Add(9600);
ar.Add(19200);
ar.Add(38400);
ar.Add(57600);
ar.Add(115200);
ar.Add(230400);
ar.Add(460800);
ar.Add(921600);
PrintValues(ar, cboBaudRate);
cboBaudRate.SelectedIndex = 5;
Console.WriteLine("Done!");
}
void GetDataBits()
{
Console.Write("Getting Data Bits..");
ar.Clear();
for (int i = 5; i <= 8; i++)
{
ar.Add(i);
}
PrintValues(ar, cboDataBits);
cboDataBits.SelectedIndex = 3;
Console.WriteLine("Done!");
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Console.Write("In Data Received ..");
int i = 0;
string dtString="";
string[] dtArray; // data string saving in here
Thread.Sleep(500); // wait data ready
while (serialPort1.BytesToRead > 0) // if data ready in buffer
{
DataReceived[i] = Convert.ToByte(serialPort1.ReadByte()); // read data serial & saving to array byte
i++; // counter buffer
}
if (i == 15 && DataReceived[14]==15)
{
dtString = ASCIIEncoding.ASCII.GetString(DataReceived); // convert array byte to string
dtArray = dtString.Split((char)44); // parsing string data with separator char(44)
ReceivedData(txtRXAll, dtString); // complete receive data show in here
ReceivedData(txtRXParsing1, dtArray[0]); // data first show in here
}
Console.WriteLine("Done!");
}
private void btnExit_Click(object sender, EventArgs e)
{
Console.Write("Button Exit Pressed..");
if (serialPort1.IsOpen == true)
{
MessageBox.Show("Force quit serial port", "Exit", MessageBoxButtons.OK, MessageBoxIcon.Warning);
Application.Exit();
}
else {
Application.Exit();
Console.WriteLine("Serial port closed,quitting app now.");
Thread.Sleep(1000);
}
Console.WriteLine("Done!");
}
private void btnSend_Click(object sender, EventArgs e)
{
Console.Write("Button Send Pressed..");
if (serialPort1.IsOpen)
{
Console.WriteLine("Shoulda write something.");
var collector = new DataCollector("COM6", ProcessMeasurement);
serialPort1.Write(txtTX.Text);
Thread.Sleep(500);
//Console.WriteLine(serialPort1.Read());
}
else {
MessageBox.Show("Not receiving anything", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
Console.WriteLine("Done!");
}
private void ProcessMeasurement(List<byte> bytes)
{
Console.WriteLine("In process measurement...");
}
private void GetHandshake()
{
Console.WriteLine("Get Handshake ...");
try
{
ar.Clear();
foreach (String s in Enum.GetNames(typeof(Handshake)))
{
ar.Add(s);
}
PrintValues(ar, cboHandshake);
cboHandshake.SelectedIndex = 0;
}
catch (NotImplementedException nie)
{
Console.WriteLine(nie);
}
}
private void GetStopBits()
{
Console.WriteLine("Get StopBits ....");
try
{
ar.Clear();
foreach (String s in Enum.GetNames(typeof(StopBits)))
{
if (s != "None") ar.Add(s);
}
PrintValues(ar, cboStopBits);
cboStopBits.SelectedIndex = 0;
}
catch (NotImplementedException nie)
{
Console.WriteLine(nie);
}
}
private void GetParity()
{
Console.WriteLine("Get Parity ....");
try
{
ar.Clear();
foreach (String s in Enum.GetNames(typeof(Parity)))
{
ar.Add(s);
}
PrintValues(ar, cboParity);
cboParity.SelectedIndex = 0;
}
catch (NotImplementedException nie)
{
Console.WriteLine(nie);
}
}
}
}
And here is DataCollector class,
namespace serialPort_wengweng
{
class DataCollector
{
private readonly Action<List<byte>> _processMeasurement;
private readonly string _port;
private SerialPort _serialPort;
private const int SizeOfMeasurement = 4;
List<byte> Data = new List<byte>();
public DataCollector(string port, Action<List<byte>> processMeasurement)
{
Console.WriteLine("in Data Collector ..");
_processMeasurement = processMeasurement;
_serialPort = new SerialPort(port);
_serialPort.DataReceived += SerialPortDataReceived;
Console.WriteLine("Done!");
}
private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
while (_serialPort.BytesToRead > 0)
{
var count = _serialPort.BytesToRead;
var bytes = new byte[count];
Console.WriteLine(_serialPort.Read(bytes, 0, count));
AddBytes(bytes);
}
}
private void AddBytes(byte[] bytes)
{
Data.AddRange(bytes);
while (Data.Count > SizeOfMeasurement)
{
var measurementData = Data.GetRange(0, SizeOfMeasurement);
Data.RemoveRange(0, SizeOfMeasurement);
if (_processMeasurement != null) _processMeasurement(measurementData);
}
}
}
}

c# Serial DataReceived very slow

I've trying to communicate with an Arduino Due in C#. The communikation works quite well, but my DataReceived handler needs about 1 second to react. This is my problem because I have to send up to 1 billion (1*10E9) commands.
If I activate a DEBUG Setting in the Arduino, it tells me that it's need 64 Milliseconds for a command. I think the C# the App should get it no later than 80 Milliseconds after sending it.
Here is a Part of the Code:
StopWatch s1 = new StopWatch();
private void Open_Port()
{
string port = null;
int baud = 0;
bool ERR = false;
if ((COM_cb.SelectedItem != null) | (BAUD_cb.SelectedItem != null))
{
port = this.COM_cb.GetItemText(this.COM_cb.SelectedItem);
baud = Convert.ToInt32(this.BAUD_cb.GetItemText(this.BAUD_cb.SelectedItem));
ERR = false;
}
else
{
ERR = true;
System.Windows.Forms.MessageBox.Show("Error Msg");
}
if (ERR == false)
{
serialPort1.PortName = port;
serialPort1.BaudRate = baud;
serialPort1.Open();
}
if (serialPort1.IsOpen)//Kalibrieren der Buttons
{
OPEN_btn.Enabled = false;
CLOSE_btn.Enabled = true;
textBox1.ReadOnly = false;
ERR = true;
}
}
private void Print_Click(object sender, EventArgs e) // start
{
Thread t = new Thread(transmit_pic);
t.Start();
}
private void DataReceivedHandler(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
s1.Stop();
//Till this line it take 1 Second after sending
//string t = "";
int byt = serialPort1.BytesToRead;
byte[] buffer = new byte[1];
for (int i = 0; i < byt; i++)
{
serialPort1.Read(buffer, 0, 1);
if(buffer[0] == '0') {
got_answer = true;
}
//t += (char)buffer[0];
}
//RxString= t;
//this.Invoke(new EventHandler(DisplayText));
}
private void sendAktion(int[,] data)
{
string s = int_to_string(data, false);
Console.Write("Send->");
serialPort1.Write(s);
s1.Start();
got_answer = false;
int i = 0;
while (!got_answer) { i++; } //wait for answer
i = 0;
Console.WriteLine("back again ");
}
private void transmit_pic()
{
stop = false;
Bitmap bm = new Bitmap(img);
if (!serialPort1.IsOpen)
{
MessageBox.Show("Open the Serial Port first!");
}
else
{
int size_X = bm.Width;
int size_Y = bm.Height;
for (int h = 0; h < size_Y; h++)
{
for (int w = 0; w < size_X; w++)
{
if(/*somthing happend*/){
//get data...
sendAktion(data)
}
}
}
Console.WriteLine("DONE");
}
}
Does anyone an Idea why c# needs so long to call the datahandler?
Sincere regards,
Fabian Harmsen
UPDATE
- Added comment to DataHandler (24.02.2016 16:30 Europa/Berlin)
The problem lies in the serialPort1_DataReceived received data handler.
I ran a separate thread with a while(true) loop and serial.ReadLine(), all works perfectly.
Hope someone else doesn't need to spend 3 hours fixing this.
using System.Threading;
public void main()
{
setup();
Thread readThread = new Thread(Read);
readThread.Start();
}
public void Read()
{
while(true)
{
try
{
string message = serialPort1.ReadLine();
}
catch (Exception)
{ }
}

How to add realtime data from OPC client to user control using c#

I created an OPC client to connect to KepServerEX, I got realtime data from KepServerEX and now I want to add realtime data to user control that contains a textbox.
Realtime data will be updated via value_changed event.
I created Windows Form Application and added textbox to Form to display realtime value, I can not post images here.
This is my code:
namespace OPC_Client
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
OPCServer KepServer;
OPCGroups KepGroups;
OPCGroup KepGroup;
OPCItems KepItems;
OPCItem KepItem;
string strHostIP = "";
string strHostName = "";
bool opc_connected = false;
int itmHandleClient = 0;
int itmHandleServer = 0;
private bool CreateGroup()
{
try
{
KepGroups = KepServer.OPCGroups;
KepGroup = KepGroups.Add("OPCDOTNETGROUP");
SetGroupProperty();
KepGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
KepGroup.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(KepGroup_AsyncWriteComplete);
KepItems = KepGroup.OPCItems;
}
catch (Exception)
{
return false;
}
return true;
}
private void SetGroupProperty()
{
KepServer.OPCGroups.DefaultGroupIsActive = true;
KepServer.OPCGroups.DefaultGroupDeadband = 0;
KepGroup.UpdateRate = 1000;
KepGroup.IsActive = true;
KepGroup.IsSubscribed = true;
}
private void RecurBrowse(OPCBrowser OPCBrowser)
{
OPCBrowser.ShowBranches();
OPCBrowser.ShowLeafs(true);
listBox1.Items.Clear();
foreach (object turn in OPCBrowser)
{
bool bl = turn.ToString().Contains("System") ;
if (bl == false)
{
if (!Regex.IsMatch(turn.ToString(), #"^(\w+\.\w+\.\w+)$"))
{
}
else
{
listBox1.Items.Add(turn.ToString());
}
}
}
}
private bool ConnectRemoteServer(string remoteServerIP, string remoteServerName)
{
try
{
KepServer.Connect(remoteServerName, remoteServerIP);
}
catch (Exception ex)
{
MessageBox.Show(""+ex);
return false;
}
return true;
}
// Write the TAG value when executed event
void KepGroup_AsyncWriteComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors)
{
lblState.Text = "";
for (int i = 1; i <= NumItems; i++)
{
lblState.Text += "Tran:" + TransactionID.ToString() + " CH:" + ClientHandles.GetValue(i).ToString() + "Error:" + Errors.GetValue(i).ToString();
}
}
void KepGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
{
for (int i = 1; i <= NumItems; i++)
{
if (Qualities.GetValue(i).ToString() == "192")
{
// add realtime value to texbox to display
txtTagValue.Text = ItemValues.GetValue(i).ToString();
txtQualities.Text = Qualities.GetValue(i).ToString();
txtTimeStamps.Text = TimeStamps.GetValue(i).ToString();
}
else
{
MessageBox.Show("disconnected to opc server");
txtQualities.Text = Qualities.GetValue(i).ToString();
txtTimeStamps.Text = TimeStamps.GetValue(i).ToString();
}
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
if (itmHandleClient != 0)
{
Array Errors;
OPCItem bItem = KepItems.GetOPCItem(itmHandleServer);
int[] temp = new int[2] { 0, bItem.ServerHandle };
Array serverHandle = (Array)temp;
KepItems.Remove(KepItems.Count, ref serverHandle, out Errors);
}
itmHandleClient = 1;
KepItem = KepItems.AddItem(listBox1.SelectedItem.ToString(), itmHandleClient);
itmHandleServer = KepItem.ServerHandle;
}
catch (Exception err)
{
itmHandleClient = 0;
txtTagValue.Text = "Error ox";
txtQualities.Text = "Error ox";
txtTimeStamps.Text = "Error ox";
MessageBox.Show("The reserved for system entry:" + err.Message, "message");
}
}
private void Form1_Load(object sender, EventArgs e)
{
//GetLocalServer();
KepServer = new OPCServer();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (!opc_connected)
{
return;
}
if (KepGroup != null)
{
KepGroup.DataChange -= new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
}
if (KepServer != null)
{
KepServer.Disconnect();
KepServer = null;
}
opc_connected = false;
}
private void btnSetGroupPro_Click(object sender, EventArgs e)
{
SetGroupProperty();
}
private void btnConnLocalServer_Click(object sender, EventArgs e)
{
try
{
if (!ConnectRemoteServer(txtRemoteServerIP.Text.Trim(), "KEPware.KEPServerEx.V5"))
{
return;
}
btnSetGroupPro.Enabled = true;
opc_connected = true;
GetServerInfo();
RecurBrowse(KepServer.CreateBrowser());
if (!CreateGroup())
{
return;
}
}
catch (Exception ex)
{
MessageBox.Show("" + ex);
}
}
private void btnWrite_Click(object sender, EventArgs e)
{
OPCItem bItem = KepItems.GetOPCItem(itmHandleServer);
int[] temp = new int[2] { 0, bItem.ServerHandle };
Array serverHandles = (Array)temp;
Object[] valueTemp = new Object[] { "", txtWriteTagValue.Text };
Array values = (Array)valueTemp;
Array Errors;
int cancelID;
KepGroup.AsyncWrite(1, ref serverHandles, ref values, out Errors, 2009, out cancelID);
GC.Collect();
}
}
}
Now I want to create some User Controls to display some tag values.What should I do?
This is a pretty big topic in itself, but I have implemented such a beast a few years back in C#, also using KepServerEx.
Without seeing your code it's a bit difficult for me to understand what you have done so far, but the general idea is that you want to handle the OPCGroup.DataChange event. From there you have to "dispatch" the changed value to the proper TextBox.
Of course, you have to setup your OPCServer, your OPCGroup(s) and so on.
I created a library for this, and it was some extensive work required, so I'm afraid it can't really be answered in one Q&A like here.
If you have a very specific question, please open another one and I'll try to answer more specifically.
Cheers

Categories