Wednesday, April 26, 2023

Get serial pin event and status(level) c#(ring, cts, dsr, rlsd)

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.IO.Ports;

using System.Reflection;

using System.Runtime.InteropServices;

using Microsoft.Win32.SafeHandles;


namespace SerialEventMonitor

{

    class Program

    {

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]

        static extern Boolean GetCommModemStatus(SafeFileHandle hFile, ref UInt32 Status);


        const UInt32 MS_CTS_ON = 0x0010;

        const UInt32 MS_DSR_ON = 0x0020;

        const UInt32 MS_RING_ON = 0x0040;

        const UInt32 MS_RLSD_ON = 0x0080;


        static void Main(string[] args)

        {


            Console.WriteLine( string.Join( ",",SerialPort.GetPortNames()));

            

            string com_port_name = Console.ReadLine();



            SerialPort port = new SerialPort(com_port_name.Trim(), 9600, Parity.None, 8, StopBits.One);

            port.PinChanged += PinChanged;

            

            port.Open();


            DateTime dt_Start = DateTime.MinValue;            

            while(true)

            {

                if( port.ReadExisting() == "q")

                    break;


                System.Threading.Thread.Sleep(1000);

            }

            port.Close();

            port.Dispose();

        }


        private static void PinChanged(object sender, SerialPinChangedEventArgs e)

        {

            SerialPort port = sender as SerialPort;


            Console.WriteLine( e.EventType.ToString());

            ShowPinStates(port);

        }

        static private void ShowPinStates(System.IO.Ports.SerialPort serialPort)

        {

            UInt32 Status = 0;

            Boolean CTS = false;

            Boolean DSR = false;

            Boolean DCD = false;

            Boolean RI = false;


            if (serialPort == null) return;

            if (serialPort.IsOpen)

            {

                object baseStream = serialPort.BaseStream;

                Type baseStreamType = baseStream.GetType();


                // Get the Win32 file handle for the port

                SafeFileHandle portFileHandle = (SafeFileHandle)baseStreamType.GetField("_handle", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(baseStream);


                if (GetCommModemStatus(portFileHandle, ref Status))

                {

                    CTS = ((Status & MS_CTS_ON) == MS_CTS_ON);

                    DSR = ((Status & MS_DSR_ON) == MS_DSR_ON);

                    DCD = ((Status & MS_RLSD_ON) == MS_RLSD_ON);

                    RI = ((Status & MS_RING_ON) == MS_RING_ON);


                    Console.WriteLine(RI);


                }

            }

        }

    }

}