Search code examples
c#serializationtcpclient

Sending a bit type data through TCP socket method in C#


it's my first time questioning on this platform. Feel free to point out what I should do or avoid in order to get better, thanks.

I'm trying to sending a Struct object to MES(Manufacturing Execution System) for changing status of my work station. Here is the illustration of the data structure(2.2):

1

And the code below in C# is what I have done. I' m sure that I connected to the MES system but the Status just did't change, and I thought the reason might related to the format of the data I transfered.

using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;
using TcpClient = NetCoreServer.TcpClient;


//the Struct of data
[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct StateOfRobotino
{
    public int ResourceID;
    public byte SPSType;
    public byte State_info;
}


StateOfRobotino robotino10 = new StateOfRobotino();
robotino10.ResourceID = 10;
robotino10.SPSType = 2;
robotino10.State_info = 0b10000001; //MES mode, Auto
byte[] b_robotino10 = getBytes(robotino10);


//Convert Struct type to byte array through Marshal
byte[] getBytes(StateOfRobotino str)
        {
            int size = Marshal.SizeOf(str);
            byte[] arr = new byte[size];

            IntPtr ptr = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(str, ptr, true);
            Marshal.Copy(ptr, arr, 0, size);
            Marshal.FreeHGlobal(ptr);
            return arr;
        }

One thing I was doubt on is the third data in my Struct, can I just use a byte(State_info) to represent 8 bits data? If not, how am I suppose to do? Or is there any other way that I can try to transfer this kind of data ? Thank you.


Solution

  • The marshalling method to get your byte array should work.

    Now onto your data structure:

    ResourceID  Int   0
    SPSType     Byte  2
    Auto Mode   Bit   3.0
    ...         Bit   3.n
    MES Mode    Bit   3.7
    

    I bring your attention to the numeric column containing 0, 2, and 3.x

    1. ResourceID looks to occupy bytes 0 and 1. Two bytes in an Int indicates your PLC is 16-bit. C#'s int is 32-bit which takes up FOUR bytes. You need to explicitly specify either Int16 or UInt16 (probably the unsigned UInt16, unless you MES expects a negative number from the PLC).

      They are also known as short or ushort, but it's always nice to be more explicit by specifying the 16-bitness when dealing with external systems to minimise confusion.

    2. SPSType is simply a byte.

    3. The rest of them are marked as 3.0 ... 3.7. This is the notation for 8 bits (0..7) that occupy byte 3. Which means, yes, you are expected to send one byte containing all the bits. Do bear in mind that bit 0 is the right-most bit, so 0b00000001 is AutoMode, and 0b10000000 is MESMode.