I'm writing a C# application that will receive serial data from 3 different COM ports configure with 8-bit UART with no parity. The other devices will be sending and receiving binary encoded HEX ex. AF01h = 10101010 00000001 two characters for each byte. I have set up virtual COM ports and a simple application for testing purposes and am sending data back and forth before I hook the devices up. I found that data is ASCII encoded by default on transmission and reception but I need both to be binary encoded HEX. I do not see that option in the encoding class and would rather not have the application using a complete different encoding than the 3 other devices. Right now I am using this code to convert the string when it is sent
string binarystring = String.Join(String.Empty, hexstring.Select(c => Convert.ToString(Convert.ToInt32(c.ToString(), 16), 2).PadLeft(4, '0')));
sport.Write(binarystring);
txtReceive.AppendText("[" + dtn + "] " + "Sent: " + binarystring + "\n");
This works for testing transmission for now but i will eventually change the code to place the two digit hex number directly into a byte array.
This code will allow me to enter AF01h = 1010101000000001, but on the receiving end of the application I get 16 bytes of ASCII encoded characters. Is there a way I can get the app on the same page as the other devices?
Figured out a way to do it. Just needed to convert the long string of hex to two hex character byte integers
string hex = txtDatatoSend.Text; //"F1AAAF1234BA01"
int numOfBytes = HEX.Length;
byte[] outbuffer = new byte[numOfBytes / 2];
for (int i = 0; i < numOfBytes; i += 2)
{
outbuffer[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
sport.Write(outbuffer, 0, outbuffer.Length);
sport.DiscardOutBuffer()
The only caveat is you have to enter in the an even number of characters
On the other end the data gets placed right back in the Byte[] and i can decode it like this.
byte[] inbuffer = new byte[sport.BytesToRead];
sport.Read(inbuffer, 0, inbuffer.Length);
txtReceive.AppendText("[" + dtn + "] " + "Received: " + inbuffer.Length + " bytes ");
for (int i = 0; i < inbuffer.Length; i++)
{
string hexValue = inbuffer[i].ToString("X2");
txtReceive.AppendText(inbuffer[i] + " is " + hexValue + "HEX ");
}
txtReceive.AppendText("\n");
sport.DiscardInBuffer();
Related
I have a device emulator which accept the data as text from socket.Below code works fine until I send from 0x00 to 0x7F means upto Ascii limit (0 to 127).
Issue arise when I try to send beyond the Ascii limit like 0x80,0x81. It send to emulator 0x3F('?') and it change the whole meaning of command. because it does not able to understand this.
So What may be the possible solution to send the data beyond Ascii limit
Send data code:
//string data = textBox1.Text;
string d1 = ConvertHex("35"); //getting exact byte in socket
byte[] buffer = Encoding.ASCII.GetBytes(d1);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
ConverHex function:
public static string ConvertHex(String hexString)
{
try
{
string ascii = string.Empty;
for (int i = 0; i < hexString.Length; i += 2)
{
String hs = string.Empty;
hs = hexString.Substring(i, 2);
uint decval = System.Convert.ToUInt32(hs, 16);
char character = System.Convert.ToChar(decval);
ascii += character;
}
return ascii;
}
catch (Exception ex) { Console.WriteLine(ex.Message); }
return string.Empty;
}
but when I send more than 79 then I get 3F in emulator.
7F is in fact the upper bound. Because that's 127 in decimal, the highest code point supported by the ASCII encoding. Code points higher than that get decoded to a question mark, having the code point of 63 or 3F in hexadecimal.
That's because you're using text to transmit binary data. Don't do that. See How can I convert a hex string to a byte array? for a proper implementation of "hex string to byte array".
I'm receiving data using serial port, and I'm use the following code to convert the string to hex representation and show it in the richtextbox5:
string hex = "";
foreach (char c in RXstring)
{
uint tmp = c;
hex += String.Format("{0:X2}", (uint)System.Convert.ToInt16(tmp.ToString())) ;
}
richTextBox5.AppendText(hex + " <= Hex");
where RXstring is where I store data from serial port.
The problem is :
when I send data like 127(decimal)=> 01111111(binary)=> 7F(hex) it converted correctly, while when I send data like 191 or 167 which all share that the most significant bit is 1 and they are all 8 bits the output is 3F despite the other bits, (the representation of any 8 bits start with 1 is 3F), whats wrong with my code?
can you help, thx.
This is an example of using bytes - and it seems to work as you want:
string hex = "";
byte[] RXstring = { 0xFF, 0xCF, 0xB8, 167,191 };
foreach (byte c in RXstring)
{
uint tmp = c;
hex += String.Format("{0:X2}", (uint)System.Convert.ToInt16(tmp.ToString()));
}
System.Console.WriteLine("{0} <= Hex", hex);
I just add serialPort1.Encoding = Encoding.Default; to my serial port and worked perfectly
I need help with a checksum calculation.
This is (not my code!) but from specification
http://www.leupamed.at/?wpdmact=process&did=NC5ob3RsaW5r
private void CalcCheckSum(string msg, out byte checksum1, out byte checksum2)
{
byte cs1 = 0;
byte cs2 = 0;
// Always use "\n" as line break when calculating the checksum.
msg = msg.Replace("\r\n", "\n"); // Find and replace CR LF with LF
msg = msg.Replace("\r", "\n"); // Find and replace CR with LF.
for (int i = 0; i < msg.Length; i++)
{
cs1 += (byte) msg[i];
cs2 += cs1;
}
checksum1 = cs1;
checksum2 = cs2;
}
I must create a packet like this:
<!--:Begin:Chksum:1:--><!--:Ack:Msg:3:0:--><!--:End:Chksum:1:184:62:-->
The string <!--:Ack:Msg:3:0:--> is the actual data, I must calculate two checksum bytes (184 and 62) and insert these into the final packet (as seen above).
But my result from the calculation is 10 and 62
var msg = "<!--:Ack:Msg:3:0:-->";
byte checksum1 = 0;
byte checksum2 = 0;
CalcCheckSum(msg, out checksum1, out checksum2);
I don't now how to calculate correct checksum values.
This is checksum for response. Not for validating request.
I can't upload image due to low reputation, so look at last line in specification: https://drive.google.com/file/d/0B_Gs9q9SJteadVRwSVc1a2FmUTg/edit?usp=sharing
This acknowledge message is independent on request. Only it must be response to request message ID 3.
Solution?
After calculating checksum:
checksum1 = 256 - (10 + 62) = 184
checksum2 = 62
Device communicating without problem, now.
After calculating checksum:
checksum1 = 256 - (10 + 62) = 184
checksum2 = 62
Probably this question is too specific and no one has experience with this type of checksum calculation.
Device communicating without problem, now.
recently I have discovered C#, which is really what I want. Before C# I was coding with AS3. I've recoded all my old program using C# but I am blocked with this :
public function Envoie_Serveur(param1:String) : void
{
var _loc_2:* = String(this.CMDTEC % 9000 + 1000).split("");
this.Serveur.send(this.MDT[_loc_2[0]] + this.MDT[_loc_2[1]] + this.MDT[_loc_2[2]] + this.MDT[_loc_2[3]] + param1);
var _loc_3:* = this;
var _loc_4:* = this.CMDTEC + 1;
_loc_3.CMDTEC = _loc_4;
return;
}
CMDTEC and MDT are 2 byteArray (byte[] in C# I guess)
That is what I have tried but which is not working ;c
byte[] _loc_1 = Encode((Int64.Parse(this.CMDTEC[0].ToString("X", System.Globalization.NumberStyles.HexNumber)) % 9000 + 1000) + "");
var fingerprint = new byte[4];
fingerprint[0] = byte.Parse(this.MDT[_loc_1[0]].ToString("X"), System.Globalization.NumberStyles.HexNumber);
fingerprint[1] = byte.Parse(this.MDT[_loc_1[1]].ToString("X"), System.Globalization.NumberStyles.HexNumber);
fingerprint[2] = byte.Parse(this.MDT[_loc_1[2]].ToString("X"), System.Globalization.NumberStyles.HexNumber);
fingerprint[3] = byte.Parse(this.MDT[_loc_1[3]].ToString("X"), System.Globalization.NumberStyles.HexNumber);
this.CMDTEC++;
And for exemple, that is what CMDTEC and MDT contains :
this.MDT = "1400175151406"; (just for exemple, I get this by socket)
this.CMDTEC = "8306"; (idem as ^)
How can I convert properly that to C# please ? Thanks in advance for answers.
Here's an attempt; but you need to add more details to your question regarding inputs and outputs, datatypes etc. Although you are dealing with strings, it appears you are mainly handling numeric values.
The code below is verbose for clarity, it can be condensed a lot more. Please note I haven't actually compiled and tried the code (because I don't have a Serveur object, it won't compile for me).
byte[] MDT = System.Text.Encoding.ASCII.GetBytes ("1400175151406");
byte[] CMDTEC = System.Text.Encoding.ASCII.GetBytes ("8306");
void Envoie_Serveur(string param1)
{
// firstly, get CMDTEC as a string, assuming ascii encoded bytes
string sCMDTEC = System.Text.Encoding.ASCII.GetString(CMDTEC);
// now convert CMDTEC string to an int
int iCMDTEC = int.Parse(sCMDTEC);
// now do modulation etc on the int value
iCMDTEC = iCMDTEC % 9000 + 1000;
// now convert modulated int back into a string
sCMDTEC = iCMDTEC.ToString();
// now convert modulated string back to byte array, assuming ascii encoded bytes
byte[] bCMDTEC = System.Text.Encoding.ASCII.GetBytes(sCMDTEC);
// send the data
this.Serveur.send(((int)this.MDT[bCMDTEC[0]]) + ((int)this.MDT[bCMDTEC[1]]) + ((int)this.MDT[bCMDTEC[2]]) + ((int)this.MDT[bCMDTEC[3]]) + int.Parse(param1));
// convert CMDTEC bytes to string again
sCMDTEC = System.Text.Encoding.ASCII.GetString(CMDTEC);
// convert CMDTEC string to int again
iCMDTEC = int.Parse(sCMDTEC);
// increament CMDTEC
iCMDTEC += 1;
// convert back to string
sCMDTEC = iCMDTEC.ToString();
// convert back to bytes
this.CMDTEC = System.Text.Encoding.ASCII.GetBytes(sCMDTEC);
}
So, I'm attempting to communicate with a device over a serialport object in C#. The device is looking for a mask value to be sent to it as a part of a command string. For example, one of the strings will be something like "SETMASK:{}", where {} is the unsigned 8-bit mask.
When I use a terminal (such as BRAY) to communicate with the device, I can get the device to work. For example, in BRAY terminal, the string SETMASK:$FF will set the mask to 0xFF. However, I can't for the life of me figure out how to do this in C#.
I've already tried the following function, where Data is the mask value and CMD is the surrounding string ("SETMASK:" in this case"). Where am I going wrong?
public static string EmbedDataInString(string Cmd, byte Data)
{
byte[] ConvertedToByteArray = new byte[(Cmd.Length * sizeof(char)) + 2];
System.Buffer.BlockCopy(Cmd.ToCharArray(), 0, ConvertedToByteArray, 0, ConvertedToByteArray.Length - 2);
ConvertedToByteArray[ConvertedToByteArray.Length - 2] = Data;
/*Add on null terminator*/
ConvertedToByteArray[ConvertedToByteArray.Length - 1] = (byte)0x00;
Cmd = System.Text.Encoding.Unicode.GetString(ConvertedToByteArray);
return Cmd;
}
Can't be certain, but I'll bet your device is expecting 1-byte chars, but the C# char is 2 bytes. Try converting your string into a byte array with Encoding.ASCII.GetBytes(). You'll probably also need to return the byte[] array instead of a string, since you'll end up converting it back to 2 byte chars.
using System.Text;
// ...
public static byte[] EmbedDataInString(string Cmd, byte Data)
{
byte[] ConvertedToByteArray = new byte[Cmd.Length + 2];
System.Buffer.BlockCopy(Encoding.ASCII.GetBytes(Cmd), 0, ConvertedToByteArray, 0, ConvertedToByteArray.Length - 2);
ConvertedToByteArray[ConvertedToByteArray.Length - 2] = Data;
/*Add on null terminator*/
ConvertedToByteArray[ConvertedToByteArray.Length - 1] = (byte)0x00;
return ConvertedToByteArray;
}
If your device accepts some other character encoding, swap out ASCII for the appropriate one.
Problem solved, the System.Buffer.BlockCopy() command was embedding zeroes after each character in the string. This works:
public static byte[] EmbedDataInString(string Cmd, byte Data)
{
byte[] ConvertedToByteArray = new byte[(Cmd.Length * sizeof(byte)) + 3];
char[] Buffer = Cmd.ToCharArray();
for (int i = 0; i < Buffer.Length; i++)
{
ConvertedToByteArray[i] = (byte)Buffer[i];
}
ConvertedToByteArray[ConvertedToByteArray.Length - 3] = Data;
ConvertedToByteArray[ConvertedToByteArray.Length - 2] = (byte)0x0A;
/*Add on null terminator*/
ConvertedToByteArray[ConvertedToByteArray.Length - 1] = (byte)0x00;
return ConvertedToByteArray;
}