zwavers232.cs

来自「zwave 无线通讯协议 PC controller 控制器源码」· CS 代码 · 共 868 行 · 第 1/3 页

CS
868
字号
//////////////////////////////////////////////////////////////////////////////////////////////// 
//
//          #######
//          #   ##    ####   #####    #####  ##  ##   #####
//             ##    ##  ##  ##  ##  ##      ##  ##  ##
//            ##  #  ######  ##  ##   ####   ##  ##   ####
//           ##  ##  ##      ##  ##      ##   #####      ##
//          #######   ####   ##  ##  #####       ##  #####
//                                           #####
//          Z-Wave, the wireless language.
//
//          Copyright Zensys A/S, 2005
//
//          All Rights Reserved
//
//          Description:   
//
//          Author:   Morten Damsgaard, Linkage A/S
//
//          Last Changed By:  $Author: jrm $
//          Revision:         $Revision: 1.6 $
//          Last Changed:     $Date: 2007/01/24 10:24:41 $
//
//////////////////////////////////////////////////////////////////////////////////////////////
#region Using directives

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
using System.Globalization;
#endregion

namespace Zensys.ZWave.Communication
{
      /// <summary>
      /// 
      /// </summary>
      public class ZWaveRS232 : ITransportLayer , IDisposable
      {
        private CommAPI comm;
        private TransportStatistics stats;
        private IntPtr txOverlapped = IntPtr.Zero;
        private IntPtr rxOverlapped = IntPtr.Zero;
        private bool isOpen;
        private IntPtr unmanagedResource;
        private bool disposed = false;

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    // Release managed resources.
                }

                // Free the unmanaged resource ...

