Com port max speed - c#

I have a hardware that send data to the com port in the form: "HxxxxVxxxx" where x = number: eg: (H1234V5678).
I want to ask, what should I set the sample rate to send it as soon as possible. (baud 9600, 8bits, parity: none, stop bit: 1).
The program written in Java or C# was able to recive these data on the whole, not in parts.
When sending data every 22ms, and receive such data:
2014-08-11 18:48:39.669 56 36 36 37
2014-08-11 18:48:39.674 48 30 0D 0A
2014-08-11 18:48:39.687 56 36
2014-08-11 18:48:39.692 36 39 48 30
2014-08-11 18:48:39.696 0D 0A
2014-08-11 18:48:39.712 56 36 36 38
2014-08-11 18:48:39.716 48 30 0D 0A
2014-08-11 18:48:39.732 56 36
2014-08-11 18:48:39.737 36 37 48 30
2014-08-11 18:48:39.742 0D 0A
2014-08-11 18:48:39.753 56
but i wana somethink like:
2014-08-11 18:48:39.600 56 36 36 37 48 30 0D 0A
2014-08-11 18:48:39.622 56 36 36 37 48 30 0D 0A
2014-08-11 18:48:39.644 56 36 36 37 48 30 0D 0A
2014-08-11 18:48:39.666 56 36 36 37 48 30 0D 0A
2014-08-11 18:48:39.688 56 36 36 37 48 30 0D 0A
c# code:
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff");
int bytes = comport.BytesToRead;
byte[] buffer = new byte[bytes];
comport.Read(buffer, 0, bytes);
File.AppendAllText(#"c:\file.txt", timestamp + " "+ByteArrayToHexString(buffer) +"\n" + Environment.NewLine);
}

It looks like the data you're receiving is in a slightly different format than: "HxxxxVxxxx"
The way I read your logs, you're receiving "V66H0\r\n".
(\r = carriage return, \n = line feed)
If you can guarantee that all of your individual commands will end in a \r\n (0x0D,0x0A), then you have 2 options:
Create a buffer and keep adding to it until you hit a 0x0D 0x0A, then you can process that as a line.
Instead of using the asynchronous SerialPort.DataRecieved event, you could change your code around to using the synchronous SerialPort.ReadLine() method, which will read an entire line at a time.
This is obviously simplified, but it should work something like this:
public bool KeepRunning = true;
while(KeepRunning)
{
string command = serialport.ReadLine();
processCommand(command);
}
Where serialport is an already opened SerialPort object, and processCommand is some method that will handle an entire line.

Changing the baud rate will not give you the desired result you are looking for
. The SerialPort class (nor any class based on Stream which is what the class tries to emulate) guarantees the exact amount of data received will be the amount you requested. If you want 8 byte chunks you need to buffer the incoming data and every time you get 8 bytes worth of data you return the result.
You will need to put a layer to do your buffering between your reading of the serial port and your File.AppendAllText so you build up until you have 8 bytes of data then you write out to the file.
private byte[] buffer = new byte[8];
private int bufferOffset = 0;
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int totalBytesToRead = comport.BytesToRead;
int totalBytesRead = 0;
while (totalBytesToRead > totalBytesRead)
{
//Chooses the remaining size in the buffer or the remaining bytes available to read, whichever is smaller.
var bytesToRead = Math.Min(buffer.Length - bufferOffset, totalBytesToRead - totalBytesRead);
var bytesRead = comport.Read(buffer, bufferOffset, bytesToRead);
bufferOffset += bytesRead;
totalBytesRead += bytesRead;
//If we have filled our buffer write it out to the file.
if (bufferOffset == buffer.Length)
{
string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff");
File.AppendAllText(#"c:\file.txt", timestamp + " " + ByteArrayToHexString(buffer) + "\n" + Environment.NewLine);
bufferOffset = 0;
}
}
}

Related

How to Encrypt and upload data using selling-partner-api in Amzon using .net

