/// <summary> /// Handler for timers Elapsed event /// </summary> /// <param name="sender">Timer instance that triggered event</param> /// <param name="e">Arguments</param> private void TimeoutHandler(object sender, System.Timers.ElapsedEventArgs e) { if (Connected) { if (ActualState == ModbusAsciiLinkState.IDLE) { // Timeout occured but bus is idle (message processed) should not happen TimeoutCounter.Stop(); Debug.WriteLine("LINK - IDLE_TIMEOUT"); return; } if (ActualMessageId != TkickMessageId) { // Timeout occured but link is already handling another message - should not happen TimeoutCounter.Stop(); Debug.WriteLine("LINK - BUSY_TIMEOUT"); return; } // Timeout occured and link is stuck, reset (required transport layer for handling possible data loss) Debug.WriteLine("LINK - STUCK_TIMEOUT"); ActualFrameIndex = 0; ActualMessageId = 0; TkickMessageId = 0; TriggerTimeoutOccured(); ActualState = ModbusAsciiLinkState.IDLE; return; } }
/// <summary> /// Close bus connection /// </summary> /// <returns>true if success, false if error</returns> public bool Disconnect() { // Stop link thread LinkThread.Abort(); ActualState = ModbusAsciiLinkState.IDLE; return(PHY.Disconnect()); }
/// <summary> /// Open connection and access bus /// </summary> /// <returns>true if success, false if error</returns> public bool Connect() { if (PHY.Connect()) { // Start the link thread if connection was successful ActualState = ModbusAsciiLinkState.IDLE; LinkThread.Start(); return(true); } return(false); }
/// <summary> /// Task for processing received data running in thread /// </summary> private void ModbusAsciiLinkTask() { int threadDelay = 10; while (true) { Thread.Sleep(threadDelay); // Pop byte from receive ring buffer int value = PHY.Receive(); if (value != -1) { byte ReceivedByte = Convert.ToByte(value); switch (ActualState) { // Link is idle, wait for start character case ModbusAsciiLinkState.IDLE: if (ReceivedByte == ':') { // Start character received, start timeout timer and set state to receiving TkickMessageId = ActualMessageId; TimeoutCounter.Start(); // Reset reception buffer index ActualFrameIndex = 0; threadDelay = 0; ActualState = ModbusAsciiLinkState.RECEIVING; } break; case ModbusAsciiLinkState.RECEIVING: // Link is receiving a message if (ReceivedByte == '\n') { // Stop character received, stop timeout timer TimeoutCounter.Stop(); // Check data integrity and notify upper layer ProcessReceivedData(); // Set state to idle ActualState = ModbusAsciiLinkState.IDLE; threadDelay = 10; // Increment message id ActualMessageId++; break; } if (ReceivedByte == '\r') { // do not store CR character break; } if (ActualFrameIndex < ActualFrame.Length) { // Write received byte buffer ActualFrame[ActualFrameIndex++] = ReceivedByte; } // If buffer overflow occured, skip and wait for timeout break; default: break; } } } }