コード例 #1
0
        /// <summary>
        /// Send short frame command 0 to discover the HART Device that is
        /// connected to the network.
        /// </summary>
        /// <returns><see cref="HartDevice"/></returns>
        private HartDevice DiscoverHartDevice(byte polladdr)
        {
            HartIPResponse Rsp = null;

            byte[]     Params = new byte[5];
            HartDevice Dev    = null;

            // short frame
            Params[0] = 0x02;
            // Device's polling address in short frame
            Params[1] = (byte)((polladdr & 0x3F) | 0x80);
            // cmd 0
            Params[2] = HARTIPMessage.CMD_READ_UID;
            // byte count is zero
            Params[3] = 0x00;
            // get check sum byte
            Params[4] = HartUtil.GetCheckSum(Params, 4);

            Rsp = SendHartRequest(Params, 5, HARTIPConnect.IO_SOCKET_TIMEOUT);
            if (Rsp != null)
            {
                try
                {
                    Dev = HartUtil.CreateHartDevice(Rsp, null);
                }
                catch (Exception e)
                {
                    m_Error = "DiscoverHartDevice Exception: " + e.Message;
                    Logger.Log(m_Error, true);
                }
            }

            return(Dev);
        }
コード例 #2
0
        /// <summary>
        /// Add a request or response message string
        /// </summary>
        /// <param name="Msg">string a message to add</param>
        /// <param name="bRequest">bool true is added to request message</param>
        /// <param name="bAddTimeStamp">bool true is added a timestamp in front of the specified string</param>
        public void AddMessage(string Msg, bool bRequest, bool bAddTimeStamp)
        {
            string Output = string.Empty;

            if (bAddTimeStamp)
            {
                Output = string.Format("{0} {1}", HartUtil.GetTimeStamp(), Msg);
            }
            else
            {
                Output = Msg;
            }

            if (bRequest)
            {
                if (m_Request.Length > 0)
                {
                    m_Request += "\r\n";
                }

                m_Request += Output;
            }
            else
            {
                if (m_Response.Length > 0)
                {
                    m_Response += "\r\n";
                }

                m_Response += Output;
            }
        }
コード例 #3
0
        /// <summary>
        /// Receive a HART-IP Response from the network connection.
        /// </summary>
        /// <returns><see cref="HartIPResponse"/></returns>
        protected override HartIPResponse GetResponse()
        {
            HartIPResponse Rsp      = null;
            BinaryReader   breader  = null;
            MemoryStream   inStream = null;

            do
            {
                if (m_socket == null)
                {
                    break;
                }

                try
                {
                    byte[]     RspMsg       = new byte[HARTIPMessage.MAX_HARTMSG_LENGTH];
                    int        nRecvLen     = 0;
                    IPEndPoint sender       = new IPEndPoint(/*m_HostIp*/ IPAddress.Any, 0);
                    EndPoint   senderRemote = (EndPoint)sender;
                    nRecvLen = m_socket.ReceiveFrom(RspMsg, ref senderRemote);
                    if (nRecvLen == 0)
                    {
                        break;
                    }

                    String TimeStamp = HartUtil.GetTimeStamp();
                    inStream = new System.IO.MemoryStream(RspMsg);
                    breader  = new System.IO.BinaryReader(inStream);
                    // set position to the beginning of the stream
                    breader.BaseStream.Position = 0;

                    int nRecvPort = ((IPEndPoint)senderRemote).Port;
                    if (m_nSendPort != nRecvPort)
                    {
                        m_nSendPort = ((IPEndPoint)senderRemote).Port;
                    }

                    Rsp = new HartIPResponse(breader, TimeStamp);
                }
                finally
                {
                    if (breader != null)
                    {
                        breader.Close();
                    }
                    if (inStream != null)
                    {
                        inStream.Close();
                        inStream.Dispose();
                    }
                }
            } while (false);

            return(Rsp);
        }
