Author Topic: Separate ZMODEM usage  (Read 2564 times)

Kolan

  • Newbie
  • *
  • Posts: 14
    • View Profile
Separate ZMODEM usage
« on: August 13, 2009, 08:58:51 am »
Is it possible to use TnrZModem component alone with out TnrComm? And if yes, are there any examples available?

I've found a ZModem.DataReceive method, but there is nothing said about in help.

Roman Novgorodov

  • Engineer
  • Administrator
  • Hero Member
  • *****
  • Posts: 994
  • we will win
    • View Profile
    • Forums.nrCommLib.Com
Re: Separate ZMODEM usage
« Reply #1 on: August 15, 2009, 01:35:26 pm »
Hello

You can try to use the following:
TnrZModem.DoProcessing() method for transmit incoming data from remote client to ZModem class and
You should handle TnrZModem.OnDataSend event for transmit bytes from ZModem to remote client.

Sorry if my answer is too late.

Roman Novgorodov
DeepSoftware llc - The professional components for Delphi/CBuilder/.NET. The high quality custom software development.
Forums.nrCommLib.Com - DeepSoftware Tech Support Forum.

Kolan

  • Newbie
  • *
  • Posts: 14
    • View Profile
Re: Separate ZMODEM usage
« Reply #2 on: August 17, 2009, 08:42:42 am »
Thanks Roman!

Can you provide OnDataSend event interface. Since this event is not described in help file I tried to compose it my self using IDE hint.
Code: [Select]
procedure ZModemDataSend(Sender: TObject; ptrBuffer: PAnsiChar;
      Len: Cardinal; flSyncro: Boolean; flHandled: Boolean);

But this interface is wrong, IDE says that: E2009 Incompatible types: 'Parameter lists differ'

Can you also, please, explain the meaning of params, especially flSyncro and flHandled.

Any additional information, examples etc would be great.

Roman Novgorodov

  • Engineer
  • Administrator
  • Hero Member
  • *****
  • Posts: 994
  • we will win
    • View Profile
    • Forums.nrCommLib.Com
Re: Separate ZMODEM usage
« Reply #3 on: August 18, 2009, 01:30:02 am »
Hello

The following handler sample should work:

procedure TForm1.nrZModem1DataSend(Sender: TObject; ptrBuffer: PAnsiChar;
  Len: Cardinal; flSynchro: Boolean; var flHandled: Boolean);
begin
  // code for data output ...
end;

Roman Novgorodov
DeepSoftware llc - The professional components for Delphi/CBuilder/.NET. The high quality custom software development.
Forums.nrCommLib.Com - DeepSoftware Tech Support Forum.

Kolan

  • Newbie
  • *
  • Posts: 14
    • View Profile
Re: Separate ZMODEM usage
« Reply #4 on: August 19, 2009, 07:07:55 am »
Thanks, and one more thing, where TIngnoreTypes type is declared?

This value is required for DoProcessing method.

Roman Novgorodov

  • Engineer
  • Administrator
  • Hero Member
  • *****
  • Posts: 994
  • we will win
    • View Profile
    • Forums.nrCommLib.Com
Re: Separate ZMODEM usage
« Reply #5 on: August 20, 2009, 05:31:28 pm »
Hello

You can use somthing like this:

Code: [Select]
uses nrclasses;

var it:TIgnoreTypes;

begin
  it := [];
  nrZMoedm.DoProcessing(data, len, it);
end;

Roman Novgorodov
DeepSoftware llc - The professional components for Delphi/CBuilder/.NET. The high quality custom software development.
Forums.nrCommLib.Com - DeepSoftware Tech Support Forum.

Kolan

  • Newbie
  • *
  • Posts: 14
    • View Profile
Re: Separate ZMODEM usage
« Reply #6 on: August 21, 2009, 09:51:47 am »
OK, it compiles now, thanks. But there are still problems...

I've created a tread that constantly read data from the port via FTDI Dxx2.dll. When data is got it is being forwarded to the ZModem:
Code: [Select]
procedure TFTDIUSBPortWrapper.PortDataReadEvent(Data: AnsiString);
var
  R: TIgnoreTypes;
