ping9719 / McProtocol

三菱plc通信MC协议的实现。(This is a protocol for communicating with Mitsubishi PLCs.)
37 stars 15 forks source link

How can I read ASCII data? #1

Open locodust6 opened 2 years ago

locodust6 commented 2 years ago

I tried with below code.

PLCData<char> devices = new(PlcDeviceType.W, 0x100, 256);
devices.ReadData();

StringBuilder sb = new();
for (int i = 0; i < 160; i++)
{
    sb.Append(devices[i]);
}
sb.ToString();

However, I get "McProtocol.PLCData`1[System.Char]".
How can I get the string?

locodust6 commented 2 years ago

I was able to get it in the following way.

PLCData<short> devices = new(PlcDeviceType.W, 0x100, 256);
devices.ReadData();

StringBuilder sb = new();
for (int i = 0; i < 160; i++)
{
    string str = ASCIIEncoding.ASCII.GetString(Convert.FromHexString(devices[i].ToString("X2")));
    if (str == "\0") break;
    sb.Append(str);
}
sb.ToString();

Is there a smarter way or an official way?

ping9719 commented 2 years ago

支持直接转的类型有:Boolean,Int32,Int16,UInt16,UInt32,Single,Char 我开放出来了Bytes,在版本 v2.1.6 你可以试试:(我也不知道是否可行,我没有测试环境,如果不行请告诉我) ` //>= v2.1.6 PLCData devices = new(PlcDeviceType.W, 0x100, 256); devices.ReadData(); Encoding.ASCII.GetString(devices.Bytes);

//< v2.1.6 var bytes = await mcProtocolTcp.ReadDeviceBlockByte(PlcDeviceType.W, 0x100, 256); Encoding.ASCII.GetString(bytes); `

locodust6 commented 2 years ago

Thank you for your response.

However, since the byte order is reversed, it cannot be converted into a string as is.
For example, "ABCDEF" becomes "BADCFE".

Therefore, it was necessary to change the byte order as shown below and convert it to a string.

//It is necessary to loop to read all character strings, but it is omitted.
Encoding.ASCII.GetString(Convert.FromHexString(BinaryPrimitives.ReadInt16LittleEndian(bytes.AsSpan(intStart, intLength)).ToString("X2")))

Appendix

I was able to get it in the following way.

PLCData<short> devices = new(PlcDeviceType.W, 0x100, 256);
devices.ReadData();
byte[] devicesBytes = devices.Bytes;

byte[] cropBytes = bytes.AsSpan(0 * 2, 160 * 2).ToArray();
byte[] trimdBytes = cropBytes.TakeWhile(x => x != 0).ToArray();
byte[] sortedBytes = new byte[trimdBytes.Length];
for (int i = 0; i < sortedBytes.Length; i += 2)
{
    if (i == sortedBytes.Length -1)
        {
            sortedBytes[i] = trimdBytes[i];
            break;
        }
        sortedBytes[i] = trimdBytes[i + 1];
        sortedBytes[i + 1] = trimdBytes[i];
}

Encoding.ASCII.GetString(sortedBytes);
ping9719 commented 2 years ago

高低位转换需要自己转换,不是很难。不提供的原因是一般都是为ABCDE这样的,你自己转换就行了。 我为你提供一段代码思路:

    byte[] bytes = Encoding.ASCII.GetBytes("BADCFEG");
    for (int i = 0; i < bytes.Length - 1; i += 2)
        (bytes[i], bytes[i + 1]) = (bytes[i + 1], bytes[i]);
    //ABCDEFG
    string re = Encoding.ASCII.GetString(bytes);
locodust6 commented 2 years ago

Thank you.

I will refer to it. Since it is a process that is commonly used, I would be happy if it could be provided by the ToString() method.

ping9719 commented 2 years ago

string 和 int bool .... 不同,你可以自己写一个类来完成自己的特殊化需求。 然后你把你的代码发出来(我试了一下,我的代码不是很合理),我试试能不能加入到代码中,提供给所有的人使用。

Please provide your code for my reference.