コード例 #1
0
ファイル: Program.cs プロジェクト: CrossEyedHollow/M_Bus_Spy
        private static void InitializePorts()
        {
            foreach (DataRow dr in mySetting.Tables["tblSettings"].Rows)
            {
                //Get serial port settings
                int      id               = Convert.ToInt32(dr["fldID"]);
                string   threadName       = (string)dr["fldThread"];
                string   portName         = (string)dr["fldPortName"];
                int      baudRate         = Convert.ToInt32(dr["fldBaudRate"]);
                Parity   parity           = GetParity(dr["fldParity"]);
                int      dataBits         = Convert.ToInt32(dr["fldDataBits"]);
                StopBits stopbits         = GetStopBits(dr["fldStopBits"]);
                int      readTimeout      = Convert.ToInt32(dr["fldReadTimeout"]);
                bool     enabled          = Convertor.StringToBool((string)dr["fldEnabled"]);
                bool     transferCommands = Convertor.StringToBool((string)dr["fldTransferCommands"]);

                if (!enabled)
                {
                    continue;
                }
                SerialPortPlus serialPort = new SerialPortPlus(portName, id, baudRate, parity, dataBits, stopbits)
                {
                    ReadTimeout      = readTimeout,
                    TransferCommands = transferCommands
                };

                ports.Add(serialPort);

                //Initialize the serial port
                switch (threadName.ToLower())
                {
                case "master":
                {
                    Thread tr = new Thread(() => MasterThread(serialPort))
                    {
                        Name = $"Thread{id}_{threadName.ToLower()}"
                    };
                    threads.Add(tr);
                    break;
                }

                case "slave":
                {
                    Thread tr = new Thread(() => SlaveThread(serialPort))
                    {
                        Name = $"Thread{id}_{threadName.ToLower()}"
                    };
                    threads.Add(tr);
                    break;
                }

                default:
                    throw new NotImplementedException($"Bad input '{threadName}' for fldThread in Settings.xml");
                }
            }
        }
コード例 #2
0
ファイル: Program.cs プロジェクト: CrossEyedHollow/M_Bus_Spy
 private static void OpenPort(SerialPortPlus serialPort)
 {
     try
     {
         serialPort.Open();
     }
     catch (Exception ex)
     {
         Messenger.Enqueue($"Can't open {serialPort.PortName}:" + ex.Message);
     }
 }
コード例 #3
0
ファイル: Program.cs プロジェクト: CrossEyedHollow/M_Bus_Spy
 private static void ClosePort(SerialPortPlus serialPort)
 {
     try
     {
         Thread.Sleep(50);
         serialPort.Close();
         //Messenger.Enqueue(serialPort.PortName + " closed.");
     }
     catch (Exception ex)
     {
         Messenger.Enqueue($"Can't close {serialPort.PortName}:" + ex.Message);
     }
 }
コード例 #4
0
ファイル: Program.cs プロジェクト: CrossEyedHollow/M_Bus_Spy
        /// <summary>
        /// Finds and returns the first serialPort with TransferCommand field enabled
        /// </summary>
        /// <returns></returns>
        private static SerialPortPlus GetPlcPort()
        {
            SerialPortPlus output = null;

            foreach (SerialPortPlus port in ports)
            {
                if (port.TransferCommands == true)
                {
                    output = port;
                    break;
                }
            }
            return(output);
        }
