I use a timer to get bandwidth per second and place that information on a label The output is a large value like 419000KB/S and next tick it may be 0KB/S. Is it a problem related to thread or something? I guess it was bytes can not update properly, but I have no idea to fix it.
public partial class MainWindow : Window
{
static long bytes = 0;
static NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
static Label uploadLabel;
public MainWindow()
{
InitializeComponent();
uploadLabel = uploadBandwidth;
IPv4InterfaceStatistics statistics = adapters[0].GetIPv4Statistics();
bytes = statistics.BytesSent;
Timer myTimer = new Timer();
myTimer.Elapsed += new ElapsedEventHandler(TimeUp);
myTimer.Interval = 1000;
myTimer.Start();
}
public void TimeUp(object source, ElapsedEventArgs e)
{
IPv4InterfaceStatistics statistics = adapters[0].GetIPv4Statistics();
bytes = statistics.BytesSent - bytes;
Dispatcher.Invoke(DispatcherPriority.Normal, new Action<Label>(SetValue), uploadLabel);
}
private void SetValue(Label upload)
{
upload.Content = ((int)bytes / 1024).ToString() + "KB/s";
}
}
Update:
The problem is I change the value bytes to statistics.BytesSent - bytes which is wrong.
Here is the function I modified:
public void TimeUp(object source, ElapsedEventArgs e)
{
IPv4InterfaceStatistics statistics = NetworkInterface.GetAllNetworkInterfaces()[0].GetIPv4Statistics();
long bytesPerSec = statistics.BytesReceived - bytes;
bytes = statistics.BytesReceived;
String speed = (bytesPerSec / 1024).ToString() + "KB/S";
Dispatcher.Invoke(DispatcherPriority.Normal, new Action<Label, String>(SetValue), uploadLabel, speed);
}
private void SetValue(Label upload, String speed)
{
upload.Content = speed;
}
There's a problem with your logic.
At the beginning, you store the data sent so far in bytes:
uploadLabel = uploadBandwidth;
IPv4InterfaceStatistics statistics = adapters[0].GetIPv4Statistics();
bytes = statistics.BytesSent; // initialize bytes to amount already sent
And then on each event, you reset the value to contain BytesSent - bytes:
IPv4InterfaceStatistics statistics = adapters[0].GetIPv4Statistics();
bytes = statistics.BytesSent - bytes;
So assuming that you start with 15k sent and send 1kB every second, the variables will be as follows:
|| seconds elapsed | BytesSent | bytes ||
||=================|===========|=======||
|| 0 | 15000 | 15000 ||
|| 1 | 16000 | 1000 ||
|| 2 | 17000 | 16000 ||
|| 3 | 18000 | 2000 ||
So as you can see, the bytes value is alternating and not showing any legitimate value in any of the cases except for the first one.
In order to fix your problem, you'll either need to introduce a second state variable or pass the bytes value to the SetValue method in a correct manner similar to answer by #Sign:
public void TimeUp(object source, ElapsedEventArgs e)
{
IPv4InterfaceStatistics statistics = adapters[0].GetIPv4Statistics();
var sent = statistics.BytesSent - bytes;
Dispatcher.Invoke(DispatcherPriority.Normal, new Action<Label>(SetValue), uploadLabel, sent);
bytes = statistics.BytesSent;
}
Related
In C I simply do a memcpy from my data buffer array to the address of my struct.
I am not sure how to do this in C# for the desktop side of things. This is my struct in C#
struct frame_type
{
public UInt32 start_of_frame;
public UInt32 frame_id;
public UInt16 frame_len;
public UInt32 crc;
public UInt32 end_of_frame;
}
And I have a Datareceived serial port callback, the dataIn variable below is a string but obviously I can change it something else to make it easier to grab all those bytes and assemble the frame.
private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
dataIN = port.ReadExisting();
//increment variable and when i have 34 bytes assemble a frame
//and checkl if it is an ack frame.
bytes_received_count++;
if(bytes_received_count == 34)
{
//assemble a frame_type frame
}
this.Invoke(new EventHandler(sendFirmware));
}
So any suggestions are welcome.
UPDATE:
I ended up with this code after some research:
private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
for (int i = 0; i < 34; i++)
{
bytes_received[i] = (byte)port.ReadByte();
}
assemble_frame_from_port_bytes();
// this.Invoke(new EventHandler(sendFirmware));
}
public void assemble_frame_from_port_bytes()
{
frame.start_of_frame = (UInt32)(bytes_received[3] << 24 | bytes_received[2] << 16 | bytes_received[1] << 8 | bytes_received[0] << 0);
frame.frame_id = (UInt32)(bytes_received[7] << 24 | bytes_received[6] << 16 | bytes_received[5] << 8 | bytes_received[4] << 0);
frame.frame_len = (UInt16)(bytes_received[9] << 8 | bytes_received[8] << 0);
int idx = 10;
for (int i = 0; i < 16; i++)
{
payload[i] = bytes_received[idx++];
}
frame.crc = (UInt32)(bytes_received[29] << 24 | bytes_received[28] << 16 | bytes_received[27] << 8 | bytes_received[26] << 0);
frame.end_of_frame = (UInt32)(bytes_received[33] << 24 | bytes_received[32] << 16 | bytes_received[31] << 8 | bytes_received[30] << 0);
}
It gets the job done, is it great? I dont know but it serves its purpose at this stage. C# surely is a great powerful tool but in the hands of a fool it is crippled haha.
In C I simply do a memcpy from my data buffer array to the address of my struct.
I suppose the following is something similar, but I'm not in a position to test it:
[StructLayout(LayoutKind.Sequential)]
struct frame_type
{
public UInt32 start_of_frame;
public UInt32 frame_id;
public UInt16 frame_len;
public UInt32 crc;
public UInt32 end_of_frame;
public static implicit operator frame_type(byte[] data)
{
unsafe
{
fixed (byte* b = &data[0])
{
return *(frame_type*)b;
}
}
}
}
It should allow you to just straight assign a byte array of length 18 to the struct
frame_type f = aByteArray18Long;
Of course, it is the root of all evil and a safe approach would perhaps look like:
static public implicit operator frame_type(byte[] b)
{
var f = new frame_type();
f.start_of_frame = (uint)(b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3]);
f.frame_id = (uint)(b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7]);
f.frame_len = (ushort)(b[8]<<8 | b[9]);
f.crc = (uint)(b[10]<<24 | b[11]<<16 | b[12]<<8 | b[13]);
f.end_of_frame = (uint)(b[14]<<24 | b[15]<<16 | b[16]<<8 | b[17]);
return f;
}
ps; it's perhaps easiest to get your bytes by something like:
var buf = new byte[18];
for(int x = 0; x<18; x++)
buf[x] = port.Read();
ok big caveat, I have no serial port so cannot test
MemoryStream buffer = new MemoryStream();
private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) {
for (int i = 0; i < port.BytesToRead; i++) {
if (buffer.Length == 34)
break;
// write needs an array even though its only 1
byte[] bytes = new bytes[1];
bytes[0] = port.ReadByte();
buffer.Write(bytes, 0, 1);
}
if (buffer.Length == 34){
// ok we now have the next 34 bytes in buffer
var frame = new frame_type();
// rewind to the beginning
buffer.Seek(0, SeekOrigin.Begin);
using (var br = new BinaryReader(buffer)) {
frame.start_of_frame = br.ReadUInt32();
frame.frame_id = br.ReadUint32();
.......
}
// rewind to be ready for next block
buffer.Seek(0, SeekOrigin.Begin);
}
}
the core is using BinaryReader this reads serialized elements from a byte stream, ReadUInt32 pulls the next 4 bytes and marshalls to a UIn32 etc.
The fiddly bit is getting the bytes from thr port into a stream since we cant connect a stream directly to the port (I coulsnt see how to do it) so I use a MemoryStream which, as the name suggests , is a byte stream in memory
So my Arduino is taking almost 200ms processing a total of 128 bytes. The whole process without writing over the serial port is only taking 25ms.
Why is my Arduino bottlenecking so much?
Arduino
setColor is simply setting the color of the ledstrip using the FastLED library.
void loop() {
if(Serial.available() == 4){
int led = Serial.read();
int r = Serial.read();
int g = Serial.read();
int b = Serial.read();
setColor(led, r, g, b);
Serial.write(1);
if(Serial.available() > 0) Serial.read();
}
}
C#
In a loop I am doing the following to write the data:
attempt:
if (Port.isReady) {
strip.Send(new byte[] { id, c.R, c.G, c.B });
Port.isReady = false;
} else {
goto attempt;
}
public void Send(byte[] bytes) {
port.Write(bytes, 0, bytes.Length);
}
And I read the Arduino response using:
private const int DONE = 1;
public void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e) {
Console.WriteLine("- Serial port data received -");
Console.WriteLine("Nr. of bytes: {0}", port.BytesToRead);
if (port.ReadByte() == DONE) {
isReady = true;
}
port.DiscardInBuffer();
}
Well it all depends on your baudrate. If your baudrate are 9600 you can receive 9600 bit per second, thats 1200 bytes.
So 128/1200 = 0.1066 = 107 ms spend on receiving 128 bytes.
Higher baudrates will give shorter readtime.
Well why is it then taking 200ms you then ask?
My guess is that it is because of the many calls to setColor()
You are calling that once for every 4 bytes so that is 32 times.
I don't know the execution time on that function, but if it's something like 2-3ms you'r hitting that 200ms fast.
Data packets are sent from TcpListener to TcpClient via NetworkStream. Packets aren't big(5 Bytes) but come with great frequency (about 1000 per second or more). Can you give me advice how should I process it most effective? Now I use async for getting stream, which fill buffer, then I cut it to the packets. After that the process is repeated. But
at some point I lose true sequence.
s is NetworkStream.
Packet has 2 fields: type(1 Byte (byte)) and value(4 Bytes (int))
MAXVALUEPACKET = 4096
Client Code:
async Task process()
{
bool flag = false;
while (true)
{
byte[] actionBuffer;
flag = false;
actionBuffer = await ReadFromStreamAsync();
while (!flag)
{
byte type = actionBuffer[0];
int value = 0;
if (type > 0)
{
byte[] valueBytes = { actionBuffer[4], actionBuffer[3], actionBuffer[2], actionBuffer[1] };
value = BitConverter.ToInt32(valueBytes, 0);
actionBuffer = actionBuffer.Skip(5).ToArray();
CommonVariables.RawMessages.Add(new KeyValuePair<byte, int>(type, value));
OnHandler();
}
else
flag = true;
}
}
}
byte[] buf = new byte[MAXVALUEPACKET];
async Task<byte[]> ReadFromStreamAsync()
{
await s.ReadAsync(buf, 0, MAXVALUEPACKET);
return buf;
}
Setting MAXVALUEPACKET = 5 to read exactly every 5 bytes may help avoid loss of bytes:
const int MAXVALUEPACKET = 5;
async Task process()
{
while (true)
{
var actionBuffer = await ReadFromStreamAsync();
byte type = actionBuffer[0];
int value = 0;
if (type > 0)
{
byte[] valueBytes = { actionBuffer[4], actionBuffer[3], actionBuffer[2], actionBuffer[1] };
value = BitConverter.ToInt32(valueBytes, 0);
CommonVariables.RawMessages.Add(new KeyValuePair<byte, int>(type, value));
OnHandler();
}
}
}
async Task<byte[]> ReadFromStreamAsync()
{
await s.ReadAsync(buf, 0, MAXVALUEPACKET);
return buf;
}
The problem of original code logic is when iteration reaches the 820th loop, there is 1 byte left and it makes the logic to read integer value fail. I'm assuming the server always writes exactly 5 bytes in every portions.
Just to explain, I have a dev board that is, on command, shooting out 4 chars (Bytes). The terminal program (RealTerm) i'm using to debug this sees all 4 bytes. I've now moved on to writing the desktop software, and my program is only paying attention to 1 out of 4 bytes sent. TO clarify, i don't know which 1 of 4 bytes (first , last, middle two) but i can find out if its really necessary.
At first I thought the SerialPort.DataReceived event would fire for each byte that was received. This isn't true, I don't know what causes it to fire but its not the receiving of a singular Byte.
So I tried looping over SerialPort.BytesToRead, but this also only gets the first byte, even though it recognizes there are 3 bytes to read (why not 4??)
Its not essential for me to receive this data at the exact time it hits the port, but obviously I dot want to be loosing 3/4 of my data. However it wont always be 4 bytes, that's just what its doing now. I just want to get all bytes that are ready to be read.
Event Handler:
private void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
while (comPort.BytesToRead > 0)
{
RxString = comPort.ReadExisting();
RxByte = comPort.ReadByte();
byte[] myByte = new byte[6];
for (int i = 0; i < 6; i++)
{
myByte[i] = 0000000;
}
comPort.Read(myByte, 0, comPort.BytesToRead);
for (int i=0;i<6;i++)
{
if (myByte[i] != null)
{
thisBytes.Add(myByte[i]);
}
}
RxString = RxByte + "";
try
{
this.Invoke(new EventHandler(dealWithByte));
}
catch
{
}
}
}
private void dealWithByte(object sender, EventArgs e)
{
foreach (byte item in thisBytes)
{
RxByte = Convert.ToInt16(item);
string binary = Convert.ToString(RxByte, 2).PadLeft(8, '0');
//processTime(binary);
}
}
I am not a C# person but the code is pretty simple, pseudo code
numBytes As Int = SerialPort1.BytesToRead 'get # of bytes available
buf(numBytes - 1) As Byte 'allocate a buffer
br As Int = SerialPort1.Read(buf, 0, numBytes) 'read the bytes
If br <> numBytes {
Resize(buf, br) 'resize the buffer
}
at this point store the bytes into a list. This list can then be processed for messages.
I'm trying to handle my incoming buffer and ensure that I got all the 125 bytes of the data at each transmission. I've created a byte array. How can I know 125 bytes of data is being received. I tried displaying the number of bytes but it displayed different number and I'm unsure if it's the right coding to get the number of bytes received.
Here's my code:
void datareceived(object sender, SerialDataReceivedEventArgs e)
{
myDelegate d = new myDelegate(update);
listBox1.Invoke(d, new object[] { });
}
public void update()
{
Console.WriteLine("Number of bytes:" + serialPort.BytesToRead); // it shows 155
while (serialPort.BytesToRead > 0)
bBuffer.Add((byte)serialPort.ReadByte());
ProcessBuffer(bBuffer);
}
private void ProcessBuffer(List<byte> bBuffer)
{
// Create a byte array buffer to hold the incoming data
byte[] buffer = bBuffer.ToArray();
// Show the user the incoming data // Display mode
for (int i = 0; i < buffer.Length; i++)
{
listBox1.Items.Add("SP: " + (bBuffer[43].ToString()) + " " + " HR: " + (bBuffer[103].ToString()) + " Time: ");
}
}
At the moment you are reading until the local receive buffer (BytesToRead) is empty, however, a better approach is to keep a buffer and offset, and loop until you have what you need, even if that means waiting - i.e.
byte[] buffer = new byte[125]
int offset = 0, toRead = 125;
...
int read;
while(toRead > 0 && (read = serialPort.Read(buffer, offset, toRead)) > 0) {
offset += read;
toRead -= read;
}
if(toRead > 0) throw new EndOfStreamException();
// you now have all the data you requested