コード例 #4
0
        /// <summary>
        /// Send a Hart Request
        /// </summary>
        /// <param name="usDeviveType">ushort</param>
        /// <param name="nDeviceId">uint</param>
        /// <param name="cCmd">byte</param>
        /// <returns><see cref="HartIPResponse"/></returns>
        /// <remarks>It will create long frame, device type, device id,
        /// cmd and checksum bytes array for the request command.</remarks>
        private HartIPResponse SendHartRequest(ushort usDeviveType, uint nDeviceId,
                                               byte cCmd)
        {
            byte[] Params = new byte[9];

            // Create request cmd
            Params[0] = 0x82; // long frame
            Params[1] = (byte)(((usDeviveType >> 8) & 0x3F) | 0x80);
            Params[2] = (byte)(usDeviveType & 0x0ff);
            Params[3] = (byte)((nDeviceId >> 16) & 0x0ff);
            Params[4] = (byte)((nDeviceId >> 8) & 0x0ff);
            Params[5] = (byte)(nDeviceId & 0x0ff);
            Params[6] = cCmd;                            // cmd byte
            Params[7] = 0x00;                            // byte count
            Params[8] = HartUtil.GetCheckSum(Params, 8); // get check sum byte

            return(SendHartRequest(Params, 9));
        }
コード例 #5
0
        /// <summary>
        /// Send a Hart request to connected network HART-IP device.
        /// </summary>
        /// <param name="Request"><see cref="HartIPRequest"/></param>
        /// <returns>bool True if it is success to send the HART request.</returns>
        protected override bool SendRequest(HartIPRequest Request)
        {
            bool   bSuccess  = false;
            String TimeStamp = HartUtil.GetTimeStamp();

            if (m_socket != null)
            {
                m_socket.Send(Request.Message);
                Request.TimeStamp = TimeStamp;
                bSuccess          = true;
            }
            else
            {
                m_Error = "SendRequest Error: Socket is already closed.";
                LogMsg.Instance.Log("Error, Socket is already closed in SendRequest.", true);
            }

            return(bSuccess);
        }
コード例 #6
0
        /// <summary>
        /// Write message in debug console and/or write into a file.
        /// </summary>
        /// <param name="msg">String message to write</param>
        /// <param name="bAddTimeStamp">bool true to add timestamp in front of message</param>
        /// <param name="bAddEmptyLine">bool true to add empty line after the message</param>
        /// <remark>It will write a message to debug console console screen,
        /// and/or write to log file.</remark>
        public void Log(String msg, bool bAddTimeStamp, bool bAddEmptyLine)
        {
            do
            {
                lock (SyncRoot)
                {
                    String strOutput;

                    if (bAddTimeStamp)
                    {
                        String TimeStamp = HartUtil.GetTimeStamp();
                        strOutput = String.Format("{0}, {1}", TimeStamp, msg);
                    }
                    else
                    {
                        strOutput = msg;
                    }

                    // Check if display output string to screen
                    if (m_bOutputToScreen)
                    {
                        Console.WriteLine(strOutput);
                        Console.WriteLine();
                    }

                    if (m_bLogToFile)
                    {
                        if (m_Count >= m_Limit)
                        {
                            AddTimeStampInFileName();
                            m_Count = 0;
                        }
                        WriteMsgToFile(m_strFileName, strOutput, bAddEmptyLine);
                        m_Count++;
                    }
                    else
                    {
                        System.Diagnostics.Debug.WriteLine(strOutput);
                    }
                }
            } while (false); /* ONCE */
        }
