1

I am using TComPort (4.11f) in a simple Delphi 10.3 console application, see below, but I do not get any data.

Using the same code in a VCL application works fine. Any thoughts?

My guess is that I am not connecting the ComDataPacket1 and ComPort1 objects correctly. However, I could not find another way to do it.

program commapp;

{$APPTYPE CONSOLE}

uses
  Vcl.Forms, CPort, CPortCtl, system.sysutils, classes, Windows;

{$R *.res}

var
  ComPort1: TComPort;
  ComDataPacket1: TComDataPacket;
  Sender: TObject;
  Str: string;

type
  TEventHandlers = class
    class procedure ComDataPacket1Packet(Sender: TObject; const Str: string);
  end;

class procedure TEventHandlers.ComDataPacket1Packet(Sender: TObject; const Str: string);
begin
  WriteLn('Inside the proc with ' + str);
end;

begin // Main program                 ///
  ComPort1 := TComPort.Create(nil);  // create the    comm
  ComDataPacket1 := TComDataPacket.Create(nil);
  ComPort1.BaudRate := br115200;                 // set parameters
  ComPort1.Port     := 'COM3';
  ComPort1.Parity.Bits := prNone;

  ComDataPacket1.Size := 33;
  ComDataPacket1.ComPort  := ComPort1;
  ComDataPacket1.OnPacket := TEventHandlers.ComDataPacket1Packet;
  ComDataPacket1.StartString := '';
  ComDataPacket1.StopString := '';

  if ParamCount = 0 then // no paramters passed enter menu
  begin
    ComPort1.ShowSetupDialog; // Open the port settings.
    ComPort1.Open;
    ComPort1.WriteStr('b') ;  // Send the command to start sending data
    WriteLn('After sending an b I get  :  ' + str); 
    ReadLn;
  end;

  // release the components
  ComDataPacket1.Free;
  ComPort1.Free;
end.
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
na38
  • 109
  • 2
  • 12
  • Do you use **class** procedure as event handler in VCL application too? And what is purpose of datapacket with empty sentinels? – MBo Dec 30 '18 at 16:12
  • No that is one difference. If I do not wrap the proc in a class I get an error per the link below. So I have wrapped it in a class to make the compiler happy. https://stackoverflow.com/questions/11314641/method-pointer-and-regular-procedure-incompatible The empty start and stop strings did not make any difference if I leave in or take out and they are in both versions. – na38 Dec 30 '18 at 16:21
  • But you can use usual method without `class` (but with creating `TEventHandlers` instance). – MBo Dec 30 '18 at 16:26
  • true, but taking the class out and creating an instance of TEventHandlers and attaching it to the Comport did not make any difference. – na38 Dec 30 '18 at 16:44
  • Global `str` is never assigned in code. Main problem is that you close the program before the message is received. – LU RD Dec 30 '18 at 17:08
  • `class` methods work just fine as event handlers, I do it all the time in Console test apps. I'm betting the real problem is that the console code shown doesn't have a message loop to process activity from the com port to trigger the events – Remy Lebeau Dec 30 '18 at 17:40
  • 2
    `ReadLn` is not sufficient to wait for an event to be processed in a console application. Like @RemyLebeau say, you will have to implement a message loop for the event to be processed. – LU RD Dec 30 '18 at 19:45
  • Hi Remy, I assume you are talking about something along the lines of what you have here https://stackoverflow.com/questions/11364434/delphi-7-handling-events-in-console-application-tidirc. – na38 Dec 30 '18 at 20:16
  • @user3338048 not quite. That example was about implementing a thread synchronization loop, not a message loop. Your code does not involve threads. – Remy Lebeau Dec 31 '18 at 06:55
  • If I remember correctly TComPort has a SyncMethod property which defaults to smThreadSync. I think that requires a message loop to work. Try to set it to smNone which should directly call the event methods. – dummzeuch Dec 31 '18 at 12:13

1 Answers1

2

Try running a message loop while waiting for the OnPacket event to fire, eg:

program commapp;

{$APPTYPE CONSOLE}

uses
  Vcl.Forms, CPort, CPortCtl, System.SysUtils,
  System.Classes, Winapi.Windows, System.SyncObjs;

{$R *.res}

var
  ComPort1: TComPort;
  ComDataPacket1: TComDataPacket;
  DataEvent: TEvent;
  hEvent: THandle;
  DataStr: string;

type
  TEventHandlers = class
    class procedure ComDataPacket1Packet(Sender: TObject; const Str: string);
  end;

class procedure TEventHandlers.ComDataPacket1Packet(Sender: TObject; const Str: string);
begin
  WriteLn('Inside the proc with ' + Str);
  DataStr := Str;
  DataEvent.SetEvent;
end;

begin // Main program
  ComPort1 := TComPort.Create(nil); // create the comm
  ComDataPacket1 := TComDataPacket.Create(nil);
  DataEvent := TEvent.Create;

  ComPort1.BaudRate := br115200; // set parameters
  ComPort1.Port := 'COM3';
  ComPort1.Parity.Bits := prNone;

  ComDataPacket1.Size := 33;
  ComDataPacket1.ComPort := ComPort1;
  ComDataPacket1.OnPacket := TEventHandlers.ComDataPacket1Packet;
  ComDataPacket1.StartString := '';
  ComDataPacket1.StopString := '';

  if ParamCount = 0 then // no paramters passed enter menu
  begin
    ComPort1.ShowSetupDialog; // Open the port settings.
  end;

  ComPort1.Open;
  ComPort1.WriteStr('b') ; // Send the command to start sending data

  hEvent := DataEvent.Handle;
  repeat
    case MsgWaitForMultipleObjects(1, hEvent, False, INFINITE, QS_ALLINPUT) of
      WAIT_OBJECT_0: Break;
      WAIT_OBJECT_0 + 1: Application.HandleMessage; // or Application.ProcessMessages()
      WAIT_FAILED: RaiseLastOSError;
    end;
  until False;

  WriteLn('After sending an b I get : ' + DataStr);
  ReadLn;

  // release the components
  DataEvent.Free;
  ComDataPacket1.Free;
  ComPort1.Free;
end.
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thanks for the example code. Running it I get an error message on MsgWaitForMultipleObjects(1, DataEvent.Handle, False, INFINITE, QS_ALLINPUT) stating "Constant object cannot be passed as var parameter", referring to DataEvent.Handle I believe. I looked this up and tried to pass it a pointer to no avail and also tried setting that parameter as a regular THandle. The latter works but no longer attached to the event I think so no data. – na38 Dec 31 '18 at 18:26
  • @user3338048 sorry about that. I tweaked my answer. – Remy Lebeau Dec 31 '18 at 18:43
  • thanks for the edits, works perfectly. I have accepted the answer. – na38 Jan 01 '19 at 15:07