Not signed in (Sign In)

Site Tag Cloud

Categories

Vanilla 1.1.9 is a product of Lussumo. More Information: Documentation, Community Support.

  1.  
    I was wanting to know if i can get some help I'm wanting to write a Windows C# application to control coasters through the tel server I'm looking at using the System.Net.Sockets Lib.

    My only issue is I've never done anything with the sockets so I'm unsure of how to build the messages to send to the server. the only C# samples i can find show how to send messages shows it sending a text string not the byte array that is needed. I attempted to try to look at the java example and convert it but I'm unsure of how to build the message correctly. If anyone could help me with how i can build the message and receive messages from the server would be greatly appreciated.

    Currently i have the following trying to send just the idle message

    private void BTN_CONNECT_Click(object sender, RoutedEventArgs e)
    {
    IPAddress IP = IPAddress.Parse(TB_IPADDRESS.Text);



    TcpClient client = new TcpClient();

    client.Connect(IP, 15151);

    while (client.Connected == true)
    {
    //Get the stream to send and recieve data
    NetworkStream stream = client.GetStream();
    Byte[] sendBytes = Encoding.UTF8.GetBytes("0,1,0,0");
    Byte[] RecieveBytes = new byte[client.ReceiveBufferSize];
    stream.Write(sendBytes, 0, sendBytes.Length);
    stream.Read(RecieveBytes, 0, (int)client.ReceiveBufferSize);

    }

    }
    •  
      CommentAuthorbestdani
    • CommentTimeAug 7th 2017
     
    Posted By: slifer1231
    Byte[] sendBytes = Encoding.UTF8.GetBytes("0,1,0,0");

    This looks a bit odd. When I understand this line correctly it seems that you convert the UTF8 string "0,1,0,0" into a byte array here.
    What you actually want to send is a structure / class with the data types that are presented in the manual (uchar8, ushort16, uint32, ushort16, uchar8).
    This could be what you are looking for (I don't know C#): How to convert a structure to byte array in c# which looks like a simple method to convert a simple class that acts as a structure into a byte array.
    • CommentAuthorslifer1231
    • CommentTimeAug 7th 2017 edited
     
    I'm not currently with my computer to try this out or read the no limits manual again to look at the message IDs etc but I wrote this out so in theory something like this should work right?


    //Make a Strut a Byte array for sending to the socket
    byte [] StructureToByteArray(object obj)
    {
    int len = Marshal.SizeOf(obj);

    byte [] arr = new byte[len];

    IntPtr ptr = Marshal.AllocHGlobal(len);

    Marshal.StructureToPtr(obj, ptr, true);

    Marshal.Copy(ptr, arr, 0, len);

    Marshal.FreeHGlobal(ptr);

    return arr;
    }

    //Return the Data Recieved back in to a Strut
    void ByteArrayToStructure(byte [] bytearray, ref object obj)
    {
    int len = Marshal.SizeOf(obj);

    IntPtr i = Marshal.AllocHGlobal(len);

    Marshal.Copy(bytearray,0, i,len);

    obj = Marshal.PtrToStructure(i, obj.GetType());

    Marshal.FreeHGlobal(i);
    }

    //Create a Struct convert it to a Byte Array and return it to the calling function to be send by socket
    byte[] CreateMessage()
    {
    struct MessageStrut
    {
    public byte uchar8; //byte is C# equivalent to uchar8
    public ushort ushort16; //This is the ushort16
    public uint uint32; //This is the uint32
    public ushort 2ndushort16; //this is the second ushort
    public byte end; //this is the uchar8
    };

    //Create the Strut
    MessageStruct SendStruct = new MessageStruct();

    //The Zeros would be replaced with variables for the message ID,Response,ID,Etc
    SendStruct.uchar8 = 0;
    SendStruct.ushort16 = 0;
    SendStruct.uint32 = 0;
    SendStruct.2ndushort16 = 0;
    SendStruct.end = 0;


    Byte[] ConvertedStruct = StructureToByteArray(SendStruct);

    return ConvertedStruct

    }


    private void BTN_CONNECT_Click(object sender, RoutedEventArgs e)
    {
    IPAddress IP = IPAddress.Parse(TB_IPADDRESS.Text);



    TcpClient client = new TcpClient();

    client.Connect(IP, 15151);

    while (client.Connected == true)
    {


    //Get the stream to send and recieve data
    NetworkStream stream = client.GetStream();
    Byte[] SendBytes = CreateMessage();
    Byte[] RecieveBytes = new byte[client.ReceiveBufferSize];
    stream.Write(sendBytes, 0, sendBytes.Length);
    stream.Read(RecieveBytes, 0, (int)client.ReceiveBufferSize);

    }

    }
    •  
      CommentAuthorbestdani
    • CommentTimeAug 7th 2017 edited
     
    Looks better but what is missing is that you currently use the char 0 for the message start and end, while the NL2 telemetry server uses theses as "magic bytes" to detect messages as stated in the manual. So therefore the first uchar8 has to be 'N' and the last one 'L' (hex values 0x4e and 0x4c). As far as I could see C# also has the char type. If this is ASCII encoded something like that might also work directly, maybe it needs some tweaks to make it work in C#, but this can at least considered as pseudo code that should show the idea:

    struct Nl2TelemetryMessage
    {
    public char magicStart = 'N'; //magic start (uchar8)
    public ushort typeId = 0; //this is the ushort16
    public uint requestId = 0; //this is the uint32
    public ushort dataSize = 0; //this is the second ushort
    public char magicEnd = 'L'; //magic end (uchar8)
    };
    //..
    Nl2TelemetryMessage message = new Nl2TelemetryMessage();
  2.  
    When I get back home ill try to test what you put and see if I can get a response. Ill test with a message I can see visually in the game to verify the command is received such as opening the gates etc. if that works then I can work on getting the responses decoded and get them in a human readable form. once I get the code base done and can send and receive messages I will try to make a close to real life panel as I can I have some graphics that I can use on the UI
    • CommentAuthorslifer1231
    • CommentTimeAug 7th 2017 edited
     

    If anyone wants to follow along or offer advice I have the source here

    GitHub Source.

    • CommentAuthorslifer1231
    • CommentTimeAug 8th 2017 edited
     

    I'm not sure if its creating the array correctly after the Byte Array for sending the idle message is created it comes out as 12 bytes like so 78,0,0,0,1,0,0,0,0,0,76,0 After sending that there is no data available on the stream so its either doesn't respond or I didn't create the byte array correctly the source code on the GitHub link is current the function to send it is in the MainWindow.xaml file under btn_SendIdle_Click

    EDIT: so the byte array looks like everything is shifted 1 byte Example the Get Version message array should be like this: 78,3,0,1,0,0,0,0,0,76,0

    but instead after the Strut is converted to the byte array it comes out like this 78,0,3,0,1,0,0,0,0,0,76,0

    the response i get on this is 78,0,2,1,0,0,0,0,15,85,110,107,12

    Here is my code for Sending the Message >

          //Get the Stream to send and recieve data
           Byte[] data = CreateMessage(3, 1, 0);
           NetworkStream stream = NL2Client.GetStream();
    
           stream.Write(data, 0, data.Length);
           //make a buffer to store the response
           //data = new Byte[10];
           string responsedata = string.Empty;
           //Cant read for some reason 
           Int32 bytes = stream.Read(data, 0, data.Length);
    
           stream.Close();
    

    Here is the code for creating the strut

          Nl2TelemetryMessage message = new Nl2TelemetryMessage();
    
    
           message.magicStart = (byte)'N';
           message.typeId = Typeid;
          message.requestId = Requestid;
          message.dataSize = datasize;
           message.magicEnd = (byte)'L' ;
    
    
    
          Byte[] ConvertedStruct = StructureToByteArray(message);
    
           return ConvertedStruct;
    

    and finally here is the code for converting the strut to the byte array

      private byte[] StructureToByteArray(object obj)
       {
           int len = Marshal.SizeOf(obj);
    
           byte[] arr = new byte[len];
    
           IntPtr ptr = Marshal.AllocHGlobal(len);
    
           Marshal.StructureToPtr(obj, ptr, true);
    
           Marshal.Copy(ptr, arr, 0, len);
    
           Marshal.FreeHGlobal(ptr);
    
           return arr;
       }
    

    it seems once the strut gets passed to the StructureToByteArray Function it has a byte size of 12 and after the Marshal.copy is done and fills the array everything after the start byte is shifted

  3.  

    So after messing for hours i gave up on trying to figure out the strut problem so instead i took a look at the java sample that comes with the Game and i managed to port most of the functions into my program and now it can send and receive messages. I just have to work on getting toggles working and reading status then i can get the rest of it done