Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GPS Socket communication (CONCOX)

Tags:

c#

sockets

1]1i have a gps device that should send GPRMC Data but it require login packect Review the dataSheet Device DataSheet

enter image description here

i can recieve the login 787811010XXX739050313XXX20200001000E0EAD0D0A

     IMEI Sart With XXX

the packet is different from the example Image

i have 2 Questions 1-according to the data recieveid and the example what should i send 2- how to calcaulate the Error Check Thank You

Edit

public static void StartListening()
{
    // Data buffer for incoming data.
    byte[] bytes = new Byte[1024];

    // Establish the local endpoint for the socket.
    // The DNS name of the computer
    // running the listener is "host.contoso.com".
    IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
    IPAddress ipAddress = ipHostInfo.AddressList[0];
    IPAddress local = IPAddress.Parse("My IP");
    IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 8841);

    // Create a TCP/IP socket.
    Socket listener = new Socket(AddressFamily.InterNetwork,
        SocketType.Stream, ProtocolType.Tcp);

    // Bind the socket to the local endpoint and listen for incoming connections.
    try
    {
        listener.Bind(localEndPoint);
        listener.Listen(100);

        while (true)
        {
            // Set the event to nonsignaled state.
            allDone.Reset();

            // Start an asynchronous socket to listen for connections.
            // Console.WriteLine("Waiting for a connection...");
            listener.BeginAccept(
                new AsyncCallback(AcceptCallback),
                listener);

            // Wait until a connection is made before continuing.
            allDone.WaitOne();
        }

    }
    catch (Exception e)
    {
        // Console.WriteLine(e.ToString());
    }

    // Console.WriteLine("\nPress ENTER to continue...");
    // Console.Read();

}
private static void Send(Socket handler, String data)
{
    // Convert the string data to byte data using ASCII encoding.
    byte[] byteData = Encoding.ASCII.GetBytes(data);

    // Begin sending the data to the remote device.
    handler.BeginSend(byteData, 0, byteData.Length, 0,
        new AsyncCallback(SendCallback), handler);
}
private static void Send(Socket handler, byte[]  data)
{
    // Convert the string data to byte data using ASCII encoding.
   // byte[] byteData = Encoding.ASCII.GetBytes(data);

    // Begin sending the data to the remote device.
    handler.BeginSend(data, 0, data.Length, 0,
        new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
    try
    {
        // Retrieve the socket from the state object.
        Socket handler = (Socket)ar.AsyncState;

        // Complete sending the data to the remote device.
        int bytesSent = handler.EndSend(ar);
        // Console.WriteLine("Sent {0} bytes to client.", bytesSent);

        handler.Shutdown(SocketShutdown.Both);
        handler.Close();

    }
    catch (Exception e)
    {
        // Console.WriteLine(e.ToString());
    }
}
public static void AcceptCallback(IAsyncResult ar)
{
    // Signal the main thread to continue.
    allDone.Set();

    // Get the socket that handles the client request.
    Socket listener = (Socket)ar.AsyncState;
    Socket handler = listener.EndAccept(ar);

    // Create the state object.
    StateObject state = new StateObject();
    state.workSocket = handler;
    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
        new AsyncCallback(ReadCallback), state);
}
static byte[] Unpack(string data)
{
    //return null indicates an error
    List<byte> bytes = new List<byte>();

    // check start and end bytes

    if ((data.Substring(0, 4) != "7878") && (data.Substring(data.Length - 4) != "0D0A"))
    {
        return null;
    }

    for (int index = 4; index < data.Length - 4; index += 2)
    {
        bytes.Add(byte.Parse(data.Substring(index, 2), System.Globalization.NumberStyles.HexNumber));
    }
    //crc test
    byte[] packet = bytes.Take(bytes.Count - 2).ToArray();
    byte[] crc = bytes.Skip(bytes.Count - 2).ToArray();

    uint CalculatedCRC = crc_bytes(packet);


    return packet;
}
public static UInt16 crc_bytes(byte[] data)
{
    ushort crc = 0xFFFF;

    for (int i = 0; i < data.Length; i++)
    {
        crc ^= (ushort)(data[i] << 8);
        for (int j = 0; j < 8; j++)
        {
            if ((crc & 0x8000) > 0)
                crc = (ushort)((crc << 1) ^ 0x1021);
            else
                crc <<= 1;
        }
    }

    return crc;
}
public static void ReadCallback(IAsyncResult ar)
{
    String content = String.Empty;

    // Retrieve the state object and the handler socket
    // from the asynchronous state object.
    StateObject state = (StateObject)ar.AsyncState;
    Socket handler = state.workSocket;

    // Read data from the client socket. 
    int bytesRead = handler.EndReceive(ar);

    if (bytesRead > 0)
    {

        if (state.buffer[3] == 1)
        {

            string input = BitConverter.ToString(state.buffer, 0, bytesRead).Replace("-", "");

            byte[] bytes = Unpack(input);

            byte[] serialNumber = bytes.Skip(bytes.Length - 2).ToArray();

            byte[] response = { 0x78, 0x78, 0x05, 0x01, 0x00, 0x00, 0x00, 0x0 };

            serialNumber.CopyTo(response, 4);

            UInt16 sendCRC = crc_bytes(response.Take(response.Length - 2).ToArray());

            response[response.Length - 2] = (byte)((sendCRC >> 8) & 0xFF);
            response[response.Length - 1] = (byte)((sendCRC) & 0xFF);

            Send(handler, response);
           // handler.Send(response);
        }
        else
        {
            // There  might be more data, so store the data received so far.
            state.sb.Append(Encoding.ASCII.GetString(
                state.buffer, 0, bytesRead));

            // Check for end-of-file tag. If it is not there, read 
            // more data.
            content = state.sb.ToString();


            SaveData(content);
            // Not all data received. Get more.
            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
            new AsyncCallback(ReadCallback), state);
            // }
        }
    }
}

