Geepster - it is COM emulator, isn't it? It would help me with testing software, wouldn't it?
And one more question - do you have example of using class you sent a link? And I can't see something like 'Write' function, just 'Read'.
Yep. The com0com will install virtual COM ports in pairs. Each pair is connected to each other. So you end up with COM8 and COM9. You run a server on one port and a client on the other. The difference between a server and a client is which one remains in a "read locked" state. ie: Waiting for requests.
RE: Why no write method. If you look at the code for SerWrite(), you will see it uses the function WriteFile(). THandleStream also uses this command, so there was no need to override the Write method for the TStream.
RE: Example. Here is the TSerialStream unit again:
unit SerialStream;
{$mode objfpc}{$H+}
interface
uses
Classes, Serial, SysUtils;
type
TSerialStream = class(THandleStream)
public
constructor Create(const ADevice: string; const ABaud: integer;
const AByteSize: integer = 8; const AParity: TParityType = NoneParity;
const AStopBits: integer = 1);
destructor Destroy; override;
public
function Read(var ABuffer; ACount: longint): longint; override;
end;
implementation
constructor TSerialStream.Create(const ADevice: string; const ABaud, AByteSize: integer;
const AParity: TParityType; const AStopBits: integer);
begin
inherited Create(SerOpen(ADevice));
if Handle = 0 then begin
raise Exception.Create('Unable to open serial device');
end;
SerSetParams(Handle, ABaud, AByteSize, AParity, AStopBits, []);
end;
destructor TSerialStream.Destroy;
begin
SerClose(Handle);
inherited;
end;
function TSerialStream.Read(var ABuffer; ACount: longint): longint;
begin
Result := SerReadTimeout(Handle, byte(ABuffer), ACount, High(longint));
end;
end.
Here is a basic server which just reads a string message and returns it as uppercase.
program Server;
uses
SerialStream;
{$R *.res}
var
GServerStream: TSerialStream;
GData: string;
begin
GServerStream := TSerialStream.Create('COM8', 2400);
while True do begin
GData := GServerStream.ReadAnsiString;
GServerStream.WriteAnsiString(upcase(GData));
end;
end.
Here is a client:
program Client;
uses SerialStream;
{$R *.res}
var
GClientStream: TSerialStream;
begin
GClientStream := TSerialStream.Create('COM9', 2400);
while True do begin
GClientStream.WriteAnsiString('This is an example of remoting the uppercase function via RS232');
WriteLn(GClientStream.ReadAnsiString);
end;
end.
You will run into a number of problems like, what happens when the server is not responding? ie: timeouts. You can write your own timeouts or adjust the timeouts for the handle via Windows functions.
Apart from that, its pretty easy. WriteAnsiString/ReadAnsiString can also handle binary data. Use SetString() to convert a record to a string, and send it via WriteAnsiString().
For speed incompatible devices, you may require echoing, or some other handshaking. I used echoing because the TRS80 only has 3 RS232 wires and is very slow compared to the PC, so, each byte needed to "hold" the PC to prevent the PC from sending too fast.