コード例 #5
0
ファイル: Program.cs プロジェクト: CrossEyedHollow/M_Bus_Spy
        /// <summary>
        /// Gets the response message from the buffer and clears the buffer
        /// </summary>
        /// <param name="masterLength"></param>
        /// <param name="slaveLength"></param>
        /// <returns></returns>
        private static ResponseResult GetResponseMessage(SerialPortPlus serialPort, Telegram telegram, out byte[] result)
        {
            if (telegram.responseLength == 0)
            {
                Messenger.Enqueue(StandartMessages.TelegramSkiped(telegram));
                result = null;
                return(ResponseResult.Skiped);
            }

            //If the telegrams dictionary is filled, ask for it instead
            byte[] request = telegram.dictionary.Length > 1 ? telegram.dictionary : telegram.request;

            List <byte> buffer = GetRawResponse(serialPort, request);

            //If the first byte in the buffer is not 68 or E5, add 68  in front
            //if (!((buffer[0] == HexToByte("68")[0]) || (buffer[0] == HexToByte("E5")[0]))) buffer.Insert(0, HexToByte("68")[0]);

            if (buffer.Count == telegram.responseLength) //correct response
            {
                result = buffer.ToArray();
                //Check checksum
                if (Checksum.Check(result))
                {
                    //If the checksum is correct, proceed
                    Messenger.Enqueue(StandartMessages.SlaveResponded(serialPort, result, request));
                    return(ResponseResult.Correct);
                }
                else
                {
                    //Return bad checksum
                    Messenger.Enqueue(StandartMessages.BadChecksum(serialPort, telegram, buffer));
                    return(ResponseResult.Checksum_Error);
                }
            }
            else if (buffer.Count == 0) //no response
            {
                Messenger.Enqueue(StandartMessages.RequestTimeout(serialPort, telegram));
                result = null;
                return(ResponseResult.Timeout);
            }
            else //unexpected response
            {
                Messenger.Enqueue(StandartMessages.UnexpectedResponse(serialPort, telegram, buffer));
                result = buffer.ToArray();
                return(ResponseResult.Incorrect);
            }
        }
コード例 #6
0
ファイル: Program.cs プロジェクト: CrossEyedHollow/M_Bus_Spy
        private static List <byte> GetRawResponse(SerialPortPlus serialPort, byte[] request)
        {
            List <byte> output    = new List <byte>();
            Stopwatch   stopWatch = new Stopwatch();

            //Open port
            OpenPort(serialPort);

            //Send request and start timeout timer
            serialPort.DiscardInBuffer();
            stopWatch.Start();

            //Send request
            Respond(serialPort, request);

            //Get response
            while (stopWatch.Elapsed.TotalMilliseconds < serialPort.ReadTimeout)
            {
                if (serialPort.BytesToRead > 0)
                {
                    do
                    {
                        //Read and save everything from the buffer
                        byte[] receivedBytes = new byte[serialPort.BytesToRead];
                        serialPort.Read(receivedBytes, 0, serialPort.BytesToRead);

                        //Save the read bytes into the buffer
                        output.InsertRange(output.Count, receivedBytes);
                        Thread.Sleep(200);
                    } while ((serialPort.BytesToRead > 0) && (stopWatch.Elapsed.TotalMilliseconds < serialPort.ReadTimeout));
                    stopWatch.Stop();
                    break;
                }
                else
                {
                    Thread.Sleep(50);
                }
            }
            stopWatch.Stop();
            stopWatch = null;

            //Close port
            ClosePort(serialPort);

            return(output);
        }
コード例 #7
0
ファイル: Program.cs プロジェクト: CrossEyedHollow/M_Bus_Spy
        private static void MasterThread(SerialPortPlus serialPort)
        {
            while (MainThread.IsAlive)
            {
                try
                {
                    //For each telegram
                    for (int i = 0; i < telegrams.Count; i++)
                    {
                        Telegram telegram = telegrams[i];

                        //If the telegram does not belong to this port, skip
                        if (telegram.PortID != serialPort.ID)
                        {
                            continue;
                        }

                        //Get response
                        byte[]         response   = null;
                        ResponseResult arResponse = ResponseResult.Unindentified;

                        //Retry until response is correct
                        for (int k = 0; k < 8; k++)
                        {
                            try
                            {
                                lock (serialPort)
                                {
                                    arResponse = GetResponseMessage(serialPort, telegram, out response);
                                }

                                //If a correct response is received break the cycle
                                if (arResponse == ResponseResult.Correct)
                                {
                                    break;
                                }
                                //Sleep between tries
                                Thread.Sleep(TimeSpan.FromSeconds(sleepTime));
                            }
                            catch (Exception ex)
                            {
                                Messenger.Enqueue(ex.Message);
                            }
                        }

                        telegram.response = response;

                        //Sleep before sending next request
                        if (i < telegrams.Count - 1)
                        {
                            Thread.Sleep(TimeSpan.FromSeconds(sleepTime));
                        }
                    }

                    //Update the database
                    DBManager.UpdateDB(serialPort.ID);

                    //Sleep
                    Thread.Sleep(TimeSpan.FromSeconds(cycleTime));
                }
                catch (Exception ex)
                {
                    Messenger.Enqueue(ex.Message);
                }
            }
            ClosePort(serialPort);
        }
コード例 #8
0
ファイル: Program.cs プロジェクト: CrossEyedHollow/M_Bus_Spy
        private static void SlaveThread(SerialPortPlus serialPort)
        {
            List <byte> serialBuffer = new List <byte>();

            byte[] lastResponse = new byte[0];
            //Try to open the port
            OpenPort(serialPort);
            //If the port didnt open return
            if (!serialPort.IsOpen)
            {
                return;
            }
            //clear the buffer
            serialPort.DiscardInBuffer();

            //Messenger.Enqueue($"{Thread.CurrentThread.Name} status: {Thread.CurrentThread.IsAlive.ToString()}");
            while (MainThread.IsAlive)
            {
                try
                {
                    int bytesToRead = serialPort.BytesToRead;
                    //Wait for a full telegram
                    if (serialPort.BytesToRead > 0)
                    {
                        Thread.Sleep(100);
                        if (serialPort.BytesToRead > bytesToRead)
                        {
                            continue;
                        }
                        else
                        {
                            bytesToRead = serialPort.BytesToRead;
                        }
                    }
                    else
                    {
                        Thread.Sleep(250);
                        continue;
                    }

                    //Read and save everything from the buffer
                    byte[] receivedBytes = new byte[bytesToRead];
                    //Console.WriteLine($"Bytes to read: {receivedBytes.Length}");
                    serialPort.Read(receivedBytes, 0, bytesToRead);

                    //If the received message is just an echo, ignore it
                    if (echoCancellation && IsEcho(lastResponse, receivedBytes))
                    {
                        Messenger.Enqueue(StandartMessages.EchoIgnored(serialPort, receivedBytes));
                        continue;
                    }
                    //Save the read bytes into the buffer
                    serialBuffer.InsertRange(serialBuffer.Count, receivedBytes);

                    //If there are known telegrams to listen for, do so
                    if (telegrams.Count > 0)
                    {
                        //For each telegram in the list
                        for (int i = 0; i < telegrams.Count; i++)
                        {
                            Telegram telegram = telegrams[i];

                            //If a telegram is recognized
                            if (FindInBuffer(telegram.request, serialBuffer))
                            {
                                Respond(serialPort, telegram, ref lastResponse);

                                //If the telegram is of the default type clear the buffer,
                                //else keep the bytes and wait for next telegram
                                if (telegram.teleType != TeleType.Complex)
                                {
                                    serialBuffer.Clear();
                                }
                                break;
                            }
                            else if (i >= telegrams.Count - 1)
                            {
                                //Check if any of the master ports have TransferCommand enabled
                                SerialPortPlus sp;
                                if ((sp = GetPlcPort()) != null)
                                {
                                    lock (sp)
                                    {
                                        Messenger.Enqueue(StandartMessages.UnrecognizedTelegram(serialPort, serialBuffer) + $"...sending to {sp.PortName}");

                                        //Send the bytes to the port and get response
                                        List <byte> response    = GetRawResponse(sp, serialBuffer.ToArray());
                                        byte[]      arrResponse = response.ToArray();

                                        Messenger.Enqueue($"[{sp.PortName}]response is: [{Convertor.ByteToHex(arrResponse)}], transfering response to master...");

                                        //Send the responce back to the port that requested it
                                        Respond(serialPort, arrResponse);
                                        lastResponse = arrResponse;
                                        serialBuffer.Clear();
                                    }
                                }
                                else
                                {
                                    Messenger.Enqueue(StandartMessages.UnrecognizedTelegram(serialPort, serialBuffer));
                                    serialBuffer.Clear();
                                }
                            }
                        }
                    }
                    else //Sniff the port
                    {
                        Messenger.Enqueue(StandartMessages.CurrentBytes(serialPort, serialBuffer));
                        serialBuffer.Clear();
                    }

                    //Check connection
                    if (!serialPort.IsOpen)
                    {
                        Reconnect(serialPort);
                    }
                    //Sleep between readings
                    Thread.Sleep(250);
                }
                catch (Exception ex)
                {
                    Messenger.Enqueue(ex.Message);
                    serialBuffer.Clear();
                    serialPort.DiscardInBuffer();
                    Thread.Sleep(250);
                }
            }
            serialPort.Close();
        }