/// <summary> /// Continue get Hart-IP Response from the connected stream. /// Remove the received request from the list and release the /// MsgResponse lock signal. /// </summary> private void ReceiveMsg() { bool stoploop; lock (SyncRoot) { stoploop = m_bStopped; } while (!stoploop) { try { HartIPResponse Rsp = GetResponse(); if (Rsp == null) { continue; } m_lLastActivityTime = DateTime.Now.Ticks; if (Rsp.MessageType == HARTIPMessage.HART_ACK) { MsgRequest Req = DequeueRequest(Rsp.TransactionId); if (Req != null) { Req.Response.SetResponse(Rsp); } else { // just in case can't find the request in the list LogMsg.Instance.Log(Rsp.ToString()); } } else { if ((Rsp.MessageType == HARTIPMessage.HART_PUBLISH_NOTIFY) && (PublishedCmdNotify != null)) { HartIPResponseArg Arg = new HartIPResponseArg(Rsp); PublishedCmdNotify(this, Arg); } else { LogMsg.Instance.Log(Rsp.ToString()); } } } catch (SocketException se) { int nErrorCode = se.ErrorCode; // socket receive timeout if ((nErrorCode == 10060) || (nErrorCode == 10035)) { if (m_nConnection != UDP) { break; } } // socket closed, server close the connection or interrupted else if ((nErrorCode == 995) || (nErrorCode == 10004) || (nErrorCode == 10054)) { break; } else { LogMsg.Instance.Log("Error, ReceiveMsg SocketException: ErrorCode:" + nErrorCode + ". " + se.Message, true); break; } } catch (EndOfStreamException e) { LogMsg.Instance.Log("Error, ReceiveMsg EndOfStreamException: " + e.Message, true); break; } catch (IOException io) { if (m_nConnection != TCP) { LogMsg.Instance.Log("Error, ReceiveMsg IOException: " + io.Message, true); break; } } catch (ObjectDisposedException obex) { LogMsg.Instance.Log("Error, ReceiveMsg Expection :" + obex.Message, true); break; } catch (ThreadStateException tsEx) { // caller failed to release the lock signal and it will timeout LogMsg.Instance.Log("Error, ReceiveMsg ThreadStateException: " + tsEx.Message, true); } } ClearRequests(); }
/// <summary> /// Send a Hart Request and it handles Delay Retry. /// If no more dr retry, it sends nerwork HART device a flush Dr cmd. /// </summary> /// <param name="Request"><see cref="HartIPRequest"/></param> /// <returns><see cref="HartIPResponse"/></returns> public HartIPResponse SendHartRequest(HartIPRequest Request) { HartIPResponse Rsp = null; if (Request == null) { throw new ArgumentException("HartIPRequest is null"); } if ((m_HartIPConn == null) || !m_HartIPConn.IsConnected) { throw new Exception("Call Connect to initialize the network connection first."); } lock (SyncRoot) { m_Error = String.Empty; // send the first request Rsp = SendRequest(Request); if (Rsp != null) { Logger.Log(Rsp.ToString()); } if ((Rsp != null) && ((Rsp.ResponseCode == HARTIPMessage.RSP_DR_INITIATE) || (Rsp.ResponseCode == HARTIPMessage.RSP_DR_CONFLICT) || (Rsp.ResponseCode == HARTIPMessage.RSP_DR_RUNNING) || (Rsp.ResponseCode == HARTIPMessage.RSP_DEVICE_BUSY))) { if (m_nDrRetries > 0) { Rsp = null; // Create a request task to store the request and retries values. RequestTask ReqTask = new RequestTask(Request, m_nDrRetries, m_nDrRetryDelay); // Create a request worker to do the task with the callback to handles the retries. RequestWorker ReqWorker = new RequestWorker(ReqTask, new RequestWorker.HandleSendRequestDelegate(HandleSendHARTIPRequest)); try { // start the task ReqWorker.Perform(); Rsp = ReqTask.HartIPRsp; } catch (UserCancelException) { // user canceled action m_Error = "User canceled sending retries command."; } } else { SendFlushDrCmd(); } } } // if (Rsp.Command == 77) // { // unwrap the HART PDU in the response data // Rsp // } return(Rsp); }
/// <summary> /// Initiate session with the network HART-IP device. /// </summary> /// <returns>bool</returns> private bool InitSession() { bool bSuccess = false; HartIPResponse Response = null; do { // create init session request HartIPRequest Request = HartIPRequest.InitiateSession(TransactionId, m_InactivityCloseTime); if (!SendHartIPRequest(Request)) { LogMsg.Instance.Log("Error, sending InitSession request failure.", true); Close(); break; } try { Response = GetResponse(); } catch (SocketException se) { m_Error = String.Format("InitSession SocketException: ErrorCode:{0}. {1}.", se.ErrorCode, se.Message); LogMsg.Instance.Log("Error, " + m_Error, true); Close(); break; } catch (Exception ex) { m_Error = String.Format("InitSession Exception: {0}", ex.Message); LogMsg.Instance.Log("Error, " + m_Error, true); Close(); break; } if (Response == null) { m_Error = "Initiate Session failed getting response."; LogMsg.Instance.Log("Error, " + m_Error, true); Close(); break; } else if (0 != Response.ResponseCode) { m_Error = "InitSession received an error response code: " + Response.ResponseCode.ToString() + " " + GetSessionInitStatusCode(Response.ResponseCode); LogMsg.Instance.Log("Error, " + m_Error, true); LogMsg.Instance.Log(Response.ToString()); Close(); break; } else if (!Response.IsValidResponse) { m_Error = "InitSession received an invalid response Msg Type."; LogMsg.Instance.Log("Error, " + m_Error, true); LogMsg.Instance.Log(Response.ToString()); Close(); break; } LogMsg.Instance.Log(Response.ToString()); bSuccess = (Response.Status == HARTIPMessage.RSP_SUCCESS || Response.Status == HARTIPMessage.RSP_SET_TO_NEAREST_POSSIBLE_VALUE) ? true : false; } while (false); /* ONCE */ return(bSuccess); }
/// <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); }