コード例 #7
0
        /// <summary>
        /// Get the network HART Device IO info.
        /// </summary>
        /// <param name="Dev"><see cref="HartDevice"/></param>
        /// <returns>bool returns true if success. Otherwise, false.</returns>
        private bool GetHartDeviceIO(HartDevice Dev)
        {
            byte   cCmd;
            ushort usNumOfDevices = 0;
            bool   bSuccess       = false;

            if (Dev != null)
            {
                cCmd = (byte)((Dev.UniversalRev >= 7) ? HARTIPMessage.CMD_READ_IO_SYSTEM_CAPABILITIES :
                              HARTIPMessage.CMD_READ_HARTPORT_PARAMETERS);
                HartIPResponse Rsp = SendHartRequest(Dev.DeviceType, Dev.DeviceId, cCmd);
                if (Rsp != null)
                {
                    try
                    {
                        usNumOfDevices = HartUtil.GetHIPDeviceNumOfDevices(Rsp);
                        bSuccess       = true;
                    }
                    catch (Exception e)
                    {
                        m_Error = "GetHartDeviceIO Exception: " + e.Message;
                        Logger.Log(m_Error, true);
                    }

                    if (bSuccess && (usNumOfDevices > 0))
                    {
                        // Hart7 device cmd 74 rsp num of devices include HART-IP device itself.
                        if (Dev.UniversalRev >= 7)
                        {
                            Dev.NumOfSubDevices = (ushort)(usNumOfDevices - 1);
                        }
                        else
                        {
                            Dev.NumOfSubDevices = usNumOfDevices;
                        }
                    }
                }
            }

            return(bSuccess);
        }
コード例 #8
0
        /// <summary>
        /// Send 13 or 20 command to get HART device tag.
        /// </summary>
        /// <param name="usDeviceType">ushort</param>
        /// <param name="nDeviceId">uint</param>
        /// <param name="cCmd">byte</param>
        /// <returns>string device's Tag</returns>
        private string GetDeviceTag(ushort usDeviceType, uint nDeviceId, byte cCmd)
        {
            string         Tag = String.Empty;
            HartIPResponse Rsp = SendHartRequest(usDeviceType, nDeviceId, cCmd);

            if (Rsp != null)
            {
                try
                {
                    Tag = HartUtil.GetHARTDeviceTag(Rsp);
                    Tag = Tag.TrimEnd();
                }
                catch (Exception e)
                {
                    m_Error = "GetDeviceTag Exception: " + e.Message;
                    Logger.Log(m_Error, true);
                }
            }

            return(Tag);
        }
コード例 #9
0
        /// <summary>
        /// HartIPResponse
        /// </summary>
        /// <param name="inBuffer">BinaryReader</param>
        /// <param name="TimeStamp">String response timestamp</param>
        internal HartIPResponse(BinaryReader inBuffer, String TimeStamp)
            : base("Rx")
        {
            byte   Version, MsgType, MsgId, Status;
            ushort usMsgByteCount;

            Version = inBuffer.ReadByte();
            if (Version != HARTIPMessage.HART_UDP_TCP_MSG_VERSION)
            {
                throw new ArgumentException(String.Format("HartIPResponse Error: Unsupported Response Message Version: {0}.",
                                                          Version));
            }

            // If the input timestamp is null or empty, get the current time as timestamp
            if ((TimeStamp != null) && (TimeStamp.Length > 0))
            {
                m_TimeStamp = TimeStamp;
            }
            else
            {
                m_TimeStamp = HartUtil.GetTimeStamp();
            }

            MsgType = inBuffer.ReadByte();
            MsgId   = inBuffer.ReadByte();
            Status  = inBuffer.ReadByte();

            // Create message header
            MsgHeader = new HartIPMessageHeader(MsgType, (MessageId)MsgId, Status);
            // transaction id
            m_TransactionId = (ushort)IPAddress.NetworkToHostOrder((short)inBuffer.ReadUInt16());
            // byte count
            usMsgByteCount = (ushort)IPAddress.NetworkToHostOrder((short)inBuffer.ReadUInt16());
            // message body byte count
            m_HartCmdSize = (ushort)(usMsgByteCount - HARTIPMessage.HART_MSG_HEADER_SIZE);

            if (m_HartCmdSize > HARTIPMessage.MAX_HARTMSG_LENGTH)
            {
                m_HartCmdSize = HARTIPMessage.MAX_HARTMSG_LENGTH;
            }

            // get data bytes if message has data
            if (m_HartCmdSize > 0)
            {
                ushort usExtra;
                int    nIndex;
                int    j, i;

                // get the message bytes
                for (i = MsgHeader.ByteCount, j = 0; i < usMsgByteCount; i++, j++)
                {
                    m_HartCmd[j] = inBuffer.ReadByte();
                }

                // if the message is the ACK or BACK (notify) type
                if (MsgType == HARTIPMessage.HART_ACK || MsgType == HARTIPMessage.HART_PUBLISH_NOTIFY)
                {
                    // Check if response is initiate session
                    if (MsgHeader.MsgId == MessageId.SESSION_INITIATE)
                    {
                        nIndex       = 0;
                        m_cDataCount = (byte)m_HartCmdSize;
                        m_cRspcode   = MsgHeader.Status;
                    }
                    // Check if it is a long frame
                    else if ((m_HartCmd[0] & 0x80) == 0x80)
                    {
                        // get the extra
                        usExtra      = (ushort)((m_HartCmd[0] & 0x60) >> 5);
                        nIndex       = 6 + usExtra;
                        m_cCmd       = m_HartCmd[nIndex++];
                        m_cDataCount = m_HartCmd[nIndex++];
                        // subtract response code and device status bytes
                        m_cDataCount -= 2;
                        // get respsone code and device status bytes
                        m_cRspcode      = m_HartCmd[nIndex++];
                        m_cDeviceStatus = m_HartCmd[nIndex++];
                    }
                    else
                    {
                        // it is a short frame
                        nIndex          = 2;
                        m_cCmd          = m_HartCmd[nIndex++];
                        m_cDataCount    = m_HartCmd[nIndex++];
                        m_cRspcode      = m_HartCmd[nIndex++];
                        m_cDeviceStatus = m_HartCmd[nIndex++];
                        // subtract response code and device status bytes
                        m_cDataCount -= 2;
                    }

                    // Get the rest of response data bytes and store them in the data array
                    m_Data = new byte[m_cDataCount];
                    for (i = nIndex, j = 0; j < m_cDataCount; i++, j++)
                    {
                        m_Data[j] = m_HartCmd[i];
                    }
                }
            }
            else
            {
                m_cRspcode = MsgHeader.Status;
            }
        }