begin
  ShowMessage(Data);
  R := [];
 {Если Z-модем активен, то полученые байты перенаправляются ему.}
  if FZModem.Active then
    FZModem.DoProcessing(@Data, Length(Data), R)
  else
    MyAnswerHandler(Data);
end;

And there is also a DataSend event handler.

Code: [Select]
procedure TFTDIUSBPortWrapper.ZModemDataSend(Sender: TObject;
  ptrBuffer: PAnsiChar; Len: Cardinal; flSyncro: Boolean; var flHandled: Boolean);
var
  Msg: AnsiString;
  I: Integer;
begin
  Msg := '';
  for I := 0 to Len - 1 do
    Msg := Msg + ptrBuffer[I];
  MySendCommand(Msg);
end;

ZModem gets data in PortDataReadEvent, but nothing happens. I tried to use logfile component to debug:
Code: [Select]
constructor TFTDIUSBPortWrapper.Create;
begin
  inherited;
  FUSBReadThread := nil;
  FnrLog := TnrLogFile.Create(nil);

  FZModem := TnrZModem.Create(nil);
  FZModem.OnAfterFileReceived := FileDownloadedEvent;
  FZModem.OnAfterFileSent := FileUploadedEvent;
  FZModem.Options := FZModem.Options + [zoOverwrite] - [zoCreateWithNewName];
  FZModem.OnDataSend := ZModemDataSend;
  [b]FZModem.Log := FnrLog;[/b]

 // FZModem.OnDataSend := ZModemDataSend;
end;

But it is empty. What it can mean?

Kolan

  • Newbie
  • *
  • Posts: 14
    • View Profile
Re: Separate ZMODEM usage
« Reply #7 on: August 21, 2009, 10:06:07 am »
Forgot to say, ZModemDataSend is also never called.

Roman Novgorodov

  • Engineer
  • Administrator
  • Hero Member
  • *****
  • Posts: 994
  • we will win
    • View Profile
    • Forums.nrCommLib.Com
Re: Separate ZMODEM usage
« Reply #8 on: August 22, 2009, 03:58:46 am »
Hello

I don't see anywhere the following code:

Code: [Select]
FZModem.Active := True;

Roman Novgorodov
DeepSoftware llc - The professional components for Delphi/CBuilder/.NET. The high quality custom software development.
Forums.nrCommLib.Com - DeepSoftware Tech Support Forum.

Kolan

  • Newbie
  • *
  • Posts: 14
    • View Profile
Re: Separate ZMODEM usage
« Reply #9 on: August 25, 2009, 08:03:58 am »
TFTDIUSBPortWrapper has a parent TCustomPortWrapper.

When somebody sends command (a linux command) it is first processed by the parent:

Code: [Select]
procedure TCustomPortWrapper.SendCommandFromQueue;
var
  StringCommand: AnsiString;
begin
 {Если в очереди есть команды, то послать следующую.}
  if FCommandsQueue.Count > 0 then
  begin
   {Скомпоновать команду.}
    StringCommand := FCommandsQueue.Peek.CommandForDevice+#13;

   {Очистить переменную в которую будет накапливаться ответ.}
    FTempPackage := '';
    if FFilter <> nil then
      MySendCommand(FFilter.FilterCommand(StringCommand))
    else
      MySendCommand(StringCommand);

   {Включить тайм-аут таймер.}
    FTimeOutTimer.Enabled := True;

    if FCommandsQueue.Peek.LinuxCommand = lcDownloadFileViaZModem then
    begin
      MyDownloadFile((FCommandsQueue.Peek as TFileDownloadCommand).DirectoryToSaveFile);
    end;
  end;
end;

Case «if FCommandsQueue.Peek.LinuxCommand = lcDownloadFileViaZModem then» means that when there is a «lsz» in command the MyDownloadFile abstract method is called.


MyDownloadFile is implemented in descendant:

Code: [Select]
procedure TFTDIUSBPortWrapper.MyDownloadFile(const DirectoryToSaveFile: string);
begin
  inherited;
  FZModem.DefaultPath := DirectoryToSaveFile;
  FZModem.Active := True;
end;

Where FZModem.Active := True; is eventually done.