Vendor DataSheet

4.6. Error Check A check code may be used by the terminal or the server to distinguish whether the received information is error or not. To prevent errors occur during data transmission, error check is added to against data misoperation, so as to increase the security and efficiency of the system. The check code is generated by the CRC-ITU checking method. The check codes of data in the structure of the protocol, from the Packet Length to the Information Serial Number (including “Packet Length” and “Information Serial Number”) , are values of CRC-ITU. CRC error occur when the received information is calculated, the receiver will ignore and discard the data packet. 4

DataBase Table

CREATE TABLE [dbo].[T_Tracking](
[id] [int] IDENTITY(1,1) NOT NULL,
[IMEI] [nvarchar](50) NULL,
[TrackTime] [datetime] NULL,
[CurrTime] [datetime] NULL CONSTRAINT [DF_T_Tracking_CurrTime]  DEFAULT (getutcdate()),
[Longitude] [nvarchar](50) NULL,
[Lattitude] [nvarchar](50) NULL,
[speed] [float] NULL    

You Code

 switch (protocolNumber)
                            {
                                case PROTOCOL_NUMBER.LOGIN_MESSAGE:
                                    serialNumber.CopyTo(loginResponse, 4);

                                    sendCRC = crc_bytes(loginResponse.Skip(2).Take(loginResponse.Length - 6).ToArray());

                                    loginResponse[loginResponse.Length - 4] = (byte)((sendCRC >> 8) & 0xFF);
                                    loginResponse[loginResponse.Length - 3] = (byte)((sendCRC) & 0xFF);

                                    string terminalID = Encoding.ASCII.GetString(receiveMessage.Skip(4).Take(messageLength - 5).ToArray());
                                    Console.WriteLine("Received good login message from Serial Number : '{0}', Terminal ID = '{1}'", "0x" + serialNumber[0].ToString("X2") + serialNumber[1].ToString("X2"), terminalID);

                                    Console.WriteLine("Send Message : '{0}'", BytesToString(loginResponse));
                                    Send(state.workSocket, loginResponse);

                                    break;
                                case PROTOCOL_NUMBER.LOCATION_DATA:
                                    year = receiveMessage[4];
                                    month = receiveMessage[5];
                                    day = receiveMessage[6];
                                    hour = receiveMessage[7];
                                    minute = receiveMessage[8];
                                    second = receiveMessage[9];

                                    date = new DateTime(2000 + year, month, day, hour, minute, second);
                                    Console.WriteLine("Received good location message from Serial Number '{0}', Time = '{1}'", "0x" + serialNumber[0].ToString("X2") + serialNumber[1].ToString("X2"), date.ToLongDateString()); string lng = message.Substring(22, 8);
                                Int64 lngVal = Convert.ToInt64(lng, 16);

                                double step3 = (double)lngVal / 30000;
                                double step4 = (double)((step3 / 60));
                                //int lngdeg =Convert.ToInt32( step4.ToString().Split('.')[0]);

                                //  double step5 = (double)(step4 * 60) - step3;


                                string lat = message.Substring(30, 8);
                                Int64 altVal = Convert.ToInt64(lat, 16);
                                double Lstep3 = (double)altVal / 30000;
                                double Lstep4 = (double)((Lstep3) / 60);
                                //  double Lstep5 = (double)(Lstep4 * 60) - Lstep3;
                                //Console.WriteLine("Date : '{0}',Long : '{1}', Receive Message : '{2}'", dateStr, step4, Lstep4);
                                string speedstr = message.Substring(38, 2);
                                int SpeedVal = Convert.ToInt32(speedstr, 16);
                                SaveData(IMEI , dateStr, step4.ToString(), Lstep4.ToString(), SpeedVal);//Get IMEI From Login Message that is the Problem
                                    break;

enter image description here

Status Message enter image description here

like image 365
Maher Khalil Avatar asked Oct 24 '25 14:10

Maher Khalil


1 Answers

Here is the modified code Section 1 :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Data;
using System.Data.SqlClient;
using System.ComponentModel;
using System.Timers;

namespace ConcoxServer
{
    public class StateObject
    {
        public long connectionNumber = -1;
        public Socket workSocket { get; set; }
        public byte[] buffer { get; set; }
        public int fifoCount { get; set;}
        public string IMEI { get; set; }
    }

    public enum PROTOCOL_NUMBER
    {
        LOGIN_MESSAGE = 0x01,
        LOCATION_DATA = 0x12,
        STATUS_INFO = 0X13,
        STRING_INFO = 0X15,
        ALARM_DATA = 0X16,
        GPS_QUERY_ADDR_PHONE_NUM = 0X1A,
        COMMAND_INFO = 0X80,
        NONE
    }
    public enum UNPACK_STATUS
    {
        ERROR,
        NOT_ENOUGH_BYTES,
        BAD_CRC,
        GOOD_MESSAGE,
        DEFAULT
    }
    public enum PROCESS_STATE
    {
        ACCEPT,
        READ,
        PROCESS,
        UNPACK
    }
    public enum ALARM : Byte
    {
        NORMAL = 0,
        SHOCK_ALARM = 1,
        POWER_CUT_ALARM = 2,
        LOW_BATTERY = 3,
        SOS = 4
    }

    class Program
    {
        const string IP = "127.0.0.1";
        const int PORT = 8841;
        const Boolean test = true;

        static void Main(string[] args)
        {

            GPS gps = new GPS(IP, PORT, test);

            Console.WriteLine("Connection Ended");

        }
    }
    public class GPS
    {
        const int BUFFER_SIZE = 1024;
        const string CONNECT_STRING = @"Data Source=.\SQLEXPRESS;Initial Catalog=GPSTracker;Integrated Security=SSPI;";
        const string LOGIN_INSERT_COMMMAND_TEXT = "use GPSTracker INSERT INTO Login (TerminalID,Date) VALUES(@TerminalID,@Date)";
        const string LOCATION_INSERT_COMMMAND_TEXT = "INSERT INTO T_Tracking (IMEI,TrackTime, CurrTime, Longitude, Lattitude,speed)" +
            "VALUES (@IMEI, @TrackTime, @CurrTime, @Longitude, @Lattitude, @speed)";
        static SqlConnection conn = null;
        static SqlCommand cmdLogin = null;
        static SqlCommand cmdLocation = null;

        static byte[] loginResponse = { 0x78, 0x78, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0A };
        static byte[] alarmResponse = { 0x78, 0x78, 0x05, 0x16, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0A };
        static byte[] alarmDataAddressResponse = { 0x78, 0x78, 0x00, 0x97, 0x7E,
                                          0x00, 0x00, 0x00, 0x01,
                                          0x41, 0x4C, 0x41, 0x52, 0x4D, 0x53, 0x4D, 0x53,   //ALARMS
                                          0x26, 0x26,                                       //&&
                                          0x80, 0x00, 0x72, 0x00, 0x79, 0x00, 0x78, 0x00,   // PHONE HOME
                                          0x69, 0x00, 0x32, 0x00, 0x72, 0x00, 0x79, 0x00,
                                          0x77, 0x00, 0x69,
                                          0x26, 0x26,                                       //&&
                                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // Phone Numbe
                                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                          0x00, 0x00, 0x00, 0x00, 0x00,
                                          0x23, 0x23,                                       //##
                                          0x00, 0x00,                                       //serial number
                                          0x00, 0x00,                                       //check bytes
                                          0x0D, 0x0A                                        //stop bytes
                                      };
        static byte[] heartbeatResponse = { 0x78, 0x78, 0x05, 0x13, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0A };
        static byte[] connectOilAndEletricity = {
                                          0x78, 0x78, 0x16, 0x80, 0x10, 0x12, 0x34, 0x56, 0x78, 0x48,  //server flag bit 0x12345678
                                          0x46, 0x59, 0x44, 0x2C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
                                          0x23, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0A
                                     }; 

        static long connectionNumber = 0;
        //mapping of connection number to StateObject
        static Dictionary<long, KeyValuePair<List<byte>, StateObject>> connectionDict = new Dictionary<long, KeyValuePair<List<byte>, StateObject>>();
        //fifo contains list of connections number wait with receive data
        public static List<long> fifo = new List<long>();

        public static AutoResetEvent allDone = new AutoResetEvent(false);
        public static AutoResetEvent acceptDone = new AutoResetEvent(false);

        public GPS(string IP, int port, Boolean test)
        {
            try
            {
                conn = new SqlConnection(CONNECT_STRING);
                conn.Open();

                cmdLogin = new SqlCommand(LOGIN_INSERT_COMMMAND_TEXT, conn);
                cmdLogin.Parameters.Add("@TerminalID", SqlDbType.NVarChar, 8);
                cmdLogin.Parameters.Add("@Date", SqlDbType.DateTime);

                cmdLocation = new SqlCommand(LOCATION_INSERT_COMMMAND_TEXT, conn);
                cmdLocation.Parameters.Add("@IMEI", SqlDbType.NVarChar, 50);
                cmdLocation.Parameters.Add("@TrackTime", SqlDbType.DateTime);
                cmdLocation.Parameters.Add("@currTime", SqlDbType.DateTime);
                cmdLocation.Parameters.Add("@Longitude", SqlDbType.NChar, 50);
                cmdLocation.Parameters.Add("@Lattitude", SqlDbType.NVarChar, 50);
                cmdLocation.Parameters.Add("@speed", SqlDbType.Float);

            }
            catch (Exception ex)
            {
                Console.WriteLine("Error : '{0}'", ex.Message);
                //Console.ReadLine();
                return;
            }

            try
            {
                //initialize the timer for writing to database.
                WriteDBAsync.WriteDatabase();
                StartListening(IP, port, test);

                // Open 2nd listener to simulate two devices, Only for testing
                //StartListening(IP, port + 1, test);

                ProcessMessages();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error : '{0}'", ex.Message);
                //Console.ReadLine();
                return;
            }
        }
        public enum DATABASE_MESSAGE_TYPE
        {
            LOGIN,
            LOCATION
        }
        public class WriteDBMessage
        {
            public DATABASE_MESSAGE_TYPE message { get; set; }
        }
        public class WriteDBMessageLogin : WriteDBMessage
        {
            public DateTime date { get; set; }
            public string IMEI { get; set; }
        }
        public class WriteDBMessageLocation : WriteDBMessage 
        {
            public string IMEI { get; set; }
            public DateTime trackTime { get; set; }
            public DateTime currTime { get; set; }
            public byte[] longitude { get; set; }
            public byte[] lattitude { get; set; }
            public float speed { get; set; }
            public byte[] courseStatus { get; set; }
        }

        public static class WriteDBAsync
        {
            public enum Mode
            {
                READ,
                WRITE
            }
            public static List<WriteDBMessage> fifo = new List<WriteDBMessage>();
            public static System.Timers.Timer timer = null;

            public static void WriteDatabase()
            {
                timer = new System.Timers.Timer(1000);
                timer.Elapsed += Timer_Elapsed;
                timer.Start();
            }
            public static WriteDBMessage ReadWriteFifo(Mode mode, WriteDBMessage message)
            {
                Object thisLock2 = new Object();

                lock (thisLock2)
                {
                    switch (mode)
                    {
                        case Mode.READ:
                            if(fifo.Count > 0)
                            {
                                message = fifo[0];
                                fifo.RemoveAt(0);
                            }
                            break;
                        case Mode.WRITE:
                            fifo.Add(message);
                            break;
                    }

                }
                return message;
            }
            static void Timer_Elapsed(object sender, ElapsedEventArgs e)
            {
                timer.Enabled = false;
                WriteDBMessage row = null;
                int rowsAdded = 0;
                uint number = 0;
                double lat = 0;
                string latStr = "";
                double lon = 0;
                string longStr = "";
                int degrees = 0;
                double minutes = 0;
                try
                {

                    while((row = ReadWriteFifo(Mode.READ, null)) != null)
                    {
                        switch(row.message)
                        {
                            case DATABASE_MESSAGE_TYPE.LOGIN:
                                cmdLogin.Parameters["@TerminalID"].Value = ((WriteDBMessageLogin)row).IMEI;
                                cmdLogin.Parameters["@Date"].Value = ((WriteDBMessageLogin)row).date;
                                rowsAdded = cmdLogin.ExecuteNonQuery();
                                break;
                            case DATABASE_MESSAGE_TYPE.LOCATION:
                                cmdLocation.Parameters["@IMEI"].Value = ((WriteDBMessageLocation)row).IMEI;
                                cmdLocation.Parameters["@TrackTime"].Value = ((WriteDBMessageLocation)row).trackTime;
                                cmdLocation.Parameters["@currTime"].Value = ((WriteDBMessageLocation)row).currTime;

                                number = BitConverter.ToUInt32(((WriteDBMessageLocation)row).longitude.Reverse().ToArray(), 0);
                                lon = (180 * number) / 324000000.0;

                                degrees = (int)lon;
                                minutes = 60 * (lon - degrees);
                                longStr = string.Format("{0}º{1}{2}", degrees, minutes, (((WriteDBMessageLocation)row).courseStatus[0] & 0x08) == 0 ? "E" : "W");

                                cmdLocation.Parameters["@Longitude"].Value = longStr;

                                number = BitConverter.ToUInt32(((WriteDBMessageLocation)row).lattitude.Reverse().ToArray(), 0);
                                lat = (90 * number) / 162000000.0;

                                degrees = (int)lat;
                                minutes = 60 * (lat - degrees);
                                latStr = string.Format("{0}º{1}{2}", degrees, minutes, (((WriteDBMessageLocation)row).courseStatus[0] & 0x04) == 0 ? "S" : "N");

                                cmdLocation.Parameters["@Lattitude"].Value = latStr;
                                cmdLocation.Parameters["@speed"].Value = ((WriteDBMessageLocation)row).speed;
                                rowsAdded = cmdLocation.ExecuteNonQuery();
                                break;
                        }
                    }
                }
                catch (Exception ex)
                {
                    //Console.WriteLine("Error : '{0}'", ex.Message);
                }
                timer.Enabled = true;
            }
        }

        public void StartListening(string IP, int port, Boolean test)
        {
            try
            {
                // Establish the local endpoint for the socket.
                // The DNS name of the computer
                // running the listener is "host.contoso.com".
                IPHostEntry ipHostInfo = Dns.GetHostEntry(IP);  //Dns.Resolve(Dns.GetHostName());
                IPAddress ipAddress = ipHostInfo.AddressList[0];
                //IPAddress local = IPAddress.Parse(IP);

                IPEndPoint localEndPoint = null;
                if (test)
                {
                    localEndPoint = new IPEndPoint(IPAddress.Any, port);
                }
                else
                {
                    localEndPoint = new IPEndPoint(ipAddress, port);
                }

                // Create a TCP/IP socket.
                Socket listener = new Socket(AddressFamily.InterNetwork,
                    SocketType.Stream, ProtocolType.Tcp);
                // Bind the socket to the local endpoint and listen for incoming connections.


                allDone.Reset();
                acceptDone.Reset();
                listener.Bind(localEndPoint);
                listener.Listen(100);

                //login code, wait for 1st message
                Console.WriteLine("Wait 5 seconds for login message");

                listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
like image 60
jdweng Avatar answered Oct 26 '25 05:10

jdweng



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!