rossmann-engineering / EasyModbusTCP.NET

Modbus TCP, Modbus UDP and Modbus RTU client/server library for .NET implementations
949 stars 413 forks source link

How to write string data by WriteMultipleRegisters #41

Closed dj910624 closed 4 years ago

dj910624 commented 4 years ago

Is there any way to sending string data to modbus-tcp server via WriteMultipleRegisters() methods? I made the function that convert string Ascii to int array, but is not graceful. The function is follow:

int [] rawToIntArray(byte [] raw)
        {
            int[] ret = new int[raw.Length/2];

            for(int u=0; u< ret.Length; u++)
            {
                int [] temp = new int[1];
                int idx = u * 2;
                byte[] reverse = new byte[2];
                reverse[0] = raw[idx + 1];
                reverse[1] = raw[idx];
                Buffer.BlockCopy(reverse, 0, temp, 0, 2);
                ret[u] = temp[0];
            }
            return ret;
        }
byte[] raw = System.Text.Encoding.UTF8.GetBytes("FileName");
int[] param = rawToIntArray(raw);
modbusClient.WriteMultipleRegisters(12544, param);

Any other way to sending string data to server??

Padanian commented 4 years ago

It's already included in Easymodbus

        public static int[] ConvertStringToRegisters(string stringToConvert)
        {
            byte[] array = System.Text.Encoding.ASCII.GetBytes(stringToConvert);
            int[] returnarray = new int[stringToConvert.Length / 2 + stringToConvert.Length % 2];
            for (int i = 0; i < returnarray.Length; i++)
            {
                returnarray[i] = array[i * 2];
                if (i*2 +1< array.Length)
                {
                    returnarray[i] = returnarray[i] | ((int)array[i * 2 + 1] << 8);
                }
            }
            return returnarray;
        }
dj910624 commented 4 years ago

It's already included in Easymodbus

        public static int[] ConvertStringToRegisters(string stringToConvert)
        {
            byte[] array = System.Text.Encoding.ASCII.GetBytes(stringToConvert);
            int[] returnarray = new int[stringToConvert.Length / 2 + stringToConvert.Length % 2];
            for (int i = 0; i < returnarray.Length; i++)
            {
                returnarray[i] = array[i * 2];
                if (i*2 +1< array.Length)
                {
                    returnarray[i] = returnarray[i] | ((int)array[i * 2 + 1] << 8);
                }
            }
            return returnarray;
        }

Thanks Padanian. But, the ConvertStringToRegisters is not network order. So, If I use ConvertStringToRegisters mothod, I have to reordering to network order. Such like that:

data = ModbusClient.ConvertStringToRegisters("FileName");
for(int u=0; u<data.Length; u++)
{
     data[u] = (ushort)IPAddress.HostToNetworkOrder(Convert.ToInt16(data[u]));
}
modbusclient.WriteMultipleRegisters(12544, data);

Any other way more simply??

Padanian commented 4 years ago

Give a try at Array.Reverse(data) maybe?

dj910624 commented 4 years ago

I already try this, but, Array.Reverse(data) just rearrange reverse array. It's not a solution. If I use Array.Reverse(data) modbus client sends "emaNeliF". So, I should reverse each register element to network byte order. Thanks.

Padanian commented 4 years ago

See the other thread. Your array needs to be short or int16 (16bit integer)

When you need to reconvert the string, then and only then you will get two bytes from each register or combine two bytes into one Int.

static short ToShort(short byte1, short byte2) { return (byte2 << 8) + byte1; }

static void FromShort(short number, out byte byte1, out byte byte2) { byte2 = (byte)(number >> 8); byte1 = (byte)(number & 255); }

You can also use Bitconverter class

byte[ ] data

Int16 value = BitConverter.ToInt16( data, index );