コード例 #10
0
        /// <summary>
        /// Build a HartIP Request using the specified request command, request message,
        /// device type, and device id. It will have frame, device address, command, byte count,
        /// data, and checksum bytes in the returned HartIPRequest.Command.
        /// </summary>
        /// <param name="usReqCmd">ushort Request command</param>
        /// <param name="ReqMsg">String Request message in Hex string</param>
        /// <param name="usDeviceType">ushort Device Type</param>
        /// <param name="nDeviceId">uint Device ID</param>
        /// <returns><see cref="HartIPRequest"/></returns>
        public HartIPRequest BuildHartIPRequest(ushort usReqCmd, String ReqMsg, ushort usDeviceType,
                                                uint nDeviceId)
        {
            String        Msg;
            HartIPRequest HRequest = null;
            int           nDataLen = 0;

            if (m_HartIPConn == null)
            {
                throw new Exception("Call Connect to initialize the network connection first.");
            }

            if ((uint)(usReqCmd) > 65536)
            {
                Msg = "Invalid HARTIP Request Command.";
                throw new ArgumentException(Msg);
            }

            if (!String.IsNullOrEmpty(ReqMsg))
            {
                ReqMsg   = ReqMsg.Replace(" ", "");
                nDataLen = ReqMsg.Length;
                if ((nDataLen > 0) && (nDataLen % 2) != 0)
                {
                    Msg = "Multiple contiguous bytes must define an even number of hex digits.";
                    throw new ArgumentException(Msg);
                }
            }

            // Check if it is extended command
            bool bExtendedCmd   = (usReqCmd > HARTIPMessage.MAX_SINGLE_BYTE_CMD) ? true : false;
            byte cCmd           = (byte)(bExtendedCmd ? HARTIPMessage.CMD_EXTENDED_CMD : usReqCmd);
            byte cbyteCount     = 9;
            byte cDataByteCount = 0;
            int  nIndex         = 0;
            int  nSubCmdByteCountIndex;

            // Request bytes
            byte[] Data = new byte[HARTIPMessage.MAX_REQUEST_MSG_LEN];
            Array.Clear(Data, 0, Data.Length);

            if (nDataLen > 0)
            {
                cbyteCount    += (byte)(nDataLen / 2);
                cDataByteCount = (byte)(nDataLen / 2);
            }

            // form a request
            Data[nIndex++]        = 0x82; // long frame
            Data[nIndex++]        = (byte)(((usDeviceType >> 8) & 0x3F) | 0x80);
            Data[nIndex++]        = (byte)(usDeviceType & 0x0ff);
            Data[nIndex++]        = (byte)((nDeviceId >> 16) & 0x0ff);
            Data[nIndex++]        = (byte)((nDeviceId >> 8) & 0x0ff);
            Data[nIndex++]        = (byte)(nDeviceId & 0x0ff);
            Data[nIndex++]        = cCmd; // cmd
            nSubCmdByteCountIndex = nIndex;
            // skip the byte count
            nIndex += 1;

            // if it is extended cmd, put the cmd two bytes in data field first
            if (bExtendedCmd)
            {
                Data[nIndex++]  = (byte)((usReqCmd >> 8) & 0x0ff);
                Data[nIndex++]  = (byte)(usReqCmd & 0x0ff);
                cbyteCount     += 2;
                cDataByteCount += 2;
            }

            // set the data byte count value
            Data[nSubCmdByteCountIndex] = cDataByteCount;

            int  n = 0;
            byte cY, cW;

            while (n < nDataLen)
            {
                if (HartUtil.HexCharToNibble(ReqMsg[n], out cY))
                {
                    if (HartUtil.HexCharToNibble(ReqMsg[n + 1], out cW))
                    {
                        Data[nIndex++] = (byte)(cY * 16 + cW);
                        n += 2;
                    }
                    else
                    {
                        Msg = String.Format("The character: '{0}' is not allowed in the request data byte value.",
                                            ReqMsg[n + 1]);
                        throw new ArgumentException(Msg);
                    }
                }
                else
                {
                    Msg = String.Format("The character: '{0}' is not allowed in the request data byte value.",
                                        ReqMsg[n]);
                    throw new ArgumentException(Msg);
                }
            }

            // tunnel messages to attached devices
            if (RootDevice.DeviceType != usDeviceType && RootDevice.DeviceId != nDeviceId && RootDevice.IsBridgeDevice)
            { // message is routed into an attached device
                // wrap the message with command 77 to tunnel to attached device
                byte[] Data77 = new byte[HARTIPMessage.MAX_REQUEST_MSG_LEN];
                Array.Clear(Data77, 0, Data.Length);

                // command 77 request data
                HartDevice dev = FindDevice(nDeviceId);
                Data77[0] = dev.IOCard;
                Data77[1] = dev.Channel;
                Data77[2] = 5;  // transmit preamble count
                Array.Copy(Data, 0, Data77, 3, nIndex);
                nIndex += 3;

                // send the command 77 to the root device (a gateway or IO)
                string hex = BitConverter.ToString(Data77).Replace("-", string.Empty);
                hex = hex.Substring(0, nIndex * 2);
                return(BuildHartIPRequest(77, hex, RootDevice.DeviceType, RootDevice.DeviceId));
            }

            // Get check sum byte and send the request
            Data[nIndex] = HartUtil.GetCheckSum(Data, (byte)(cbyteCount - 1));
            HRequest     = HartIPRequest.HartCommandRequest(m_HartIPConn.TransactionId,
                                                            Data, cbyteCount);

            return(HRequest);
        }
コード例 #11
0
        /// <summary>
        /// Send HART device a command 84.
        /// </summary>
        /// <param name="Dev"><see cref="HartDevice"/></param>
        /// <param name="usDeviceIndex">ushort</param>
        /// <returns><see cref="HartDevice"/></returns>
        private HartDevice SendCmd84(HartDevice Dev, ushort usDeviceIndex)
        {
            HartDevice HDevice = null;
            ushort     usDeviceType;
            uint       nDeviceId;

            byte[]         Req = new byte[11];
            HartIPResponse Rsp = null;

            if (Dev != null)
            {
                usDeviceType = Dev.DeviceType;
                nDeviceId    = Dev.DeviceId;

                // send cmd to HART Device get the device list
                Req[0]  = 0x82; // long frame
                Req[1]  = (byte)(((usDeviceType >> 8) & 0x3F) | 0x80);
                Req[2]  = (byte)(usDeviceType & 0x0ff);
                Req[3]  = (byte)((nDeviceId >> 16) & 0x0ff);
                Req[4]  = (byte)((nDeviceId >> 8) & 0x0ff);
                Req[5]  = (byte)(nDeviceId & 0x0ff);
                Req[6]  = HARTIPMessage.CMD_READ_SUB_DEVICE_IDENTITY; // cmd byte
                Req[7]  = 2;                                          // byte count
                Req[8]  = (byte)((usDeviceIndex >> 8) & 0x0ff);
                Req[9]  = (byte)(usDeviceIndex & 0x0ff);
                Req[10] = HartUtil.GetCheckSum(Req, 10); // get check sum byte

                Rsp = SendHartRequest(Req, 11);
                if (Rsp != null)
                {
                    byte cDataCount = Rsp.DataCount;
                    if ((Rsp.ResponseCode != HARTIPMessage.RSP_SUCCESS) &&
                        (Rsp.Command != HARTIPMessage.CMD_READ_SUB_DEVICE_IDENTITY) ||
                        (cDataCount < 44))
                    {
                        m_Error = String.Format("{0} Received Cmd 84 invalid response from HART device.\r\n{1}",
                                                HartUtil.GetTimeStamp(), Rsp.ToString());
                        Logger.Log(m_Error);
                    }
                    else
                    {
                        byte   cIOCard, cChannel, cUniversalCmdRev;
                        byte[] Data = new byte[cDataCount];
                        Data = Rsp.Data;
                        int    nIndex = 2;
                        ushort usSubDeviceType;
                        uint   nSubDeviceId;
                        String Tag = String.Empty;

                        cIOCard  = Data[nIndex++];
                        cChannel = Data[nIndex++];
                        // skip the MfgId (2 bytes)
                        nIndex += 2;

                        // get the device type
                        usSubDeviceType = (ushort)((Data[nIndex] << 8) + (Data[nIndex + 1] & 0x0ff));
                        nIndex         += 2;

                        // get the device id
                        nSubDeviceId = (uint)((Data[nIndex] << 16) + (Data[nIndex + 1] << 8) +
                                              (Data[nIndex + 2] & 0x0ff));
                        nIndex += 3;

                        // get the universal cmd rev
                        cUniversalCmdRev = Data[nIndex++];

                        // get the tag
                        for (int i = nIndex; i < (nIndex + HARTIPMessage.MAX_LONG_TAG_LENGTH); i++)
                        {
                            char ch = (char)(Data[i] & 0x00ff);
                            if (ch == 0)
                            {
                                break;
                            }

                            Tag += ch;
                        }

                        Tag = Tag.TrimEnd();
                        // if tag is empty, set it to 'Unknown' with its device type and device id similar to MAC address
                        if (Tag.Length == 0)
                        {
                            String strOUI = (cUniversalCmdRev >= 7) ? "00-1B-1E" : "00-00-00";

                            Tag = String.Format("Unknown ({0}-{1:X2}-{2:X2}-{3:X2}-{4:X2}-{5:X2})",
                                                new object[] { strOUI,
                                                               (usSubDeviceType >> 8),
                                                               (usSubDeviceType & 0x0ff),
                                                               (nSubDeviceId >> 16 & 0x0ff),
                                                               (nSubDeviceId >> 8 & 0x0ff),
                                                               (nSubDeviceId & 0x0ff) });
                        }

                        // Create sub-device
                        HDevice         = new HartDevice(usSubDeviceType, nSubDeviceId, cUniversalCmdRev, Dev);
                        HDevice.Name    = Tag;
                        HDevice.IOCard  = cIOCard;
                        HDevice.Channel = cChannel;
                    }
                }
            }

            return(HDevice);
        }