                unmanagedResource = IntPtr.Zero;
                disposed = true;
            }
        }
 

        /// <summary>
        /// 
        /// </summary>
        /// <param name="connectionString"></param>
        public void Open(String connectionString)
        {
          string port = "COM1";
          uint baudRate = 9600;

          string[] con = connectionString.ToLower(CultureInfo.CurrentCulture).Split(';');

          for (int i = 0; i < con.Length; i++)
          {
            int idx = con[i].LastIndexOf('=');
            string key = con[i].Substring(0, idx);
            string val = con[i].Substring(idx+1);

            switch(key)
            {
              case "port": port = val; break;
              case "baudrate": baudRate = Convert.ToUInt32(val,CultureInfo.InvariantCulture); break;
              default: break;
            }
          }

          // for Windows CE, ensure the port name is colon terminated "COMx:"
          if (!CommAPI.isFullFramework && !port.EndsWith(":")) port += ":";

          Open(port, baudRate);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="port"></param>
        /// <param name="baudrate"></param>
        public void Open(String port, uint baudRate)
        {
          isOpen = true;
          comm = CommAPI.getCommAPI();

          // Open the serial port.
          if (!comm.CreateFile("\\\\.\\"+port))
            throw new ITransportLayerException("CreateFile failed: err: " + Marshal.GetLastWin32Error() + "Port: " + port);

          // Get the default port setting information.
          DCB dcb = new DCB();
          if( !comm.GetCommState(dcb) )
            throw new ITransportLayerException("GetCommState failed: err: " + Marshal.GetLastWin32Error());

          // Change the DCB structure settings.
          dcb.BaudRate      = baudRate;          // Current baud 
          dcb.fBinary       = true;             // Binary mode; no EOF check 
          dcb.fParity       = false;             // Disable parity checking 
          dcb.fOutxCtsFlow  = false;            // No CTS output flow control 
          dcb.fOutxDsrFlow  = false;            // No DSR output flow control 
          dcb.fDtrControl   = (byte)CommAPI.DTRControlFlows.ENABLE; 
          // DTR flow control type 
          dcb.fDsrSensitivity   = false;        // DSR sensitivity 
          dcb.fTXContinueOnXoff = true;         // XOFF continues Tx 
          dcb.fOutX             = false;        // No XON/XOFF out flow control 
          dcb.fInX              = false;        // No XON/XOFF in flow control 
          dcb.fErrorChar        = false;        // Disable error replacement 
          dcb.fNull             = false;        // Disable null stripping 
          dcb.fRtsControl       = (byte)CommAPI.RTSControlFlows.DISABLE;  // RTS flow control disabled
          dcb.fAbortOnError     = false;        // Do not abort reads/writes on 
          // error
          dcb.ByteSize          = 8;        // Number of bits/byte, 4-8 
          dcb.Parity            = 0;        // 0-4=no,odd,even,mark,space 
          dcb.StopBits          = 0;        // 0,1,2 = 1, 1.5, 2 

          // Configure the port according to the specifications of the DCB structure.
          if( !comm.SetCommState(dcb) )
            throw new ITransportLayerException("SetCommState failed: err: " + Marshal.GetLastWin32Error());

          // MDA - test
          // ReadIntervalTimeout 
          //   Specifies the maximum acceptable time, in milliseconds, to elapse 
          //   between the arrival of two characters on the communication line. 
          //   In Windows CE, during a ReadFile operation, the time period begins 
          //   immediately. If the interval between the arrivals of two characters 
          //   exceeds the time amount specified in ReadIntervalTimeout, the 
          //   ReadFile operation is completed and buffered data is returned. 
          //   A value of zero indicates that interval timeouts are not used. 
          // ReadTotalTimeoutMultiplier 
          //   Specifies the multiplier, in milliseconds, used to calculate the 
          //   total timeout period for read operations. 
          //   For each read operation, this value is multiplied by the requested 
          //   number of bytes to be read. 
          // ReadTotalTimeoutConstant 
          //   Specifies the constant, in milliseconds, used to calculate the total 
          //   timeout period for read operations. 
          //   For each read operation, this value is added to the product of the 
          //   ReadTotalTimeoutMultiplier member and the requested number of bytes. 
          //   A value of zero for the ReadTotalTimeoutMultiplier and 
          //   ReadTotalTimeoutConstant members indicates that total timeouts are 
          //   not used for read operations. 
          // WriteTotalTimeoutMultiplier 
          //   Specifies the multiplier, in milliseconds, used to calculate the 
          //   total timeout period for write operations. 
          //   For each write operation, this value is multiplied by the number 
          //   of bytes to be written. 
          // WriteTotalTimeoutConstant 
          //   Specifies the constant, in milliseconds, used to calculate the total 
          //   timeout period for write operations. 
          //   For each write operation, this value is added to the product of the 
          //   WriteTotalTimeoutMultiplier member and the number of bytes to be written. 
          //   A value of zero for the WriteTotalTimeoutMultiplier and 
          //   WriteTotalTimeoutConstant members indicates that total timeouts are 
          //   not used for write operations. 
          // read delay = ReadTotalTimeoutConstant + ReadTotalTimeoutMultiplier x "bytes read"
          // causes read operations to complete immediately without 
          // waiting for any new data to arrive
          CommAPI.CommTimeouts timeouts = new CommAPI.CommTimeouts();
          timeouts.ReadIntervalTimeout = UInt32.MaxValue;
          timeouts.ReadTotalTimeoutMultiplier = 0;
          timeouts.ReadTotalTimeoutConstant = 0;
          timeouts.WriteTotalTimeoutMultiplier = 0;
          timeouts.WriteTotalTimeoutConstant = 0; 
          if( !comm.SetCommTimeouts(timeouts) )
            throw new ITransportLayerException("SetCommTimeouts failed: err: " + Marshal.GetLastWin32Error());

          if( !comm.SetCommMask(CommAPI.CommEventFlags.RXCHAR) ) // rx
            throw new ITransportLayerException("SetCommMask failed: err: " + Marshal.GetLastWin32Error());

          stats = new TransportStatistics();

          if (CommAPI.isFullFramework)
          {
            // set up the overlapped tx IO
            CommAPI.OVERLAPPED tx = new CommAPI.OVERLAPPED();
            txOverlapped = CommAPI.LocalAlloc(0x40, Marshal.SizeOf(tx));
            tx.Offset = 0;
            tx.OffsetHigh = 0;
            tx.hEvent = comm.CreateEvent(true, false, "tx");
            Marshal.StructureToPtr(tx, txOverlapped, true);

            // set up the overlapped rx IO
            CommAPI.OVERLAPPED rx = new CommAPI.OVERLAPPED();
            rxOverlapped = CommAPI.LocalAlloc(0x40, Marshal.SizeOf(rx));
            rx.Offset = 0;
            rx.OffsetHigh = 0;
            rx.hEvent = comm.CreateEvent(true, false, "rx");
            Marshal.StructureToPtr(rx, rxOverlapped, true);
          }
        }

        /// <summary>
        /// 
        /// </summary>
        public void Close()
        {
          isOpen = false;
          comm.Close();

          if (txOverlapped != IntPtr.Zero)
          {
            CommAPI.LocalFree(txOverlapped);
            txOverlapped = IntPtr.Zero;
          }

          if (rxOverlapped != IntPtr.Zero)
          {
            CommAPI.LocalFree(rxOverlapped);
            rxOverlapped = IntPtr.Zero;
          }
        }
      

        /// <summary>
        /// 
        /// </summary>
        public void Purge()
        {
          if( comm.PurgeComm(CommAPI.PurgeFlags.PURGE_RXCLEAR | CommAPI.PurgeFlags.PURGE_TXCLEAR) )
            throw new ITransportLayerException("PurgeComm failed: err: " + Marshal.GetLastWin32Error());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public int Read(byte[] buffer)
        {
          int bytesRead = 0;
          CommAPI.CommEventFlags eventFlags = new CommAPI.CommEventFlags();
          bool waitEvent = false;
          while (bytesRead == 0 && this.isOpen)
          {
            waitEvent = comm.WaitCommEvent(ref eventFlags);
            if (waitEvent && (eventFlags & CommAPI.CommEventFlags.RXCHAR) != 0)
              bytesRead = ReadFile(buffer);

            if (!comm.IsValid() )
              throw new ITransportLayerException("Handle invalid: " + Marshal.GetLastWin32Error());
          }
          return bytesRead;
        }

        private int ReadFile(byte[] buffer)
        {
          int bytesRead = 0;
          if (!comm.ReadFile(buffer, buffer.Length, ref bytesRead, rxOverlapped))
          {
            if (!comm.IsValid() || Marshal.GetLastWin32Error() != (int)CommAPI.APIErrors.ERROR_IO_PENDING)
              throw new ITransportLayerException("ReadFile failed: err: " + Marshal.GetLastWin32Error());
            else
            {
              Debug.WriteLine("Overlapped read...");
              if (!comm.GetOverlappedResult(rxOverlapped, out bytesRead, true)) // false
                throw new ITransportLayerException("ReadFile failed: err: " + Marshal.GetLastWin32Error());
            }
          }

          lock (stats) { stats.ReceivedBytes += bytesRead; }
          return bytesRead;
        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?