I want to use selling-partner-api-docs for .Net . I found one reference from below url but that is use Java example coding : https://github.com/amzn/selling-partner-api-docs/blob/main/guides/use-case-guides/feeds-api-use-case-guide-2020-09-04.md#step-2-encrypt-and-upload-the-feed-data
But i want to use .Net coding can any one suggest of .Net coding of below java coding part
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.nio.charset.StandardCharsets;
import com.amazon.spapi.documents.UploadHelper;
import com.amazon.spapi.documents.UploadSpecification;
import com.amazon.spapi.documents.exception.CryptoException;
import com.amazon.spapi.documents.exception.HttpResponseException;
import com.amazon.spapi.documents.impl.AESCryptoStreamFactory;
/* We want to maintain encryption at rest, so do not write unencrypted data to disk. This is bad:
InputStream source = new FileInputStream(new File("/path/to/myFeed.xml"));
Instead, if your data can fit in memory, you can create an InputStream from a String (see encryptAndUpload_fromString()).
Otherwise, you can pipe data into an InputStream using Piped streams (see encryptAndUpload_fromPipedInputStream()).
*/
public class UploadExample {
private final UploadHelper uploadHelper = new UploadHelper.Builder().build();
// key, initializationVector, and url are returned by the createFeedDocument operation.
public void encryptAndUpload_fromString(String key, String initializationVector, String url) {
AESCryptoStreamFactory aesCryptoStreamFactory =
new AESCryptoStreamFactory.Builder(key, initializationVector)
.build();
// This contentType must be the same value that was provided to createFeedDocument.
String contentType = String.format("text/plain; charset=%s", StandardCharsets.UTF_8);
// The character set must be the same one that is specified in contentType.
try
(InputStream source = new ByteArrayInputStream("my feed data".getBytes(StandardCharsets.UTF_8))) {
UploadSpecification uploadSpec =
new UploadSpecification.Builder(contentType, aesCryptoStreamFactory, source, url)
.build();
uploadHelper.upload(uploadSpec);
}
catch (CryptoException | HttpResponseException | IOException e) {
// Handle exception.
}
}
// key, initializationVector, and url are returned from createFeedDocument.
public void encryptAndUpload_fromPipedInputStream(String key, String initializationVector, String url) {
AESCryptoStreamFactory aesCryptoStreamFactory =
new AESCryptoStreamFactory.Builder(key, initializationVector)
.build();
// This contentType must be the same value that was provided to createFeedDocument.
String contentType = String.format("text/plain; charset=%s", StandardCharsets.UTF_8);
try
(PipedInputStream source = new PipedInputStream()) {
new Thread(
new Runnable() {
public void run() {
try
(PipedOutputStream feedContents = new PipedOutputStream(source)) {
// The character set must be the same one that is specified in contentType.
feedContents.write("my feed data\n".getBytes(StandardCharsets.UTF_8));
feedContents.write("more feed data".getBytes(StandardCharsets.UTF_8));
}
catch (IOException e) {
// Handle exception.
}
}
}).start();
UploadSpecification uploadSpec =
new UploadSpecification.Builder(contentType, aesCryptoStreamFactory, source, url)
.build();
uploadHelper.upload(uploadSpec);
}
catch (CryptoException | HttpResponseException | IOException e) {
}
}
}
Edit -----------------------------------------------------
This is what I have tried and this is what I have got.
STEP 1
REQUEST URL: https://sellingpartnerapi-na.amazon.com/feeds/2020-09-04/documents
REQUEST BODY:{"contentType":"text/plain;charset=utf-8"}
Request Headers = {Host: sellingpartnerapi-na.amazon.com
x-amz-date: 20210203T120516Z
Authorization: AWS4-HMAC-SHA256 Credential=XXXXXXXX/20210203/us-east-1/execute-api/aws4_request, SignedHeaders=host;x-amz-date, Signature=XXXX
The Credential and Signature are created on the partner portal.
RESPONSE STEP 1
{"payload":
{"encryptionDetails":{"standard":"AES","initializationVector":"TTAVo5bUDNfuk7KPzgm+ow==",
"key":"GrpKm3UIvxiM5xUTlzaCC9xJFORMX41chAKUk0G6Cbg="},
"feedDocumentId":"amzn1.tortuga.3.9968967c-048c-4e8b-a6c1-ffd764f005d4.T508PJ0OCPKJ3",
"url":"https://tortuga-prod-na.s3-external-1.amazonaws.com/%2FNinetyDays/amzn1.tortuga.3.9968967c-048c-4e8b-a6c1-ffd764f005d4.T508PJ0OCPKJ3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20210203T114111Z&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Expires=300&X-Amz-Credential=AKIA5U6MO6RANYPNEUPL%2F20210203%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=1fd8b69523c06d76664c22c4093be5e8adc187436f7119aa9d4b51302cc8ae84"}}
STEP 2:
In step 2 I am using the URL coming from the first Step Response but it is not getting me result.
REQUEST URL:
https://tortuga-prod-na.s3-external-1.amazonaws.com/%2FNinetyDays/amzn1.tortuga.3.9968967c-048c-4e8b-a6c1-ffd764f005d4.T508PJ0OCPKJ3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20210203T114111Z&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Expires=300&X-Amz-Credential=AKIA5U6MO6RANYPNEUPL%2F20210203%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=1fd8b69523c06d76664c22c4093be5e8adc187436f7119aa9d4b51302cc8ae84
See the Signature and the Credential here are coming different than one we have got from the response of Step 1
RESPONSE FROM STEP 2
<?xml version="1.0" encoding="UTF-8"?>
-<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
<AWSAccessKeyId>AKIA5U6MO6RANYPNEUPL</AWSAccessKeyId>
<StringToSign>AWS4-HMAC-SHA256 20210203T114111Z 20210203/us-east-1/s3/aws4_request 057d93b83f8254c64b8ffccdfb885b79e5d96c0d2045c27732fc42ae722e335e</StringToSign>
<SignatureProvided>1fd8b69523c06d76664c22c4093be5e8adc187436f7119aa9d4b51302cc8ae84</SignatureProvided>
<StringToSignBytes>41 57 53 34 2d 48 4d 41 43 2d 53 48 41 32 35 36 0a 32 30 32 31 30 32 30 33 54 31 31 34 31 31 31 5a 0a 32 30 32 31 30 32 30 33 2f 75 73 2d 65 61 73 74 2d 31 2f 73 33 2f 61 77 73 34 5f 72 65 71 75 65 73 74 0a 30 35 37 64 39 33 62 38 33 66 38 32 35 34 63 36 34 62 38 66 66 63 63 64 66 62 38 38 35 62 37 39 65 35 64 39 36 63 30 64 32 30 34 35 63 32 37 37 33 32 66 63 34 32 61 65 37 32 32 65 33 33 35 65</StringToSignBytes>
<CanonicalRequest>PUT //NinetyDays/amzn1.tortuga.3.9968967c-048c-4e8b-a6c1-ffd764f005d4.T508PJ0OCPKJ3 X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIA5U6MO6RANYPNEUPL%2F20210203%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210203T114111Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost content-type:text/plain; charset=utf-8 host:tortuga-prod-na.s3-external-1.amazonaws.com content-type;host UNSIGNED-PAYLOAD</CanonicalRequest>
<CanonicalRequestBytes>50 55 54 0a 2f 2f 4e 69 6e 65 74 79 44 61 79 73 2f 61 6d 7a 6e 31 2e 74 6f 72 74 75 67 61 2e 33 2e 39 39 36 38 39 36 37 63 2d 30 34 38 63 2d 34 65 38 62 2d 61 36 63 31 2d 66 66 64 37 36 34 66 30 30 35 64 34 2e 54 35 30 38 50 4a 30 4f 43 50 4b 4a 33 0a 58 2d 41 6d 7a 2d 41 6c 67 6f 72 69 74 68 6d 3d 41 57 53 34 2d 48 4d 41 43 2d 53 48 41 32 35 36 26 58 2d 41 6d 7a 2d 43 72 65 64 65 6e 74 69 61 6c 3d 41 4b 49 41 35 55 36 4d 4f 36 52 41 4e 59 50 4e 45 55 50 4c 25 32 46 32 30 32 31 30 32 30 33 25 32 46 75 73 2d 65 61 73 74 2d 31 25 32 46 73 33 25 32 46 61 77 73 34 5f 72 65 71 75 65 73 74 26 58 2d 41 6d 7a 2d 44 61 74 65 3d 32 30 32 31 30 32 30 33 54 31 31 34 31 31 31 5a 26 58 2d 41 6d 7a 2d 45 78 70 69 72 65 73 3d 33 30 30 26 58 2d 41 6d 7a 2d 53 69 67 6e 65 64 48 65 61 64 65 72 73 3d 63 6f 6e 74 65 6e 74 2d 74 79 70 65 25 33 42 68 6f 73 74 0a 63 6f 6e 74 65 6e 74 2d 74 79 70 65 3a 74 65 78 74 2f 70 6c 61 69 6e 3b 20 63 68 61 72 73 65 74 3d 75 74 66 2d 38 0a 68 6f 73 74 3a 74 6f 72 74 75 67 61 2d 70 72 6f 64 2d 6e 61 2e 73 33 2d 65 78 74 65 72 6e 61 6c 2d 31 2e 61 6d 61 7a 6f 6e 61 77 73 2e 63 6f 6d 0a 0a 63 6f 6e 74 65 6e 74 2d 74 79 70 65 3b 68 6f 73 74 0a 55 4e 53 49 47 4e 45 44 2d 50 41 59 4c 4f 41 44</CanonicalRequestBytes>
<RequestId>48A2CCE3EFA66E89</RequestId>
<HostId>hiZxZwoTgGG4PBvGLchnKV94AA57zzGqnHh5BbTCIAt1ubD47O+8uQMClkDDBoJBgiXgVb57TRE=</HostId>
</Error>
Hopefully this helps some c sharpers out there for Step #2 https://github.com/amzn/selling-partner-api-docs/blob/main/guides/use-case-guides/feeds-api-use-case-guide-2020-09-04.md#step-2-encrypt-and-upload-the-feed-data
Assuming you have received an OK response for Step #1
The response for Step #1 will look something like this:
{
"payload":
{
"feedDocumentId":"amzn1.tortuga.3.920614b0-fc4c-4393-b0d9-fff175300000.T29XK4YL08B2VM",
"url":"https://tortuga-prod-na.s3.amazonaws.com/%2FNinetyDays/amzn1.tortuga.3.920614b0-fc4c-4393-b0d9-fff175300000.T29XK4YL08B2VM?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20200919T035824Z&X-Amz-SignedHeaders=<headers>&X-Amz-Expires=300&X-Amz-Credential=<credential>&X-Amz-Signature=<signature>",
"encryptionDetails":
{
"standard":"AES",
"initializationVector":"kF3bZt0FSv6JQEimfEJD8g==",
"key":"5EZo/P06OGF0UAy8QuOnMIaQbkAvYBru6EGsFvK8wJ2="
}
}
Convert EncryptionDetails.Key and EncryptionDetails.InitializationVector to bytes and read your flat file (feed) into a string variable...
var key = Convert.FromBase64String(createFeedDocumentResponse.Payload.EncryptionDetails.Key);
var iv = Convert.FromBase64String(createFeedDocumentResponse.Payload.EncryptionDetails.InitializationVector);
string feedData = File.ReadAllText(#"C:\temp\AmazonFlatFileTest.txt");
Encrypt the feed using AES w/ the key and iv variables above...
Here's an encrypt and decrypt function I took from Microsoft and altered slightly (credit to https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.aescryptoserviceprovider?view=net-5.0)...
private byte[] EncryptStringToBytes_Aes(string plainText, byte[] key, byte[] initializationVector)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (key == null || key.Length <= 0)
throw new ArgumentNullException("Key");
if (initializationVector == null || initializationVector.Length <= 0)
throw new ArgumentNullException("initializationVector");
byte[] encrypted;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = key;
aesAlg.IV = initializationVector;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt, Encoding.UTF8))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
And the decrypt function... You will need this in Step #5 decrypt and process the results.
EDIT: It's noticed for larger inputs, Amazon will use GZIP compression with their response (Payload.CompressionAlgorithm). Included 'compressionAlgorithm' parameter to the DecryptStringFromBytes_Aes method.
private string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] initializationVector, string compressionAlgorithm)
{
// Validate Compression Algorithm
var isGzip = string.Equals(compressionAlgorithm, "GZIP", StringComparison.OrdinalIgnoreCase);
var compressionAlgorithmValid = compressionAlgorithm == null || isGzip;
if (!compressionAlgorithmValid)
{
throw new InvalidOperationException($"Unexpected CompressionAlgorithm encounted. compressionAlgorithm = {compressionAlgorithm}");
}
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (initializationVector == null || initializationVector.Length <= 0)
throw new ArgumentNullException("IV");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = initializationVector;
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
if (isGzip)
{
using (var decompressedFileStream = new MemoryStream())
{
using (GZipStream decompressionStream = new GZipStream(csDecrypt, CompressionMode.Decompress))
{
decompressionStream.CopyTo(decompressedFileStream);
decompressedFileStream.Position = 0;
using (var writer = new StreamReader(decompressedFileStream))
{
plaintext = writer.ReadToEnd();
}
}
}
}
else
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt, Encoding.UTF8))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
}
return plaintext;
}
With the returned result from EncryptStringToBytes_Aes, you can now upload to S3 url (provided to you in Payload from Step #1). Here is an example using the library Rest Sharp (which some Amazon employee seems to like judging by the reference in Amazon's C# client example).
NB: The Content Type must match the content type in your CreateFeedDocument request (Step #1).
Here is a function you can use to upload to S3...
private async Task UploadFile(byte[] bytes, string url)
{
var contentType = "text/plain; charset=utf-8"; // this should be the same as what was used in Step #1 (in the CreateFeedDocument API request)
RestClient restClient = new RestClient(url);
IRestRequest restRequest = new RestRequest(Method.PUT);
restRequest.AddParameter(contentType, bytes, ParameterType.RequestBody);
var response = await restClient.ExecuteAsync(restRequest);
if (!response.IsSuccessful)
{
// your error logic
}
// success. Move to Step #3
}
Happy days...

WebClient is not following redirects in .Net Core 3.1

I try to download a file with a URL that returns a 307 redirect code.
I tried using the WebClient.DownloadFile method, but it seems to not follow the redirects of the requested site. The stuff i found by searching for this issue either says it should work (Microsoft docs) or does not really answer my questions: WebClient Does not automatically redirect
My first question here is why is it not following the redirect, even if the HttpWebRequest it uses has AllowAutoRedirect=true?
My second question is how to best implement a function which downloads a file with automatic redirects.
An example URL i'm using would be: https://api.spiget.org/v2/resources/10905/download
But this URL is not allways redirecting, depending on some internal API states i guess.
Here's a simple example with HttpClient
.NET Core 3.1 Console app (UPD: added progress reporting)
class Program
{
private static readonly HttpClient client = new HttpClient(new HttpClientHandler() { AllowAutoRedirect = true });
static async Task Main(string[] args)
{
try
{
IProgress<int> progress = new Progress<int>(p =>
{
Console.Write(p + " ");
});
await DownloadAndSaveFileAsync("https://api.spiget.org/v2/resources/10905/download", progress);
Console.WriteLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine("Done.");
Console.ReadKey();
}
private static async Task DownloadAndSaveFileAsync(string url, IProgress<int> progress)
{
using HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
response.EnsureSuccessStatusCode(); // throw if not success
string fileName = response.Content.Headers.ContentDisposition?.FileName ?? throw new Exception("Nothing to download");
fileName = fileName.Trim('\"'); // remove quotes
long contentLength = response.Content.Headers.ContentLength ?? 0;
Console.WriteLine("File: {0}", fileName);
Console.WriteLine("Content-Length: {0} bytes", contentLength);
using Stream responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
using FileStream fileStream = File.Create(fileName);
int bufferSize = 65536;
byte[] buffer = new byte[bufferSize];
int bytesRead;
long position = 0;
int storedPercentage = -1;
while ((bytesRead = await responseStream.ReadAsync(buffer, 0, bufferSize)) > 0)
{
await fileStream.WriteAsync(buffer, 0, bufferSize);
if (contentLength > 0)
{
position += bytesRead;
int percentage = (int)(position * 100 / contentLength);
if (percentage != storedPercentage)
{
progress?.Report(percentage);
storedPercentage = percentage;
}
}
}
}
}
Console output
File: [1.8 TO 1.16] Ultra Cosmetics [OPENSOURCE & FREE!!]#10905.jar
Content-Length: 1692542 bytes
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 73 72 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
Done.
File downloaded successfully.
Compared byte-by-byte with downloaded in browser. Files are idential.

How would I parse a file (which seperates unicode text with 00 bytes) into a list?

Given a selection of bytes in a hex editor shows the file separates text with 00 bytes, it's a coloring file, with the material name, follolwed by a 3 byte hex code that determines colour. which is why it contains bytes like FF. the bytes are shown like this:
00 11 46 6F 6C 69 61 67 65 5F 45 76 65 72 67 72 65 65 6E 00 FF FF FF 00 0D 46 6F 6C 69 61 67 65 5F 42 69 72 63 68 00 80 A7 55
which translates into ascii as such:
Foliage_Evergreen�ÿÿÿ�
Foliage_Birch�€§U
How would I separate these bytes down into a list and convert them into text list of the bytes' values? I'm having trouble understanding how I'd go about doing it... this is what I'm doing right now:
OpenFileDialog openFileDialog1 = new OpenFileDialog();
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
}
string line = System.IO.File.ReadAllText(openFileDialog1.FileName);
byte[] bytes = Encoding.ASCII.GetBytes(line);
List<string> listtext = line.Split('.').ToList();
listBox1.DataSource = listtext;
You shouldn’t do that, will crash for some files with encoding exception:
string line = System.IO.File.ReadAllText(openFileDialog1.FileName);
byte[] bytes = Encoding.ASCII.GetBytes(line);
Use File.ReadAllBytes instead, no need to read text then convert to bytes.
Then you’ll need to parse array of bytes into your records.
Based on your example data, your format uses 0 as field separator, and strings are prepended by their lengths. Here’s an example how to parse, untested:
static IEnumerable<(string, Color)> parse( byte[] data )
{
for( int p = 0; p < data.Length; )
{
// '\0'
if( 0 != data[ p++ ] ) throw new ApplicationException();
// String length byte
int length = data[ p++ ];
// The string; assuming the encoding is UTF8
string name = Encoding.UTF8.GetString( data, p, length );
p += length;
// '\0'
if( 0 != data[ p++ ] ) throw new ApplicationException();
// 3 color bytes, assuming the order is RGB
Color color = Color.FromArgb( 0xFF, data[ p ], data[ p + 1 ], data[ p + 2 ] );
p += 3;
yield return (name, color);
}
}

How can i convert HEX to ASCII and only get the number from it?

I am receiving data from weighing scale(serial port) as HEX. I want to convert it to ASCII and only need the weight from it.
Code:
private void button1_Click(object sender, EventArgs e)
{
if (_serialPort != null && _serialPort.IsOpen)
_serialPort.Close();
if (_serialPort != null)
_serialPort.Dispose();
_serialPort.BaudRate = Convert.ToInt16(cbBaud.Text);
_serialPort = new SerialPort(comboBox1.Text, BaudRate, Parity.None, 8, StopBits.One);
_serialPort.DataReceived += SerialPortOnDataReceived;
_serialPort.Open();
textBox1.Text = string.Format("Listening on {0}...", comboBox1.Text);
}
private delegate void Closure();
private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
if (InvokeRequired)
BeginInvoke(new Closure(() => { SerialPortOnDataReceived(sender, serialDataReceivedEventArgs); }));
else
{
while (_serialPort.BytesToRead > 0)
{
textBox1.Text += string.Format("{0:X2} ", _serialPort.ReadByte());
}
}
This is my output:
Listening on COM1...20 20 20 30 0D 28 02 71 70 30 20 20 20 20 38 30 20 20 20 20 20 30 0D 28 02 71 70 30 20 20 20 20 38 30 20 20 20 20 20 30 0D 28 02 71 70 30 20 20 20 20 38 30 20 20 20 20 20 30 0D 28 02 71 70 30 20 20 20 20 38 30 20 20 20 20 20 30 0D 28 02 71 70 30 20 20 20 20 38 30 20 20 20 20 20 30 0D 28 02 71 70 30 20 20 20 20 38 30 20 20 20 20 20 30 0D 28 02 71 70 30 20 20 20 20 38 30 20 20 20 ....
preview
This is ASCII code that i converted manually from a website:
0
( q p 0 8 0 0
( q p 0 8 0 0
( q p 0 8 0 0
( q p 0 8 0 0
( q p 0 8 0 0
( q p 0 8 0 0
( q p 0 8 0
You have copied some expample but there are more suitable methods to read from serial port that would better suit your purpose.
First you need to determine the data format of the weighting indicator from the manual. Then you can use this (instead of the while loop):
string myData = _serialPort.ReadTo("\r");
where "\r" weight record delimiter (it could be also other strings like <CR><LF>, <STX> <ETX> etc.)
If you want to read all available input data from the serial port buffer, you can use
string myData = _serialPort.ReadExisting();
and split the string by specified char
string[] weightRecords = myData.Split('\r');
Then you parse the weight numeric values from the obtained strings. So you do not need to convert data from bytes, you can read it directly as a string. If you need more inspiration, check this project.
If you want to try it, you can rewrite the body of your DataReceived handler like this:
if (InvokeRequired)
BeginInvoke(new Closure(() => { SerialPortOnDataReceived(sender, serialDataReceivedEventArgs); }));
else
{
//There may be multiple records available in the Serial Port buffer
string myData = _serialPort.ReadExisting();
//Suppose that 0D character (equals to \r) marks the end of record, see manual of the indicator
string[] weightRecords = myData.Split('\r');
foreach (var s in weightRecords)
{
//9,5 = Position and length of the numeric weight value, for exact values see your weight indicator manual
textBox1.Text += string.Format("{0} kg \n", s.Substring(9,5));
}
}
To split your string by delimiters consisting of multiple chars, you can use something like this:
string[] stringSeparators = new string[] {
System.Text.Encoding.ASCII.GetString(new byte[] {0x0d, 0x28})
};
string[] weightRecords = myData.Split(stringSeparators, StringSplitOptions.None);

Read string of numbers into a grid/matrix [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Can anyone tell me how can I read this grid into arrays like a[i][j] ? I searched on google but I can't seem to find anything useful.Thank you very much for helping!
static void Main(string[] args)
{
String grid = "08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08" +
"49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00" +
"81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65" +
"52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91" +
"22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80" +
"24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50" +
"32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70" +
"67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21" +
"24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72" +
"21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95" +
"78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92" +
"16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57" +
"86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58" +
"19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40" +
"04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66" +
"88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69" +
"04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36" +
"20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16" +
"20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54" +
"01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48";
int[] a = new int[20];
for(int i=0;i<20;i++)
for (int j = 1; j < 20; j++)
{
}
}
As suggested in the comments you can simply separate your numbers and use split string. for example:
private static void Main(string[] args)
{
String grid = "08,02,22,97,38,15,00,40,00,75,04,05,07,78,52,12,50,77,91,08," +
"49,49,99,40,17,81,18,57,60,87,17,40,98,43,69,48,04,56,62,00," +
"81,49,31,73,55,79,14,29,93,71,40,67,53,88,30,03,49,13,36,65," +
"52,70,95,23,04,60,11,42,69,24,68,56,01,32,56,71,37,02,36,91," +
"22,31,16,71,51,67,63,89,41,92,36,54,22,40,40,28,66,33,13,80," +
"24,47,32,60,99,03,45,02,44,75,33,53,78,36,84,20,35,17,12,50," +
"32,98,81,28,64,23,67,10,26,38,40,67,59,54,70,66,18,38,64,70," +
"67,26,20,68,02,62,12,20,95,63,94,39,63,08,40,91,66,49,94,21," +
"24,55,58,05,66,73,99,26,97,17,78,78,96,83,14,88,34,89,63,72," +
"21,36,23,09,75,00,76,44,20,45,35,14,00,61,33,97,34,31,33,95," +
"78,17,53,28,22,75,31,67,15,94,03,80,04,62,16,14,09,53,56,92," +
"16,39,05,42,96,35,31,47,55,58,88,24,00,17,54,24,36,29,85,57," +
"86,56,00,48,35,71,89,07,05,44,44,37,44,60,21,58,51,54,17,58," +
"19,80,81,68,05,94,47,69,28,73,92,13,86,52,17,77,04,89,55,40," +
"04,52,08,83,97,35,99,16,07,97,57,32,16,26,26,79,33,27,98,66," +
"88,36,68,87,57,62,20,72,03,46,33,67,46,55,12,32,63,93,53,69," +
"04,42,16,73,38,25,39,11,24,94,72,18,08,46,29,32,40,62,76,36," +
"20,69,36,41,72,30,23,88,34,62,99,69,82,67,59,85,74,04,36,16," +
"20,73,35,29,78,31,90,01,74,31,49,71,48,86,81,16,23,57,05,54," +
"01,70,54,71,83,51,54,69,16,92,33,48,61,43,52,01,89,19,67,48";
var splitstring = grid.Split(',');
var a = new int[20,20];
const int rowCount = 19; //counts 0 as 1
var rowIndex = 0;
var colIndex = 0;
foreach (var s in splitstring)
{
if (rowIndex > rowCount)
{
rowIndex = 0;
colIndex++;
}
a[colIndex, rowIndex] = Int32.Parse(s);
rowIndex++;
}
}
Note the Int32.Parse(s) will throw an exception if the parse fails. You can instead use an Int32.TryParse and use the out value for your result. Depends on what you want to do.
Consider add a space to the end of each "line" such as the following:
String grid = "08 02 .. 91 08 " +
"01 70 .. 67 48 ";
// ^-- add space here
This will allow the string to be converted trivially into a 1D array of strings with string.Split.
string grid = "08 02 .. 91 08"; // every number is space-separated now
string[] gridArray = grid.Split(" "); // -> ["08", "02", .. "91", "08"]
(Even without ensuring the extra spaces, a 1D array can be achieved using a Regular Expression split: var gridArray = Regex.Split(grid, "(?:\s|(?<=\d{2})(?=\d{2}))"), but I recommend "normalizing" the input string literals if possible.)
And each index in the resulting 1D array can be accessed as so, where columns represents the number of columns of the super-imposed matrix, or the "width" of each row.
int columns = 20;
int gridIndex = j * columns + i; // where j is a *row* and i is a *column*
// for a column-major matrix
string numStr = gridArray[gridIndex]; // and value at the [column,row]
Then it's just a matter of converting numStr to an integer and assigning it to the appropriate array index.
If every number is separated by a space such that ever number NN is in form "NN " it also takes up 3 characters. In this case the intermediate Split can be skipped, using the same idea of indexing into the source as a 1D sequence.
int gridNumOffset = (j * columns + i) * 3;
string numStr = grid.Substring(gridNumOffset, 2);
(Finding the substring offset even when there is no space at the end-of-line can be done using a little bit more math, which is a good exercise and the formula just becomes (j * columns + i) * 3 + f(i), where f(i) applies the appropriate offset.)
Another more mundane approach, assuming that the original string cannot be modified to include an end-of-line space/character, is to read in each line as N characters, deal with it, and move on. The concepts from above can be applied:
int rowWidth = (columns * 3) - 1; // -1 assuming no line-end space
for(int j = 0; j < rows; j++) { // j is *rows*, for column-major matrix
string rowStr = str.Substring(j * rowWidth, rowWidth);
string[] row = rowStr.Split(" "); // 1D array just for this row
for (int i = 0; i < columns; i++) {
string numStr = row[i];
// Convert and put value into the correct matrix position
}
}

Categories