ModbusClient.cin
Fix some issues with sending and receiving packets ModbusTcp.cin Don't assume the connection is ready when TcpOpen says so. Wait for OnTcpOpen() to confirm
This commit is contained in:
		
							parent
							
								
									6ddb12d98f
								
							
						
					
					
						commit
						7704769468
					
				
					 2 changed files with 21 additions and 14 deletions
				
			
		| 
						 | 
					@ -586,7 +586,7 @@ void ModbusWriteRegisters(word address, long count, word values[])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// FC16: Write Multiple Registers (AOs)
 | 
						// FC16: Write Multiple Registers (AOs)
 | 
				
			||||||
	offset = 0;
 | 
						offset = 0;
 | 
				
			||||||
	while (count > 0 && (address + offset) < devEndAddr)
 | 
						while (count > 0 && (address + offset) > devEndAddr)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		addressO = address + offset;
 | 
							addressO = address + offset;
 | 
				
			||||||
		curCount = count > gMaxRegsPerWrite ? gMaxRegsPerWrite : count;
 | 
							curCount = count > gMaxRegsPerWrite ? gMaxRegsPerWrite : count;
 | 
				
			||||||
| 
						 | 
					@ -786,6 +786,15 @@ void _OnModbusReceive(dword socket, long result, dword address, dword port, byte
 | 
				
			||||||
			// Size of zero indicates that the socket was closed by the communication peer.
 | 
								// Size of zero indicates that the socket was closed by the communication peer.
 | 
				
			||||||
			writeDbg(ConnWarning, "OnModbusReceive: Socket closed by peer");
 | 
								writeDbg(ConnWarning, "OnModbusReceive: Socket closed by peer");
 | 
				
			||||||
			_ModbusDisconnect();
 | 
								_ModbusDisconnect();
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								for (long TxID : gQueueSent)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									writeDbg(ConnWarning, "OnModbusReceive: Moving 0x%04X back to pending queue", TxID);
 | 
				
			||||||
 | 
									memcpy(gQueuePending[TxID], gQueueSent[TxID]);	// Move back to pending queue
 | 
				
			||||||
 | 
									gQueueSent.Remove(TxID);
 | 
				
			||||||
 | 
									gQueuePending[TxID].Timeouts = 0;
 | 
				
			||||||
 | 
									gQueuePending[TxID].TimeoutTicks = 0;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
| 
						 | 
					@ -975,7 +984,6 @@ void _ModbusSend(byte buffer[], word length, word TxID)
 | 
				
			||||||
	memcpy(gQueuePending[TxID], qe);
 | 
						memcpy(gQueuePending[TxID], qe);
 | 
				
			||||||
	writeDbg(ConnDebug, "Appended packet 0x%04X to pending queue", TxID);
 | 
						writeDbg(ConnDebug, "Appended packet 0x%04X to pending queue", TxID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (gQueuePending.Size() == 1 && gQueueSent.Size() == 0 && gSocketState == OK)	// start timer if connection established
 | 
					 | 
				
			||||||
	_ModbusStartQueue();
 | 
						_ModbusStartQueue();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -983,10 +991,13 @@ void _ModbusSend(byte buffer[], word length, word TxID)
 | 
				
			||||||
// It is seperate because the network layer may want to start it when it delayed some messages (e.g. while waiting for an ARP response)
 | 
					// It is seperate because the network layer may want to start it when it delayed some messages (e.g. while waiting for an ARP response)
 | 
				
			||||||
// It gets called by _ModbusSend() and OnEthReceivePacket() in ModbusEil.cin
 | 
					// It gets called by _ModbusSend() and OnEthReceivePacket() in ModbusEil.cin
 | 
				
			||||||
void _ModbusStartQueue()
 | 
					void _ModbusStartQueue()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (gSocketState >= CLOSED && (gQueuePending.Size() > 0 || gQueueSent.Size() > 0))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		writeDbg(ConnDebug, "Starting Timer gtModbusRobin");
 | 
							writeDbg(ConnDebug, "Starting Timer gtModbusRobin");
 | 
				
			||||||
		setTimerCyclic(gtModbusRobin, 1);
 | 
							setTimerCyclic(gtModbusRobin, 1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// <-ModbusSend>
 | 
					/// <-ModbusSend>
 | 
				
			||||||
// This timer will handle the pending and sent queues.
 | 
					// This timer will handle the pending and sent queues.
 | 
				
			||||||
| 
						 | 
					@ -1047,9 +1058,9 @@ on timer gtModbusRobin
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Stop timer to reduce load and latency of first new packet
 | 
						// Stop timer to reduce load and latency of first new packet
 | 
				
			||||||
	if (gSocketState == ERROR || gQueueSent.Size() == 0 && gQueuePending.Size() == 0)
 | 
						if (gSocketState != OK || gQueueSent.Size() == 0 && gQueuePending.Size() == 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		writeDbg(ConnDebug, "gtModbusRobin: Stopping Timer");
 | 
							writeDbg(ConnDebug, "gtModbusRobin: Stopping Timer. Queue Sent: %d, Queue Pending: %d", gQueueSent.Size(), gQueuePending.Size());
 | 
				
			||||||
		this.Cancel();
 | 
							this.Cancel();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -105,13 +105,9 @@ word _ModbusConnectTo(dword remoteIp, word remotePort)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						gSocketState = CONNECTING;		// Don't set state OK because the Stack doesn't tell us WSAEWOULDBLOCK
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		writeDbg(ConnInfo, "_ModbusConnectTo: Successfully connected to server");
 | 
					 | 
				
			||||||
		gSocketState = OK;
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This method will be called when TcpSocket.Connect() had to defer the result (and returned WSAEWOULDBLOCK).
 | 
					// This method will be called when TcpSocket.Connect() had to defer the result (and returned WSAEWOULDBLOCK).
 | 
				
			||||||
// It checks whether the connection was opened successfully and sets the socket state accordingly
 | 
					// It checks whether the connection was opened successfully and sets the socket state accordingly
 | 
				
			||||||
| 
						 | 
					@ -208,7 +204,6 @@ word _ModbusSnd(byte buffer[], word length)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bin_to_strhex(buffer, str);
 | 
						bin_to_strhex(buffer, str);
 | 
				
			||||||
	writeDbg(ConnDebug, "_ModbusSnd: %s (Länge: %d)", str, length);
 | 
					 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	if (gSocket.Send(buffer, length) != 0)
 | 
						if (gSocket.Send(buffer, length) != 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -223,6 +218,7 @@ word _ModbusSnd(byte buffer[], word length)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// else: tough luck!
 | 
							// else: tough luck!
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						writeDbg(ConnDebug, "_ModbusSnd: %s (Länge: %d)", str, length);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue