/// <summary> /// Raises the APDU Received event /// </summary> /// <param name="apdu">The apdu that was received</param> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 05/21/13 RCG 2.80.32 N/A Created private void OnAPDUReceived(xDLMSAPDU apdu) { if (APDUReceived != null && apdu != null) { APDUReceived(this, new APDUEventArguments(apdu)); } }
/// <summary> /// Sends an APDU to the connected device /// </summary> /// <param name="apdu">The APDU to send</param> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 05/21/13 RCG 2.80.32 N/A Created public void SendAPDU(xDLMSAPDU apdu) { if (IsOpen && apdu != null) { WPDU Wrapper = new WPDU(ClientPort, ServerPort, apdu.Data); m_Logger.WriteLine(Logger.LoggingLevel.Detailed, "Sending APDU. Type: " + EnumDescriptionRetriever.RetrieveDescription(apdu.Tag)); Send(Wrapper.Data); } }
/// <summary> /// Parses the data for any APDU's /// </summary> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 02/04/12 RCG 2.70.63 N/A Created private void ParseAPDUData() { try { lock (m_HighLevelDataBuffer) { while (m_HighLevelDataBuffer.Count > 0) { // The first byte should be the APDU tag xDLMSAPDU NewAPDU = xDLMSAPDU.Create((xDLMSTags)m_HighLevelDataBuffer[0]); CipheredAPDU NewCipheredAPDU = NewAPDU as CipheredAPDU; if (NewAPDU != null) { // Set up the security settings for a Ciphered APDU if (NewCipheredAPDU != null) { if (CipheredAPDU.IsTagGlobalCipher(NewCipheredAPDU.Tag)) { NewCipheredAPDU.BlockCipherKey = GlobalEncryptionKey; } else if (CipheredAPDU.IsTagDedicatedCipher(NewCipheredAPDU.Tag)) { NewCipheredAPDU.BlockCipherKey = DedicatedEncryptionKey; } if (PendingDecryptAuthenticationKey != null) { NewCipheredAPDU.AuthenticationKey = PendingDecryptAuthenticationKey; } else { NewCipheredAPDU.AuthenticationKey = DecryptAuthenticationKey; } NewCipheredAPDU.ApTitle = ServerApTitle; m_LastFrameCounterReceived = NewCipheredAPDU.FrameCounter; } // We found a valid APDU tag so we can try to parse it. We already checked the first byte so just use the rest MemoryStream DataStream = new MemoryStream(m_HighLevelDataBuffer.ToArray()); NewAPDU.Parse(DataStream); // Remove the data that has been parsed m_HighLevelDataBuffer.RemoveRange(0, (int)DataStream.Position); m_Logger.WriteLine(Logger.LoggingLevel.Detailed, "APDU Received. Type: " + EnumDescriptionRetriever.RetrieveDescription(NewAPDU.Tag)); if (NewCipheredAPDU != null) { xDLMSAPDU UncipheredAPDU = null; if (PendingDecryptAuthenticationKey != null) { // We are in the middle of a key exchange so we could get a message using either the pending key or // the previous key. We need to attempt the Pending key first try { UncipheredAPDU = NewCipheredAPDU.UncipheredAPDU; } catch (Exception) { m_Logger.WriteLine(Logger.LoggingLevel.Detailed, "Unciphering failed using the Pending Authentication Key. Using previous key."); } if (UncipheredAPDU == null) { // Try it with the previous key NewCipheredAPDU.AuthenticationKey = DecryptAuthenticationKey; UncipheredAPDU = NewCipheredAPDU.UncipheredAPDU; } } else { UncipheredAPDU = NewCipheredAPDU.UncipheredAPDU; } // Send up the Unciphered APDU OnAPDUReceived(UncipheredAPDU); } else { OnAPDUReceived(NewAPDU); } } else { // The tag is not valid so lets get rid of the byte and move on m_HighLevelDataBuffer.RemoveAt(0); } } } } catch (Exception e) { // This most likely means that we don't have all of the data yet for a specific message // so do nothing and hope the rest of the data comes in soon. m_Logger.WriteLine(Logger.LoggingLevel.Detailed, "Exception while parsing an APDU. Waiting for more data. Message: " + e.Message); } }
/// <summary> /// Constructor /// </summary> /// <param name="apdu">The APDU for the event</param> // Revision History // MM/DD/YY who Version Issue# Description // -------- --- ------- ------ --------------------------------------- // 05/21/13 RCG 2.80.32 N/A Created public APDUEventArguments(xDLMSAPDU apdu) : base() { m_APDU = apdu; }